Serial Communication With PIC16F690 by Houston Pillay
Serial Communication With PIC16F690 by Houston Pillay
Serial Communication With PIC16F690 by Houston Pillay
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Author: Houston Pillay
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Brief Functional Description:
; This program, for the PIC16F690, receives and transmits ASCII characters serially. Four seven
; segment displays are used. Initially, the segments will be blank. When a character is received,
; it is displayed on the right most display. When another character is sent, the characters that
; are already on the displays will shift left and allow the new character to be displayed on the
; right most display. When a character falls off the left most display as a result of the shifting
; ,it is transmitted serially.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; How it is used:
; -The four seven segment common anode displays must be connected to PortC. The decimal point will
; be connected to Pin7, g to Pin6, f to Pin5, e to Pin4, d to Pin3, c to Pin2, b to Pin1, a to Pin0
;
; -The common anodes are connected to the +5V supply rails via NPN transistors. There are four control
; lines for the four displays. Display 1: PortB,Pin4; Display 2: PortB,Pin6; Display 3: PortA,Pin2
; Display 4: PortA,Pin5. These control lines must be connected to the base of the transistors. The
; emitter must be connected to the common anode. The transistors are essential because the
; microcontroller cannot safely source current from one pin for 7 leds simultaneuosly.
;
; -The transmit pin is located on PortB,Pin7, and the receive pin is located on PortB,Pin5. Testing
; can be done through a computer that has a serial port. You must have a MAX232 chip to convert the
; TTL levels of the PIC to voltage levels, that of the computer. Connect Pin10 of the MAX232 to the
; transmit pin of the PIC, and connect Pin 9 of the MAX232 to the receive pin of the PIC. Pin 7 of
; the MAX232 must be connected to Pin2 of the DB9 female connecter, connect Pin 8 of the MAX232 to
; Pin3 of the DB9 female connector. The connector must also be grounded on Pin4.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Registers used:
;
; -Seg1,Seg2,Seg3,Seg4: Used to store values for Display1,2,3 and 4.
; -w_temp:Used to save w register before entering an interrupt service routine.
; -s_temp: Used to store the Status register before entering an interrupt service routine.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Detailed Design Description:
; There are two indentifiable solutions. One through software and the other,hardware. Software would
; entail polling. We would have to continually check the receive pin for incoming data but this is a
; time waisting procedure. The selected approach is through Hardware. This hardware is called the USART.
; It is interrupt driven meaning that when data is sent to the receive pin, an interrupt is generated.
; There is no time waisted waiting for data. 6 Functional Modules are used:
;
; -1. Disp4Multiplex: This module controlls the seven segment display procedures. It is used to drive four
; displays. The module is called as an interrupt service routine. It uses Timer0 to generate an interrupt
; every 4ms. Each time this module is called a value is displayed on one of the four displays. This is done
; sequentially at over 100 times a second. At this rate, it looks as if all segments are on simultaneously.
;
; -2. RxTxAsciiChar_USART: This module controlls the reception and transmission of ASCII characters. This
; module is called as an interrupt which is generated whenever data is sent to the receive pin of the
; microcontroller. A detailed description is available in the module.
;
; -3. Ascii_ErrorChk: This module checks the validity of the ASCII value being received. The intended range
; is from A-Z and 0-9. The module will ensure that the incoming value is consistent with the range.Detailed
; information is provided in the module
;
; -4. Disp_Update: This module simply updates the displays in a rolling fashion, whilst also placing the
; "fallen" value into a register. This register will be used by module 2 to transmit the character.
; The program waits in an infinite loop for an interrupt to begin. Once an interrupt has occured, it first
; checks to see which interrupt has occured. A timer interrupt or a USART interrupt? If a timer interrupt
; has occured, module 1 will come into effect. If a USART interrupt had occured, then first module 2 will
; be executed which receives the incoming ASCII character from the receive pin. Before transmission begins
; within this module, module 3 is called to check the validity of the character. If the character is ok
; the displays will be updated via module 4 and transmission will begin but if the character is invalid,
; the whole ISR will be exited.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Assembler Directives
__CONFIG _CP_OFF & _CPD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF &
_FCMEN_OFF & _IESO_OFF
;PIC Control Bit Settings
list p=16F690 ;Defining processor in use
#include <p16F690.inc>
errorlevel -302
org 0x00
goto Begin ;Reset Vector
org 0x04
call save ;Before any interrupts occur,the present state of the microcontroller is saved
banksel PIR1
btfsc PIR1,RCIF ;Checking to see if interrupt is that of UART
call RxTxAsciiChar_USART
;Register Definitions
banksel INTCON
movlw b'11100000'
movwf INTCON ;Enable Global Interrupts, Enable Peripheral Interrupts,Enable TMR0 Overflow Interrupt
banksel STATUS
return
save ;Code segment used to save micro registers before entering interrupt
banksel STATUS
movwf w_temp ; Save W register
swapf STATUS,0 ; Swap command used to store STATUS into w since it does not affect the
;STATUS register
clrf STATUS
movwf s_temp ; Save STATUS register
return
load ;Code segment used to load micro registers when it exits an ISR
swapf s_temp,0
movwf STATUS
swapf w_temp,1
swapf w_temp,0
return
clrf count
movlw 0x5B
movwf Seg4 ;Loading value to produce a blank display on startup for display 4
movlw b'10001000'
movwf select ;Initializing the select file register used to multiplex displays
return
Init_Display
banksel ANSEL ;This code sets up the microcontroller for digital i/o
clrw
movwf ANSEL
movwf ANSELH
banksel TRISC
movlw b'10000100' ;Set the Timer0 prescaler to 32
movwf OPTION_REG
movlw 0x00
movwf TRISC ;Setting PortC as output
bcf TRISB,4 ;Setting PortB,pins 4 and 6 to output
bcf TRISB,6
movlw 0x00
movwf TRISA ;Setting PortA pins as output
return
Init_UART
banksel TXSTA
movlw b'00100100' ;Transmit enable, High Baud Rate Select
movwf TXSTA
banksel RCSTA
movlw b'10010000' ;Serial Port Enable, Continuous Receive
movwf RCSTA
return
#include Disp4_Multiplex.asm
#include Disp_Update.asm
#include Ascii_ErrorChk.asm
#include RxTxAsciiChar_USART.asm
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Disp4Multiplex;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Author: Houston Pillay
; Student Number: 206514467
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functional Description:
;
; Disp4Multiplex: This module controlls the seven segment display procedures. It is used to drive four
; displays. The module is called as an interrupt service routine. It uses Timer0 to generate an interrupt
; every 4ms. Each time this module is called a value is displayed on one of the four displays. This is done
; sequentially at over 100 times a second. At this rate, it looks as if all segments are on simultaneously.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Registers Used:
; disp1_: Module's own file register to hold the value for display 1
; disp2_: As above but holds display2
; disp3_: As above but holds display3
; disp4_: As above but holds display4
; select: This register is used by the PIC to be able to decide which display must be switched on
; during the display multiplexing.
; -comple: This register is used to store the complemented value of the results from the jump table.
; -segsave: This register holds the jump parameter for the jump table while tests are being performed on it.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Register Definitions
Disp4_Multiplex
movlw .130 ;Setting the timer for an interrupt to occur 4ms later
movwf TMR0
btfsc select,0 ;This code segment checks which display needs to be turned on
goto DoFirst
btfsc select,1
goto DoSecond
btfsc select,2
goto DoThird
btfsc select,3
goto DoFourth
DoFirst
call Clrports_Load30 ;Clear ports and loads hex 30 into the w register
subwf disp1_,0 ;Subtracting 30 from the ASCII input to establish the correct jump parameter
;for the look up table
pagesel segments
call segments
movwf comple
comf comple,0 ;Complementing the value from the look up table since the table is designed
;for use with common cathode displays
movwf PORTC
bsf PORTB,4 ;Setting the correct control line for display 1
bcf PORTB,6
bcf PORTA,2
bcf PORTA,5
goto Exit
;return
DoSecond
call Clrports_Load30
subwf disp2_,0
call segments
movwf comple
comf comple,0
movwf PORTC
bcf PORTB,4
bsf PORTB,6 ;Setting the correct control line for display 2
bcf PORTA,2
bcf PORTA,5
goto Exit
;return
DoThird
call Clrports_Load30
subwf disp3_,0
call segments
movwf comple
comf comple,0
movwf PORTC
bcf PORTB,4
bcf PORTB,6
bsf PORTA,2 ;Setting the correct control line for display 3
bcf PORTA,5
goto Exit
;return
DoFourth
call Clrports_Load30
subwf disp4_,0
call segments
movwf comple
comf comple,0
movwf PORTC
bcf PORTB,4
bcf PORTB,6
bcf PORTA,2
bsf PORTA,5 ;Setting the correct control line for display 4
goto Exit
;return
Exit
return
segments
movwf segsave
addlw LOW segmentss ; Adding lower 8 bits of table to w
movlw HIGH segmentss ; Retrieving high byte of table
skpnc ;
addlw 1 ; If a carry occured then increment to access the new page
movwf PCLATH ; Store to the upper byte of the Program counter
movf segsave,0 ; Restore the jump parameter
RxTxAsciiChar_USART
Rx_ISR ;Initial routine used to catch the received data from RCREG
movf RCREG,0 ;Extracting the data from the UART receive register
movwf rxtxasctemp
call Ascii_ErrorChk ;Checking the validity of the incoming value
btfss TestInd,1 ;If an invalid key has been pressed,the PCL will skip to the return statement
goto Char_Valid
movlw 0x05 ;We must decrement count to allow transmission to occur but we also need,
subwf count,0 ;to check that count is'nt still less than five.
btfsc STATUS,Z
decf count,1
return
Char_Valid ;After a character has been deemed valid,this alternate routine will then update the
;display and transmit a valid character
btfss TestInd,2 ;Checking to see if character was lower case,if it was,then value already loaded into Rx_Data
call normload
movlw 0x05 ;This code segments checks to see if count has the value 5,
subwf count,0 ;when it is then that means the initial character has fallen,
btfsc STATUS,Z ;off left most display and we are ready to now transmit
call Tx_ISR
return
Tx_ISR
return
normload ;This routine will pass the value from the UART receive register directly into Rx_Data
movf rxtxasctemp,0
movwf Rx_Data
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Ascii_ErrorChk;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Author: Houston Pillay
; Student Number: 206514467
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function Description:
;
; This module handles error checking. Ascii characters wanted are from 0-9,A-Z. Checks are done to make sure this
; input is consistent with this range. Lower case inputs are transformed into upper case outputs. It first checks
; if the value is higher or lower than 0x5A. If it is lower then it checks if the value is lower than 0x30,if it is
; higher then no changes will occur and the module will be exited, else the module will indicate an out of range
; error through the register TestInd. If the value is higher than 0x5A it means one of two things..either the value
; is between 0x5A and 0x7A or it is completely out of range. It then checks if the value is lower than 0x7A. If it
; is not, then the value is out of range and this is indicated through the register TestInd. If it is lower, this
; means that a lower case character has been entered and the routine "setnew" will be called to get the
; corresponding Upper Case character after which the module will be exited.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Registers Used:
; TestInd: Bit one used to indicate if an input is invalid
; Bit two used to indicate that a lower case character has been entered
; asc_echktemp: Module's own file register to hold the ASCII value to be tested.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Register Definitions
Ascii_ErrorChk
bcf TestInd,1 ;File register used to indicate whether an invalid key has been pressed or not
bcf TestInd,2 ;File register used to indicate whether a lower case key has been pressed or not
test_small ;This routine checks to see if ASCII value is greater than 0x5A
movlw 0x5A
subwf asc_echktemp,0
btfsc STATUS,C ;If the ASCII value is greater than 0x5A, the carry flag is set
goto test_upper ;If ASCII > 0x5A, then we need to check if it is higher than 0x7A
goto test_lower ;Value is not higher than 0x5A, but we need to check if it is lower than 0x30
test_upper ;This routine checks if ASCII value is greater or lower than 0x7A
movlw 0x7B
subwf asc_echktemp,0
btfss STATUS,C
goto setnew ;If value is less than 0x7A, this means that a lower case key has been pressed
bsf TestInd,1 ;If value is greater than 0x7A, this means that the value entered is out of range
return
test_lower ;This routine checks to see if ASCII value is lower than 0x30
movlw 0x30
subwf asc_echktemp,0
btfsc STATUS,C
return
bsf TestInd,1 ;If the value is lower than 0x30,this means the value entered is out of range
return
setnew ;This routine will check if ASCII values corresponding to those between 'Z' and 'a' had been entered
movlw 0x20 ;This segment will be executed if the above checks have failed, therefore the
character is lower case
subwf asc_echktemp,0 ;Lower Case ASCII value - 20 = Higher Case ASCII value
movwf Rx_Data
bsf TestInd,2 ;This indicates that a lower case character has been pressed
Return
inbetweens
bsf TestInd,1 ;This indicates that an "inbetween character" has been pressed, therefore invalid
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Disp_Update ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Author: Houston Pillay
; Student Number: 206514467
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functional Description:
; This module is designed to shift characters right to left on four seven segment displays.
; A rippling effect is implemented whereby segment4 is pushed to an outgoing variable, segment 3
; is pushed to segment 4, then segment 2 is pushed to segment 3, then segment 1 is pushed to
; segment 2 and finally an incoming value Rx_Data is pushed to segment 1.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Registers Used:
; disp1: Module's own file register to hold the value for display 1
; disp2: Module's own file register to hold the value for display 2
; disp3: Module's own file register to hold the value for display 3
; disp4: Module's own file register to hold the value for display 4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Register Definitions
Disp_Update
movf disp4,0
movwf Tx_Data ;"Fallen" character passed into Transmit Register in module RxTxAsciiChar_USART
movf Rx_Data,0 ;Value from receive register from RxTxAsciiChar_USART pushed onto display 1
movwf Seg1
return