Coming back to this thread after recovering from some encoder/code porting issues from last week, I'm still trying to figure out the best way to send/receive data from 1 Master chip to 3-4 slaves via USART. I've read over many threads here regarding HSEROUT/HSERIN and the permutations & combinations leave me confused.
As of last night, I've got a PIC12F1840 sending the following on the Tx pin based on a rotary encoder turn (there's an IOC ISR to determine the direction of turn which sets RotEncDir):
Code:
DEFINE OSC 16 ' Set oscillator 16Mhz
DEFINE HSER_TXSTA 20h ; Set transmit status and control register
DEFINE HSER_BAUD 2400 ; Set baud rate
DEFINE HSER_RCSTA 90h
DEFINE HSER_CLROERR 1 ; Clear overrun error upon
; execution of every HSERIN
; command
.
.
.
Main:
TOGGLE LED_0
If ValueDirty = 1 THEN
' Send RotEncDir to receiving chip
' Chip Id,Itm Id, <modifier>, "~"
HSEROUT ["2", "3", SDEC RotEncDir, TxEndChar] ' use 'SDEC' if RotEncDir can be -1 for CCW
ValueDirty = 0 ' Clear the flag
#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [LCD_INST, LCD_CLR]
pause 5
' Chip Id,Itm Id, <modifier>, "~"
HSEROUT ["2", "3", SDEC RotEncDir, TxEndChar] ' use 'SDEC' if RotEncDir can be -1 for CCW
#ENDIF
ENDIF
pause 500
GOTO Main
The output on my LCD shows this for a CW turn:
and this for CCW (RotEncDir actually gets set to 0 but I change it to -1 as on the slave I want to just add this value:
The first number represents the slave chip which is the intended target of the serial data (I'll have 2-3 slaves in this project). The second number represents what to change on that chip with the rotary encoder info. The next part is either '1' for CW or '-1' for CCW (I could go back to using '0' for CCW if that makes the overall serial data easier to interpret on the slaves).
- Should I have a sync character at the start of the serial data so that on the slave I can determine if new serial data is sent before processing the first message (or there's an error)?
- Should I convert the HSEROUT line to multiple lines?
For the slaves, I've decided I need to use a Rx interrupt as I have other code running in the Main loop.
Code:
DEFINE OSC 16 ' Set oscillator 16Mhz
DEFINE HSER_TXSTA 20h ; Set transmit status and control register
DEFINE HSER_BAUD 2400 ; Set baud rate
DEFINE HSER_RCSTA 90h
DEFINE HSER_CLROERR 1 ; Clear overrun error upon
; execution of every HSERIN
; command
.
.
.
' ***************************************************************
' ASM Interrupt Definitions
' ***************************************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _UsartRx, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
' Enable interrupt
@ INT_ENABLE RX_INT ; USART Rx interrupt
.
.
.
- Do I need to make the RX_INT a low priority interrupt, or is that only important if there are other time-sensitive interrupts (I am using SPWM_INT.bas for one slave)?
- As Henrik suggests above, should I make the serial data entirely consistent in terms of number of bytes to make the parsing here easier? If that's true, then I probably need to revert to using '0' for CCW rotary encoder changes.
- The code below is from DT on another thread but I can't see how the whole serial data (e.g. "231~" for slave chip #2 to increment item #3 by 1) will be pieced together.
- Does the ISR get 1 byte every time? i.e. the first time it goes into the above ISR, 'SerialData' will be "2" and then the next iteration will have "3"?
- Should the ISR have the ResetFlag set or not? I've seen both.
Code:
'*********** 'ISR for RX_INT interrupt *************************************
Getbytes:
HSERIN [Serialdata] ' Get the serial data
IF Serialdata = SyncByte THEN ' if it's a Sync byte,
IF Sync THEN ERROR = 1 ' last command was corrupted
Sync = 1 ' indicate Sync was rcvd
ForMe = 0 ' ID has not been rcvd
ELSE
IF Sync THEN
IF !ForME THEN ' if we haven't rcvd the ID
IF Serialdata = ID THEN ' and this byte matches the ID
ForMe = 1 ' indicate ID rcvd
ELSE
Sync = 0 ' Not my packet
ForMe = 0 ' reset receive state
ENDIF ' and wait for next Sync
ELSE
CmdBuf = serialdata ' store the command
IF CmdRcvd THEN LATE = 1 ' last command not finished
CmdRcvd = 1 ' indicate a command was rcvd
Sync = 0 ' reset receive state
ForMe = 0
ENDIF
ENDIF
ENDIF
@ INT_RETURN
All slaves Rx pin will be connected to the master's Tx pin so each slave needs to determine if the serial data is for them or not (which the above code does).
Bookmarks