Code:
+;********************************************************************* ; Function Description: ;********************************************************************* ; Demonstration of the Simple Commands decoder and HEX routines to ; add commands, HEX data entry, and HEX data print via the serial port ; to a PIC program. The code was developed for the 16F873A, but can be ; adapted to most PIC's with a UART. Runs in the background and no ; interrupts are used to free the interrupt routine for user tasks. ; Command decoder and print routines are loaded in page 1 memory to ; free page 0 memory for the user's program. ; Commands are similar to Motorola style @@Xnxx commands where @@ is ; command start, X capital letter is command, n small letter (optional) ; is sub command, and xx (optional) are HEX data charaters. For Simple ; Commands each data entry expects a known number of characters, no end ; of line or parity is used, and no error testing is performed on the ; data to siplify the code. ; Basic entry and print of single and multi-byte HEX data and control ; functions are demonstrated. Data is sent directly to memory but an ; example of a buffered load is shown. Nested menus are demonstrated ; for easy expansion of the command set as the project grows. By ; selecting and customizing the routines you need for your application, ; adding a custom command menu to your program is easy! ; ; These routines are free for public use but please acknowledge the ; author when using them in your program by commenting your code with ; "Simple Commands by Richard H McCorkle" (Is that so much to ask?) ; Thanks! ; ;********************************************************************* ; Serial Command Functions: ;********************************************************************* ; NOTE: Make sure that RTS is connected to CTS at the PIC serial port ; (DB-9 pin 7 tied to pin 8) and a standard serial cable (all pins ; connected) is used or commands may not function correctly. ; The demo command set is defined as: ; Command Function ; @@- Decrement v1 down 1 count ; @@+ Increment v1 up 1 count ; @@Bxxxxxxxxxx Buffered load of 40-bit value v4 ; @@E Toggle keyboard echo ; @@L Load register commands ; @@L0x Load 4-bit value v0 ; @@L1xx Load 8-bit value v1 ; @@L2xxxx Load 16-bit value v2 ; @@L3xxxxxx Load 24-bit value v3 ; @@L4xxxxxxxxxx Load 40-bit value v4 directly ; @@P Print value to serial TX port ; @@Pc Print Command Bit state ; @@P0 Print a 4-bit value from v0 ; @@P1 Print an 8-bit value from v1 ; @@P2 Print a 16-bit value from v2 ; @@P3 Print 24-bit value a or b (nested menu) ; @@P3a Print the 24-bit register v3 ; @@P3b Print the high 24-bits of 40-bit register v4 ; @@R Reset Command Bit C,0 ; @@S Set Command Bit C,0 ; @@Z Zero 40-bit v4 register ;********************************************************************* ; Program Listing: ;********************************************************************* TITLE "Simple Commands Demonstration - Richard H McCorkle, June 1, 2006" LIST n=58, p=PIC16F873A errorlevel 1 include P16F873A.INC __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF ;********************************************************************* ; Define Storage Locations ;********************************************************************* ;NOTE: Keep registers in H -> L sequential order for indexed ops! CBLOCK 0x20 ;Bank 0 Registers - 80 max, 25 used flg0 ;flag bit storage cHdr0 ;communication header flags ; cHdr1 ;if adding headers, add cHdr1,2, etc Hbyte,Mbyte,Lbyte ;Binary-to-HEX print storage BytCt,Dadr ;serial data entry regs btmp ;background temporary storage ; User variables v0 ;4 bit variable (0-F) v1 ;8 bit variable Hv2,Lv2 ;16 bit variable Hv3,Mv3,Lv3 ;24 bit variable Hv4,Mv4,Lv4 ;40 bit variable Sv4,SSv4 Hbuf,Mbuf,Lbuf ;40-bit Transfer Buffer Sbuf,SSbuf ENDC ;Registers 70-7F common in all banks so stack and buffers stored here ;If not common in PIC used, don't use bank 1 registers in the ;background without disabling interrupts first as background routine ;could be interrupted in either bank and W may not get saved properly ;in W_TEMP on interrupt. CBLOCK 0x70 ;Common registers - 16 max, 6 used W_TEMP ;temp storage for W on interrupt STAT_TEMP ;ditto for status reg PCL_TEMP ;ditto for PCLATH FSR_TEMP ;ditto for FSR TX_BUF ;the next char to be xmitted RX_BUF ;the last char received ENDC ;********************************************************************* ; Hardware Bit Assignments: ;********************************************************************* #define HPF PCLATH,3 ;Hi Program Memory Flag #define Zflag STATUS,Z ;Zero Flag #define Cflag STATUS,C ;Carry Flag #define CmdB PORTC,0 ;Command Bit ;********************************************************************* ; Flag Bit Assignments: ;********************************************************************* #define BrdyF flg0,0 ;Byte Ready flag #define LoByt flg0,1 ;Low Byte flag #define Nrdy flg0,2 ;Not Ready flag #define KBE flg0,3 ;Keyboard Echo flag #define bufF flg0,4 ;Buffered Load flag #define LBF flg0,5 ;Load From Buffer flag ;#define N/U flg0,6 ;Spare flag ;#define N/U flg0,7 ;Spare flag ;********************************************************************* ; Command Header Flags: ;********************************************************************* ;if adding headers, add Hdr7, Hdr8, etc keeping Nrtn last #define Hdr0 cHdr0,0 ;Header 0 Flag (@ ) #define Hdr1 cHdr0,1 ;Header 1 Flag (@@ ) #define Hdr2 cHdr0,2 ;Header 2 Flag (@@P ) #define Hdr3 cHdr0,3 ;Header 3 Flag (@@P3) #define Hdr4 cHdr0,4 ;Header 4 Flag (@@L ) #define Hdr5 cHdr0,5 ;Header 5 Flag (@@L0) #define Hdr6 cHdr0,6 ;Header 6 Flag (Nrtn) ;#define Hdr7 cHdr0,7 ;Header 7 Flag (N/U ) ;********************************************************************* ; Initialization ;********************************************************************* ;Set start of code and interrupt vector org 0 ;initialize code nop ;required for the ICD clrf STATUS ;ensure we are at bank 0 clrf PCLATH ;ensure page bits are cleared goto Start org 4 ;interrupt routine movwf W_TEMP ;"push" instructions swapf STATUS,W ;swapf affects NO status bits bcf STATUS,RP0 ;select bank 0 movwf STAT_TEMP ;save STATUS movf PCLATH,W movwf PCL_TEMP ;save PCLATH clrf PCLATH ;select page 0 movf FSR,W movwf FSR_TEMP ;save FSR bcf INTCON,INTF ;clear interrupt goto Int_srv ;initialize bank 0 ports and control registers Start clrf PORTA ;clear port output latches clrf PORTB clrf PORTC clrf INTCON ;disable all interrupts for now ;initialize bank 1 control regs bsf STATUS,RP0 ;select bank 1 ; Insert user initialize code here movlw 0xfe ;0 as output, 1-5 as inputs, movwf TRISC ;2 serial port pins clrf OPTION_REG ;no TMR0, int on falling edge clrf PIE1 ;no int on async xmt bsf TXSTA,TXEN ;enable USART Tx (async mode) bsf TXSTA,BRGH ;set USART BRGH = 1 movlw D'129' ;set async rate at 9600 baud movwf SPBRG ;129 for 20 MHz clock ;back to bank 0 bcf STATUS,RP0 ;bank 0 for RCSTA reg bsf RCSTA,CREN ;enable USART rcv (async mode) bsf RCSTA,SPEN ;enable serial port bsf INTCON,INTE ;enable interrupt on RB0 clrf flg0 ;clear all flags clrf cHdr0 ;clear cmd headers ; clrf cHdr1 ;if adding headers, add cHdr1,2, etc ; Insert user initialize code here ; bsf INTCON,GIE ;enable interrupts if used ;********************************************************************* ; Background Routine ;********************************************************************* ;In background routines, insure variables used (like temp) aren't ;changed during an interrupt as this could cause trouble on return. ;Btmp used for temp storage in command decoder to prevent this. Bkgnd call Rx232 ;check for character received btfss BrdyF ;if no byte ready goto $ + 7 ;jump past process command bcf BrdyF ;clear byte ready flag bsf HPF ;set hi program flag call CmdProc ;Process command bcf HPF ;reset hi program flag btfsc LBF ;if load buffered flag set call Buf2v4 ;load v4 from buffer ; Insert user background code here goto Bkgnd ;********************************************************************* ; Interrupt Service Routine ;********************************************************************* Int_srv ;Insert user interrupt code here pop bcf STATUS,RP0 movf FSR_TEMP,W ;restore FSR movwf FSR movf PCL_TEMP,W ;restore PCLATH movwf PCLATH swapf STAT_TEMP,W ;restore STATUS movwf STATUS swapf W_TEMP ;set status bits swapf W_TEMP,W ;restore W retfie ;return from interrupt ;********************************************************************* ; Subroutines ;********************************************************************* ;Load 40-bit v4 reg from buffer to prevent partial load from ;affecting ongoing process until full 40-bit value is entered. Buf2v4 bcf bufF ;clear buffer flag bcf LBF ;clear load buffered flag movf Hbuf,W ;move buffer to v4 movwf Hv4 movf Mbuf,W movwf Mv4 movf Lbuf,W movwf Lv4 movf Sbuf,W movwf Sv4 movf SSbuf,W movwf SSv4 return ;********************************************************************* ;Get serial Rx data from the USART Rx232 btfss PIR1,RCIF ;received a char? return ;no - return movf RCSTA,W ;check Rx status for error andlw 0x06 ;only error bits btfss Zflag ;if any set, jump to goto RxErr ;error service routine movf RCREG,W ;get char from input buffer movwf RX_BUF ;store in RX_BUF btfss KBE ;if keyboard echo set goto $ + 4 bsf HPF ;set hi program flag call Tx ;echo it back out Tx port bcf HPF ;reset hi program flag bsf BrdyF ;set byte available flag return RxErr bcf RCSTA,CREN ;clear CREN to clear overrun error movf RCREG,W ;read RCREG to clear framing error bsf RCSTA,CREN ;set CREN to rcv bcf BrdyF ;clear byte ready flag clrf cHdr0 ;clear header flags ; clrf cHdr1 ;if adding headers, add cHdr1,2, etc return ;********************************************************************* ; Page 1 Programs ;********************************************************************* ;To save space in the first page of program memory for the user's ;application the command decoder and print routines are loaded into ;page 1 of program memory. The HPF flag (PCLATH,3) is set to access ;page 1 programs from page 0, and needs to be reset when the routine ;returns to page 0. To access page 0 routines from page 1, clear ;HPF before call, set HPF when the routine returns to page 1. org 800 ;load following routines into page 1 ;********************************************************************* ; Simple Commands by Richard H McCorkle ;********************************************************************* ;Check command received via USART Rx mode. When adding additional ;headers keep number return as first routine by adjusting the ;header pointers in number return and SBC acordingly CmdProc btfss Hdr6 ;is header 6 flag set? (Number Return) goto H5 ;no, test next header call GetByt ;get data bytes btfsc Nrdy ;check not ready return ;if set, get next data btfsc bufF ;if buffered load selected bsf LBF ;set load from buffer flag goto Chf ;clear header flags and exit ;********************************************************************* ;@@L0x Load register with single byte H5 btfss Hdr5 ;header 5 flag set (@@L0 received)? goto H4 ;no, test for next header call HexC ;convert input to value movwf v0 ;save in v0 goto Chf ;clear header flags and exit ;********************************************************************* ;@@L Load register commands H4 btfss Hdr4 ;header 4 flag set (@@L received)? goto H3 ;no, test for next header ;@@L0x Load 4-bit value v0 movlw "0" ;is char a "0" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bsf Hdr5 ;set Header 5 flag return ;@@L1xx Load 8-bit value v1 movlw "1" ;is char a "1" ? call RxChk btfss Zflag goto $ + 5 ;no, next header movlw v1 ;move indirect address to W G1R movwf Dadr ;store in Dadr movlw 0x01 ;get 1 register (2 bytes) goto SBC ;@@L2xxxx Load 16-bit value v2 movlw "2" ;is char a "2" ? call RxChk btfss Zflag goto $ + 5 ;no, next header movlw Hv2 ;move indirect address to W G2R movwf Dadr ;store in Dadr movlw 0x02 ;get 2 registers (4 bytes) goto SBC ;@@L3xxxxxx Load 24-bit value v3 movlw "3" ;is char a "3" ? call RxChk btfss Zflag goto $ + 5 ;no, next header movlw Hv3 ;move indirect address to W G3R movwf Dadr ;store in Dadr movlw 0x03 ;get 3 registers (6 bytes) goto SBC ;@@L4xxxxxxxxxx Load 40-bit value v4 movlw "4" ;is char a "4" ? call RxChk btfss Zflag goto Chf ;no valid @@L command, exit movlw Hv4 ;move indirect address to W G5R movwf Dadr ;store in Dadr movlw 0x05 ;get 5 registers (10 bytes) SBC movwf BytCt bsf Nrdy ;set not ready flag bsf Hdr6 ;set Header 6 flag return ;********************************************************************* ;@@P3x An example of a nested menu command H3 btfss Hdr3 ;header 3 flag set (@@P3 received)? goto H2 ;no, test for next header ;@@P3a Print the 24-bit register v3 movlw "a" ;is char an "a" ? call RxChk btfss Zflag goto $ + 3 ;no, next header call prt3 goto Prtn ;clear header flags and exit ;@@P3b Print the high 24-bits of 40-bit register v4 movlw "b" ;is char a "b" ? call RxChk btfss Zflag goto Chf ;no valid @@P3 command, exit call prt4 goto Prtn ;clear header flags and exit ;********************************************************************* ;@@P Print Commands H2 btfss Hdr2 ;header 2 flag set (@@P received)? goto H1 ;no, test for next header ;@@P3 Print 24-bit value a or b (nested menu) movlw "3" ;is char a "3" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bsf Hdr3 ;set Header 3 flag return ;@@P0 Print a 4-bit value movlw "0" ;is char a "0" ? call RxChk btfss Zflag goto $ + 3 ;no, next header call prt0 goto Prtn ;clear header flags and exit ;@@P1 Print an 8-bit value movlw "1" ;is char a "1" ? call RxChk btfss Zflag goto $ + 3 ;no, next header call prt1 goto Prtn ;clear header flags and exit ;@@P2 Print a 16-bit value movlw "2" ;is char a "2" ? call RxChk btfss Zflag goto $ + 3 ;no, next header call prt2 goto Prtn ;clear header flags and exit ;@@Pc Print Command Bit state movlw "c" ;is char a "c" ? call RxChk btfss Zflag goto Chf ;no valid @@P command, exit movlw "0" btfsc CmdB movlw "1" call Tx Prtn call TxCrLf ;send new line goto Chf ;clear header flags and exit ;********************************************************************* ;@@X Main Menu Commands H1 btfss Hdr1 ;header 1 flag set (@@ received)? goto H0 ;no, test for command start ;@@- Decrement v1 down 1 count movlw "-" ;is char a "-" ? call RxChk btfss Zflag goto $ + 3 ;no, next header decf v1 goto Chf ;clear header flags and exit ;@@+ Increment v1 up 1 count movlw "+" ;is char a "+" ? call RxChk btfss Zflag goto $ + 3 ;no, next header incf v1 goto Chf ;clear header flags and exit ;@@Bxxxxxxxxxx Buffered 40-bit load register v4 command movlw "B" ;is char a "B" ? call RxChk btfss Zflag goto $ + 4 ;no, next header bsf bufF ;set Buffer Flag movlw Hbuf ;move indirect address to W goto G5R ;@@E Toggle keyboard echo movlw "E" ;is char an "E" ? call RxChk btfss Zflag goto $ + 5 ;no, next header movf flg0,W xorlw 0x08 ;toggle 3 bit movwf flg0 goto Chf ;clear header flags and exit ;@@L Load register commands movlw "L" ;is char an "L" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bsf Hdr4 ;set Header 4 flag return ;@@P Print value to serial TX port movlw "P" ;is char a "P" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bsf Hdr2 ;yes, set header 2 flag return ;@@R Reset Command Bit movlw "R" ;is char an "R" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bcf CmdB ;clear command bit goto Chf ;clear header flags and exit ;@@S Set Command Bit movlw "S" ;is char an "S" ? call RxChk btfss Zflag goto $ + 3 ;no, next header bsf CmdB ;set command bit goto Chf ;clear header flags and exit ;@@Z Zero 40-bit v4 register movlw "Z" ;is char a "Z" ? call RxChk btfss Zflag goto Chf ;no valid @@ command, exit clrf Hv4 ;clear v4 register clrf Mv4 clrf Lv4 clrf Sv4 clrf SSv4 goto Chf ;clear header flags and exit ;********************************************************************* ;Decode @@ as command start, set Hdr1 flag H0 movlw "@" ;is char a "@" ? call RxChk btfsc Zflag goto $ + 4 btfsc Hdr0 ;If @ rcvd but second char not @ bcf Hdr0 ;clear header 0 flag and return ;exit btfsc Hdr0 ;was header 0 flag set? goto $ + 3 bsf Hdr0 ;no, set header 0 flag (@ rcvd) return ;exit bsf Hdr1 ;yes, set header 1 flag (@@ rcvd) return ;exit ;********************************************************************* ;clear header flags and exit Chf clrf cHdr0 ;clear header flags ; clrf cHdr1 ;if adding headers, add cHdr1,2, etc return ;********************************************************************* ; Check Received byte for match to character in W on call ; Sets Zflag if match RxChk movwf btmp movf RX_BUF,W subwf btmp,W return ;********************************************************************* ; Hex Convert - convert ASCII 0-9 or A-F to number 0-15 in W ; converts small a-f to caps by clearing 32 bit first so either caps ; or smalls for a-f work. Invalid chars produce some hex value HexC movf RX_BUF,W ;get the byte movwf btmp btfss btmp,6 ;number or char? goto $ + 4 bcf btmp,5 ;clear 32 bit (convert small to caps) movlw D'55' ;subtract 55 to convert A-F to values 10-15 goto $ + 2 movlw D'48' ;subtract 48 to convert 0-9 values subwf btmp,W andlw 0x0f ;discard high bits (convert to hex return ;if invalid character entered) ;********************************************************************* ; Get Bytes - fetch number of registers in BytCt and store ; at address starting at Dadr, clear Nrdy when finished GetByt movf Dadr,W ;get storage address movwf FSR call HexC ;convert input to value btfsc LoByt ;if LoByte set, goto $ + 5 movwf INDF ;load in storage swapf INDF ;move to hi nibble bsf LoByt ;set low byte flag return addwf INDF ;add to value in storage bcf LoByt ;clear low byte flag decfsz BytCt ;got all the registers? goto $ + 3 bcf Nrdy ;clear not ready flag return incf FSR ;point to next data movf FSR,W movwf Dadr ;and store in Dadr return ;********************************************************************* ; Hex Print Routines ;********************************************************************* ;Display data in the same Hex format used for data entry. ;print the 4-bit value in v0 prt0 movf v0,W ;print 4-bit value movwf Lbyte goto hp4 ;********************************************************************* ;print the 8-bit value in v1 prt1 movf v1,W ;print 8-bit value movwf Lbyte goto hp8 ;********************************************************************* ;print the 16-bit value in v2 prt2 movf Hv2,W ;print 16-bit value movwf Mbyte movf Lv2,W movwf Lbyte goto hp16 ;********************************************************************* ;print the 24-bit value in v3 prt3 movf Hv3,W ;print 24-bit value movwf Hbyte movf Mv3,W movwf Mbyte movf Lv3,W movwf Lbyte goto hp24 ;********************************************************************* ;print the high 24-bits of the 40-bit register v4 prt4 movf Hv4,W ;print 24-bit value movwf Hbyte movf Mv4,W movwf Mbyte movf Lv4,W movwf Lbyte goto hp24 ;********************************************************************* ;output chars in Hbyte, Mbyte, Lbyte as HEX ASCII to TX DATA hp24 swapf Hbyte,W movwf TX_BUF call TxHex ;print Hbyte hi nibble in hex movf Hbyte,W movwf TX_BUF call TxHex ;print Hbyte low nibble in hex hp16 swapf Mbyte,W movwf TX_BUF call TxHex ;print Mbyte hi nibble in hex movf Mbyte,W movwf TX_BUF call TxHex ;print Mbyte low nibble in hex hp8 swapf Lbyte,W movwf TX_BUF call TxHex ;print Lbyte hi nibble in hex hp4 movf Lbyte,W movwf TX_BUF goto TxHex ;print Lbyte low nibble in hex ;********************************************************************* ;convert lo nibble in TX_BUF to HEX ASCII and send TxHex movf TX_BUF,W ;get transmit data andlw 0x0f ;mask hi bits sublw 0x09 ;9 - W if >9, Cflag = 0 movf TX_BUF,W ;get data andlw 0x0f ;mask hi bits btfss Cflag ;is input >9 addlw 0x07 ;if >9 add 7 for A-F addlw "0" ;make ASCII Tx bsf STATUS,RP0 ;set bank 1 to access TXSTA reg btfss TXSTA,TRMT ;test for Tx buffer empty goto $ - 1 ;wait till buffer empty bcf STATUS,RP0 ;back to bank 0 movwf TXREG ;send it return ;********************************************************************* ;transmit carriage return, line feed TxCrLf movlw "\r" ;send CR to Tx call Tx movlw "\n" ;send LF to Tx goto Tx ;Tx returns to caller ;********************************************************************* de "SmplCmds - Richard H McCorkle, 06/01/2006" de " " END
file: /Techref/member/RHM-SSS-SC4/Scmds.htm, 26KB, , updated: 2008/3/14 01:41, local time: 2024/8/14 19:01,
owner: RHM-SSS-SC4,
18.216.208.186:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.org/techref/member/RHM-SSS-SC4/Scmds.htm"> Simple Commands – A demonstration program for the 16F873A containing a simple command decoder and example routines to enter and print single and multi-byte data values in HEX, change command bits, and control program execution from a serial port. Using the Simple Commands demonstration program as a starting point for program development and selecting and customizing the routines you need for your application, adding serial port commands and data entry to your PIC program is easy!</A> |
Did you find what you needed? |