Embedded Systems PIC16F84A Sample Programs Eng. Anis Nazer First Semester 2017-2018
Development cycle (1) Write code (2) Assemble / compile (3) Simulate (4) Download to MCU (5) Test
Inputs / Outputs PIC16F84A has 13 pins for inputs/outputs can be configured as inputs or outputs Input data from the outside world to the PIC Output data from the PIC to the outside world two ports: PORTA: 5 bits PORTB: 8 bits
Input / Output Special function registers TRISA and TRISB to configure the pin state as input or output 0 in TRIS register pin is output 1 in TRIS register pin is input Ex. if you store b'0110 1101' in TRISB then: RB0, RB2, RB3, RB5, RB6 are inputs RB1, RB4, RB7 are outputs Ex. What is the effect of the following instructions: BSF MOVLW MOVWF STATUS, RP0 0x3C TRISB
Inputs / outputs The state of the ports are mapped into registers PORTA and PORTB to read the state of an input pin, read the value stored in the register to write a value to an output pin, store the value in the register Address of PORTA: 0x05 (Bank 0) Address of PORTB: 0x06 (Bank 0) Address of TRISA: 0x85 (Bank 1) Address of TRISB: 0x86 (Bank 1) How do you select bank 0 or bank 1?
Example Write code to set the pins of port A as inputs and port B as outputs BSF STATUS, RP0 ; select bank 1 MOVLW 0xFF MOVWF TRISA CLRF TRISB
Example Write code to read the state of port A into W register BCF STATUS, RP0 ; select bank 0 MOVF PORTA, 0 Write code to put 0xA7 on port B BCF STATUS, RP0 ; select bank 0 MOVLW 0xA7 MOVWF PORTB
Example Assume you have a switch and an LED, the switch and LED are connected as shown, Write a program that turns the LED on if the switch is closed, and turns the LED off if the switch is not closed. Vdd RB0 RA0 LED PIC16F84A
Example Steps: 1) set RA0 as output, and RB0 as input 2) read value on RB0: if RB0 == 0 turn LED off if RB0 == 1 turn LED on 3) repeat (2)
Example Cont. BSF STATUS, RP0 ; select bank 1 BCF TRISA, 0 ; set RA0 as output BSF TRISB, 0 ; set RB0 as input BCF STATUS, RP0 ; select bank 0 loop BTFSC PORTB, 0 ; if B0 is 0 don't set A0 BSF PORTA, 0 BTFSS PORTB, 0 BCF PORTA, 0 GOTO loop
Example Same example but with two switches and two LEDs BSF STATUS, RP0 ; select bank 1 BCF TRISA, 0 ; set RA0, RA1 as output BCF TRISA, 1 BSF TRISB, 0 ; set RB0, RB1 as input BSF TRISB, 1 BCF STATUS, RP0 ; select bank 0 loop BTFSC PORTB, 0 ; if B0 is 0 don't set A0 BSF PORTA, 0 ; BTFSS PORTB, 0 ; if B0 is 1 don't clear A0 BCF PORTA, 0 BTFSC PORTB, 1 BSF PORTA, 1 BTFSS PORTB, 1 BCF PORTA, 1 ; same for B1 GOTO loop
Alarm System We want to design an alarm system, it is composed of a motion detector, an enable switch, and a buzzer. Assume that: The motion detector gives a logic 1 if motion is detected. The buzzer is turned on if it receives a logic 1 The system is enabled if the switch is closed.
Alarm System Vcc Motion detector RA0 RA1 RB0 Buzzer PIC16F84A
Alarm System Start Flow chart: is system enabled? false buzzer off true is motion detected? true false buzzer on
Alarm System - Program #include "p16f84a.inc" ORG 0x000 BSF STATUS, RP0 ; select inputs and outputs BSF TRISA, 0 BSF TRISA, 1 BCF TRISB, 0 BCF STATUS, RP0 BCF PORTB, 0 ; initially, turn the buzzer off main BTFSS PORTA, 1 ; is system enabled? GOTO buzzer_off ; no, buzzer off BTFSC PORTA, 0 ; is motion detected? BSF PORTB, 0 ; yes, turn buzzer on GOTO main buzzer_off BCF PORTB, 0 ; disable the system GOTO main END
Example Assume that 8 LEDs are connected to the pins of PORTB, study the following code and explain its function #include "p16f84a.inc" count EQU 0x33 ORG 0x000 main BSF CLRF BCF STATUS, RP0 TRISB STATUS, RP0 start MOVLW D'100' MOVWF count CLRF PORTB next INCF PORTB, 1 DECFSZ count, 1 GOTO next CLRF PORTB GOTO start end
Subroutines Like functions in high level language executed using a CALL instruction, a return will go back to the instruction written after the call instruction two return instructions: RETURN RETLW : returns and stores a value in W reg Why is it useful?
Subroutine Write a subroutine that multiplies the value stored in location 0x20 by 3, and store the result in W register mult3 MOVF 0x20, 0 ADDWF 0x20, 0 ADDWF 0x20, 0 RETURN
Calling the Subroutine A program that uses the previous subroutine X EQU 0x20 Y EQU 0x21 ORG 0x000 GOTO start mult3 MOVF X, 0 ADDWF X, 0 ADDWF X, 0 RETURN start MOVLW D'23' MOVWF X CALL mult3 MOVWF Y GOTO start END
Software Delay To achieve a delay, execute a number of instructions that do nothing Ex. counter EQU 0x0C MOVLW D'10' MOVWF counter loop NOP DECFSZ counter, 1 GOTO loop How many instruction cycles are executed by the code?
Example: Delay Write a delay subroutine that executes 200 instruction cycles delay MOVLW D'48' ; 1 instruction cycle MOVWF counter ; 1 loop NOP ; 1 DECFSZ counter, 1 ; 1 or 2 GOTO loop ; 2 NOP ; 1 NOP ; 1 NOP ; 1 RETURN ; 2 instruction cycle count = 1+1+ ( 1+1+2 )*47 + (1+2) + 1+1+1+2 = 198 loop last iteration NOPs
Delay Assume that the clock frequency is 10KHz, how much time does the above delay subroutine take? each pulse takes 1/10K = 0.1ms instruction cycle takes 4 clock cycles so, each instruction takes 4*0.1m = 0.4ms so the delay subroutine above will take 200*0.4=80ms
Example: Delay Write a program to result in the execution of 2000 instruction cycles call the above subroutine 10 times cnt EQU 0x0C cnt1 EQU 0x0D ORG 0x00 start MOVLW D'10' MOVWF cnt1 loop1 CALL delay DECFSZ cnt1,1 GOTO loop1 delay loop MOVLW D'48' MOVWF cnt NOP DECFSZ cnt, 1 GOTO loop NOP NOP NOP RETURN END
Moving light Example Assume that 8 LEDs are connected to PORTB Assume that the clock frequency is 10KHz Write code to light LED at RB0 for 0.5 seconds then LED at RB1 for 0.5 seconds, then LED at RB2 for 0.5 seconds, etc... hint: use rotate instruction
Moving light Example Circuit:
Moving light Example Steps: 1) Store 0x01 in PORTB this will turn on the LED connected to RB0 2) delay for 0.5 seconds 3) rotate PORTB to the left this will turn off the LED and will turn on the next LED 4) GOTO step (2)
Moving light Example Calculations: delay for 0.5 second clock frequency is 10kHz instruction frequency = 10k/4 = 2.5k IPS instruction cycle time = 1/2.5K = 0.4ms so, we need 0.5 / 0.4m = 1250 instructions to get a delay of 0.5 second
Moving light Example delay loop executes 1250 instruction cycles 1250 = 5 x 250 so, each iteration executes 5 instructions, and the loop repeats 250 times counter EQU 0x0c delay MOVLW D'250' ; delay loop MOVWF counter loop NOP NOP DECFSZ counter, 1 GOTO loop RETURN
Moving light Example #include "P16F84A.INC" counter EQU 0x0c ORG 0x00 BSF STATUS, RP0 ; select bank 1 CLRF TRISB ; set portb as output BCF STATUS, RP0 ; select bank 0 MOVLW 0x01 ; light up led at RB0 MOVWF PORTB BCF STATUS, C ; clear carry flag loop1 CALL delay RLF PORTB, 1 ; rotate left GOTO loop1 delay MOVLW D'250' ; delay loop MOVWF counter loop NOP NOP DECFSZ counter, 1 GOTO loop RETURN END
Moving light Example 2 Assume that 8 LEDs are connected to PORTB Assume that the clock frequency is 10KHz Write code to light LED at B0 then LED at B1 after 0.5 seconds, then light B2 after 0.5 seconds, etc, when the light reaches B7, delay for 0.5 seconds then light B6 then delay for 0.5 seconds, then light B5... etc i.e. make the light bounce...:)
Lookup Table Lookup table: is a block of data stored in program memory A lookup table can be used to implement a mathematical function, generate output patterns...etc In PIC a lookup table is implemented using a CALL and RETLW, with a computed jump PCL register holds the least significant byte of the program counter
Lookup Table what happens if we execute: ORG 0x111 MOVLW 0x02 ADDWF PCL, 1 What is the address of the instruction that will be executed after the ADDWF? PCL + 2 0x113 + 2 = 0x115 computed jump
Lookup tables Write a program that will take the input at PORTA as x (in binary) and calculate f(x) and display output on PORTB (in binary) where f x =x 2 2 x f(x) 0 2 1 3 2 6 3 11 4 18...... 15 227
Lookup table ORG BSF CLRF TRISB MOVLW 0xFF 0x00 STATUS, RP0 MOVWF TRISA BCF STATUS, RP0 loop MOVF PORTA, 0 ANDLW 0x0F CALL func MOVWF PORTB GOTO loop func ADDWF PCL, 1 RETLW D'2' RETLW D'3' RETLW D'6' RETLW D'11' RETLW D'18' RETLW D'27' RETLW D'38' RETLW D'51' RETLW D'66' RETLW D'83' RETLW D'102' RETLW D'123' RETLW D'146' RETLW D'171' RETLW D'198' RETLW D'227'