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


Menu

Re: 16F690 MCLR as Input
many thanks Henrik to clarify this post.
jackberg1 - 27th October 2025, 20:42that make more sense to me now with further test, when the pin RA3
has nothing connected to it, the input is floating thus
when adding a pulldown it's...