;************************************************** ; Pic by example ; RS232IO.ASM ; ; (c) 2004, Sergio Tanzilli ; http://www.tanzilli.com ;************************************************** PROCESSOR 16F84A RADIX DEC INCLUDE "P16F84A.INC" ;Suppress the following MPASM warning message [# 302]: ;"Register in operand not in bank 0. Ensure that bank bits are correct" ERRORLEVEL -302 ;Flag configuration __CONFIG 3FF1H ;RS232 lines TX equ 0 ;Tx data RX equ 1 ;Rx data ;I/O lines on PORTB LED1 equ 0 LED2 equ 1 LED3 equ 2 LED4 equ 3 SWITCH1 equ 4 SWITCH2 equ 5 SWITCH3 equ 6 SWITCH4 equ 7 ;Command code from PC LED1_ON equ 00h LED2_ON equ 01h LED3_ON equ 02h LED4_ON equ 03h LED1_OFF equ 10h LED2_OFF equ 11h LED3_OFF equ 12h LED4_OFF equ 13h GET_SWITCH equ 20h ;********************************************************************** ; Clock frequency related constant (4 MHz) ;********************************************************************** BIT_DELAY equ 23 ;Bit delay a 9600 bps ;********************************************************************** ; MACRO - Delay subroutine with watch dog timer clearing ; ; Macro parameters: ; ; VALUE: Delay obtained = ((VALUE-1)*4+5)*(1/(Fosc/4)) ; ;********************************************************************** DELAY MACRO VALUE LOCAL REDO movlw VALUE movwf TmpRegister REDO clrwdt ;Clear watch dog timer decfsz TmpRegister,F goto REDO ENDM ;********************************************************************** ; FILE REGISTER ;********************************************************************** ORG 0CH ;Register used by msDelay subroutine and DELAY macro msDelayCounter res 2 TmpRegister res 1 ;Register used by RS232 subroutines ShiftReg res 1 ;Shift register BitCount res 1 ;Bit counter DummyReg res 1 ;********************************************************************** ; RESET VECTOR ;********************************************************************** ORG 00H Start bsf STATUS,RP0 ;Swap to register bank 1 movlw 00011111B ;Sets the whole PORTA as input movwf TRISA movlw 11111111B ;Sets the whole PORTB as input movwf TRISB bcf PORTA,TX ;Sets TX line as output bcf TRISB,LED1 ;Set output line on PORTB bcf TRISB,LED2 bcf TRISB,LED3 bcf TRISB,LED4 bcf STATUS,RP0 ;Swap to register bank 0 bcf PORTB,LED1 ;Turn off each leds bcf PORTB,LED2 bcf PORTB,LED3 bcf PORTB,LED4 ;Wait until receives a start bit from RS232 line MainLoop btfsc PORTA,RX ;Received a start bit ? goto MainLoop ;No, wait. call RxChar ;Yes, read the byte on receiving... ;*********************** ; Check for PC commands ;*********************** ;*********************** ; LED1_ON ;*********************** Led1On movlw LED1_ON xorwf ShiftReg,W btfss STATUS,Z goto _Led1On bsf PORTB,LED1 goto MainLoop _Led1On ;*********************** ; LED2_ON ;*********************** Led2On movlw LED2_ON xorwf ShiftReg,W btfss STATUS,Z goto _Led2On bsf PORTB,LED2 goto MainLoop _Led2On ;*********************** ; LED3_ON ;*********************** Led3On movlw LED3_ON xorwf ShiftReg,W btfss STATUS,Z goto _Led3On bsf PORTB,LED3 goto MainLoop _Led3On ;*********************** ; LED4_ON ;*********************** Led4On movlw LED4_ON xorwf ShiftReg,W btfss STATUS,Z goto _Led4On bsf PORTB,LED4 goto MainLoop _Led4On ;*********************** ; LED1_OFF ;*********************** Led1Off movlw LED1_OFF xorwf ShiftReg,W btfss STATUS,Z goto _Led1Off bcf PORTB,LED1 goto MainLoop _Led1Off ;*********************** ; LED2_OFF ;*********************** Led2Off movlw LED2_OFF xorwf ShiftReg,W btfss STATUS,Z goto _Led2Off bcf PORTB,LED2 goto MainLoop _Led2Off ;*********************** ; LED3_OFF ;*********************** Led3Off movlw LED3_OFF xorwf ShiftReg,W btfss STATUS,Z goto _Led3Off bcf PORTB,LED3 goto MainLoop _Led3Off ;*********************** ; LED4_OFF ;*********************** Led4Off movlw LED4_OFF xorwf ShiftReg,W btfss STATUS,Z goto _Led4Off bcf PORTB,LED4 goto MainLoop _Led4Off ;*********************** ; GET_SWITCH ;*********************** GetSwitch movlw GET_SWITCH xorwf ShiftReg,W btfss STATUS,Z goto _GetSwitch swapf PORTB,W ;Read the switch state and send movwf DummyReg ;it to the PC comf DummyReg,W andlw 0Fh call TxChar goto MainLoop _GetSwitch goto MainLoop ;********************************************************************** ; Delay subroutine ; ; W = Requested delay time in ms (clock = 4MHz) ;********************************************************************** msDelay movwf msDelayCounter+1 clrf msDelayCounter+0 ; 1 ms (about) internal loop msDelayLoop nop decfsz msDelayCounter+0,F goto msDelayLoop nop decfsz msDelayCounter+1,F goto msDelayLoop return ;************************************************************************** ; Send a character on RS232 ; (9600 baud,8 data bit, 1 stop bit, No parity) ; ; Input: W = Character to send ;************************************************************************** TxChar movwf ShiftReg movlw 8 ;Data lenght movwf BitCount bcf PORTA,TX ;Send start bit nop nop nop nop nop nop nop DELAY BIT_DELAY ;Tx loop TxLoop btfss ShiftReg,0 goto TxLo nop bsf PORTA,TX goto cTx TxLo bcf PORTA,TX goto cTx cTx nop rrf ShiftReg,F DELAY BIT_DELAY decfsz BitCount,F goto TxLoop nop nop nop nop bsf PORTA,TX ;Stop bit DELAY BIT_DELAY DELAY 2 nop bsf PORTA,TX DELAY BIT_DELAY DELAY 2 return ;************************************************************************** ; Receive a character from RS232 ; (9600 baud,8 data bit, 1 stop bit, No parity) ; ; Return code: ; ; ShiftReg: Received character ;************************************************************************** RxChar clrf ShiftReg movlw 8 ;Data lenght movwf BitCount DELAY BIT_DELAY+BIT_DELAY/2 ;Wait 1.5 bit ;Loop di lettura dei bit dati wDB btfss PORTA,RX goto RxBitL RxBitH nop bsf STATUS,C goto RxShift RxBitL bcf STATUS,C goto RxShift RxShift nop rrf ShiftReg,F DELAY BIT_DELAY decfsz BitCount,F goto wDB return END