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
'
Code:
' 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


Menu
Re: LCDOUT command followed by variable data
no , you can create your alias names for the array address' in the buffer in any way that you prefer or just use array notation and have no alias' at all
richard - 13th March 2026, 23:08