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: K42 and Timer Interrupts
Thanks for the explanation.
Ioannis - 28th April 2025, 19:28I misinterpreted these paragraphs. My understanding was to have ASYNC cleared and use Fosc/4.
Ioannis