Comms1
' ======
' Melanie Newman
' 16 July 2004
'
' Demonstration of PC to PIC bi-directional Dialogue
' PC User (using something like Hyperterminal) is able to
' to control 5 LEDs using a number of Commands with sub-parameters
' shows a different approach to Comms in having the PIC parse
' a received command line rather than WAIT for something valid
' to arrive and latch on to.
' ---------------------------------------------------------------------------
' This example for commection to PC at
' 300 baud, 8 Data Bits, No Parity, 1 stop Bit, No Flow Control
' Set Hyperterminal (or whatever) to above parameters on your chosen COM port
' ---------------------------------------------------------------------------
' Links with PC Comms Program such as Hyperterminal
' Echo's printable characters typed on keyboard back to PC
' Performs rudimentary editing with BACKSPACE character
' Executes the following Instructions;-
'
' ON x y Turn ON LED on PortA where x=1 to 5 for LED1-LED5
' if y is specified (value 1-9), will turn ON for y Seconds an then OFF
' ON turn ON all LEDs
' ON 0 same as ON
' ON 0 y turn ON all LEDs for y Seconds then OFF
'
' OFF x y Turn OFF LED on PortA where x=1 to 4 for LED1-LED4
' if y is specified (value 1-9), will turn OFF for y Seconds then ON
' OFF turn OFF all LEDs
' OFF 0 same as OFF
' OFF 0 y Turn OFF all LEDs for y Seconds then ON
'
' BLINK x y
' Blink LED y number of times. If x=0 then Blink ALL LEDs y times
' valid range for y Blink is 1-60
'
' SWEEP x
' valid range for x is 1-99. If omitted defaults to 1.
'
' BEER just for fun!
'
' Program will respond to PC with OK on executing valid command
' Program will respond to PC with Bad! if Bad Command, Parameter or Parameter out of range
' PC User can type in UPPERCASE or lowercase or any cOmBinATioN
'
' CPU Hardware Layout
' -------------------
'
' PortA.0 - LED1-k to PIC pin, LED1-a to VDD via Resistor
' PortA.1 - LED2-k to PIC pin, LED2-a to VDD via Resistor
' PortA.2 - LED3-k to PIC pin, LED3-a to VDD via Resistor
' PortA.3 - LED4-k to PIC pin, LED4-a to VDD via Resistor
' PortA.4 - LED5-k to PIC pin, LED5-a to VDD via Resistor
' PortA.5 - N/c
' PortA.6 - N/C
' PortA.7 - N/C
'
' PortB.0 - N/C
' PortB.1 - RX cable via 1K5 Resistor to PC pin 3 on 9-Pin D Connector
' PortB.2 - TX cable via 1K5 Resistor to PC pin 2 on 9-Pin D Connector
' PortB.3 - N/C
' PortB.4 - N/C
' PortB.5 - N/C
' PortB.6 - N/C
' PortB.7 - N/C
'
' Don't forget to connect Vss to PC pin 5 on 9-pin D Connector
'
' PIC Defines ' ----------- @ DEVICE pic16F628, INTRC_OSC_NOCLKOUT ' System Clock Options @ DEVICE pic16F628, WDT_ON ' Watchdog Timer @ DEVICE pic16F628, PWRT_ON ' Power-On Timer @ DEVICE pic16F628, MCLR_OFF ' Master Clear Options (Internal) @ DEVICE pic16F628, BOD_ON ' Brown-Out Detect @ DEVICE pic16F628, LVP_OFF ' Low-Voltage Programming @ DEVICE pic16F628, CPD_OFF ' Data Memory Code Protect @ DEVICE pic16F628, PROTECT_OFF ' Program Code Protection ' ' Debug (Communication) Defines (Transmit) ' ---------------------------------------- DEFINE DEBUG_REG PORTB DEFINE DEBUG_BIT 2 DEFINE DEBUG_BAUD 300 DEFINE DEBUG_MODE 1 ' ' DEBUG (Communication) Defines (Receive) ' ---------------------------------------- DEFINE DEBUGIN_REG PORTB DEFINE DEBUGIN_BIT 1 DEFINE DEBUGIN_BAUD 300 DEFINE DEBUGIN_MODE 1 ' ' EEPROM Data ' ----------- ' The FIRST character of each line holds the Command Word LENGTH ' and the remaining 7 characters are the actual COMMAND WORD ' Space allocated for 10 commands although I'm only using the first five ' See CONSTANT CommandMax if you want to make the table larger or smaller ' Commands here should be in UPPERCASE although the PC can send aNyThiNg. ' Data @0,2,"ON",0,0,0,0,0 Data 3,"OFF",0,0,0,0 Data 5,"BLINK",0,0 Data 5,"SWEEP",0,0 Data 4,"BEER",0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 ' ' RAM Assignments and Variables ' ----------------------------- BadFlag var BIT ' Flag for Bad Command CounterA var BYTE ' Just a Counter CounterB var BYTE ' Just a Counter CounterC var BYTE ' Just a Counter CounterW var WORD ' Word-sized Counter Command var BYTE ' Holds the Command action to execute CommsBuffer var BYTE [10] ' Max Comms Command Line size CommsPointer var BYTE ' Pointer to data in Comms Buffer LEDStatus var BYTE DataA var BYTE ' Usage as Data Byte Xvariable var BYTE ' 1st Numeric Variable Yvariable var BYTE ' 2nd Numeric Variable ' ' Program Constants ' ----------------- BufMax con 10 ' Max size of data Buffer CommandMax con 10 ' Max number of COMMANDS to be processed ' ' Start - Initialise Processor ' ============================ TRISA=%00000000 TRISB=%00000010 Xvariable=0:Gosub LEDsOFF ' All LEDs OFF ' ' Clear Buffer ready for start of New Command Line ' ------------------------------------------------ RestartLine: For CounterA=1 to BufMax CommsBuffer[CounterA-1]=0 Next CounterA CommsPointer=0 ' Set Pointer to Start of Buffer ' ' Communications (Closed) Loop ' ---------------------------- ReadLoop: DEBUGIN [DataA] If DataA<32 then If DataA=8 then ' Process BACKSPACE Key If CommsPointer>0 then ' --------------------- CommsPointer=CommsPointer-1 ' Rewind one position CommsBuffer(CommsPointer)=0 ' Erase character in Buffer DEBUG $08,$20,$08 ' Echo Erase sequence to PC Goto ReadLoop endif endif If DataA=13 then goto ENTERKey Goto ReadLoop endif If DataA>126 then goto ReadLoop DEBUG DataA ' Only Echo Printable Characters If DataA>96 then ' Convert all alphabetics to UPPERCASE If DataA<123 then DataA=DataA-32 endif CommsBuffer(CommsPointer)=DataA ' Save to Buffer CommsPointer=CommsPointer+1 ' Bump Pointer If CommsPointer<10 then goto ReadLoop ' Loop for next character ' ' Process [ENTER] Key ' ------------------- ' also execute if Command Buffer exceeded ENTERKey: ' ' This section Parses the Command Line ' ==================================== ' ' Look for Command WORD ' (scan through available Command vocabulary) ' ------------------------------------------- Gosub LSpace ' Remove Leading Blanks Gosub REnd ' Locate Command Word End If CounterA=0 then goto EchoCRLF ' Nothing to Process For Command=1 to CommandMax BadFlag=0 CounterB=(Command-1)*8 Read CounterB,DataA ' Get Preset Command word Length If DataA=CounterA then ' If Length correct, process entire word For CounterC=1 to CounterA CounterB=CounterB+1 Read CounterB,DataA If CommsBuffer(CounterC-1)<>DataA then BadFlag=1 Next CounterC If BadFlag=0 then goto GoodCommand endif Next Command ' ' Bad Command Word ' ---------------- BadMove: DEBUG REP $00\8,13,10,"Bad!" ' Tell User No Cigar EchoCRLF: DEBUG 13,10 ' New Line Goto RestartLine ' Loop Round and Do again ' ' Scan for First Numeric Variable (if any) ' ---------------------------------------- GoodCommand: Gosub ShuffleData ' Advance Command Line to start of next Word (if any) Gosub REnd ' Locate End of next word Gosub GetNumericWord ' Get numeric value If BadFlag=1 then goto BadMove ' Invalid Data Xvariable=DataA ' Save 1st Numeric Variable ' ' Now check for 2nd Numeric Variable (if any) on the Command Line ' --------------------------------------------------------------- Gosub ShuffleData ' Advance Command Line to start of next (last) Word (if any) Gosub REnd ' Locate End of word Gosub GetNumericWord If BadFlag=1 then goto BadMove ' Invalid Data Yvariable=DataA ' Save 2nd Numeric Variable ' ' Execute Command ' --------------- If (Command<4 and Xvariable>5) then DEBUG REP $00\8,13,10,"No such LED!" goto EchoCRLF endif If Command<3 then If Yvariable>9 then goto BadMove If Yvariable>1 then gosub WaitMessage endif If Command=3 then If Yvariable>60 then goto BadMove If Yvariable>5 then gosub WaitMessage endif If Command=4 then If Xvariable>5 then gosub WaitMessage endif ' ' ON LED Command ' -------------- If Command=1 then Gosub LEDsON If Yvariable>0 then CounterW=Yvariable*1000 Pause CounterW Gosub LEDsOFF endif endif ' ' OFF LED Command ' --------------- If Command=2 then Gosub LEDsOFF If Yvariable>0 then CounterW=Yvariable*1000 Pause CounterW Gosub LEDsON endif endif ' ' BLINK LED Command ' ----------------- If Command=3 then For CounterA=1 to Yvariable Gosub LEDsON Pause 200 Gosub LEDsOFF Pause 200 Next CounterA endif ' ' SWEEP Command ' ------------- If Command=4 then CounterB=Xvariable If CounterB<1 then CounterB=1 For CounterA=1 to CounterB For Xvariable=1 to 5 Gosub LEDsON Pause 100 Gosub LEDsOFF Next XVariable Next CounterA endif ' ' BEER Command ' ------------ If Command=5 then DEBUG REP $00\8,13,10,"Yes Please!" ' ' Tell User all executed OK ' ------------------------- DEBUG REP $00\8,13,10,"OK" Goto EchoCRLF ' ' Subroutine Area ' =============== ' ' Subroutine extracts Numeric Value from Command Line ' --------------------------------------------------- GetNumericWord: DataA=0 BadFlag=0 If CounterA>2 then Goto BadWord If CounterA>0 then CounterB=CommsBuffer(0) If CounterB<48 then goto BadWord DataA=CounterB-48 If DataA>9 then goto BadWord If CounterA=2 then CounterB=CommsBuffer(1) If CounterB<48 then goto BadWord CounterB=CounterB-48 If CounterB>9 then goto BadWord DataA=DataA*10+CounterB endif endif Return BadWord: BadFlag=1 Return ' ' Shuffle Data to remove processed word ' ------------------------------------- ShuffleData: For CounterB=0 to 9 CounterC=CounterA+CounterB If CounterC<=9 then CommsBuffer(CounterB)=CommsBuffer(CounterC) else CommsBuffer(CounterB)=0 endif Next CounterB ' ' Subroutine removes leading SPACES (Blanks) from Buffer ' ------------------------------------------------------ LSpace: If CommsBuffer(0)=32 then For CounterA=1 to 9 CommsBuffer(CounterA-1)=CommsBuffer(CounterA) Next CounterA CommsBuffer(9)=0 Goto LSpace endif Return ' ' Subroutine Locates end of Dataword in Comms Buffer ' -------------------------------------------------- ' CounterA on exit End Point REnd: For CounterA=0 to 9 If CommsBuffer(CounterA)=32 then goto REndExit If CommsBuffer(CounterA)=0 then goto REndExit Next CounterA CounterA=10 REndExit: Return ' ' Subroutine tells User to Wait ' ----------------------------- WaitMessage: DEBUG REP $00\8,13,10,"Wait..." Return ' ' Subroutine DISABLES LEDs ' ------------------------ LEDsOFF: If Xvariable=0 then LEDStatus=$1F else LEDStatus.0(Xvariable-1)=1 endif PortA=LEDStatus Return ' ' Subroutine ENABLES LEDs ' ----------------------- LEDsON: If Xvariable=0 then LEDStatus=$0 else LEDStatus.0(Xvariable-1)=0 endif PortA=LEDStatus Return End
Re: SERIN2 Receiving Wrong Data
The sending device has the typical 18F4550 USB setup and it is set to "Define OSC 48". The receiving device is set to "DEFINE OSC 16".
rsocor01 Yesterday, 19:56