ISR based Serial Receive code usage. (Couple issues and one solution)
![RobotWorkshop](https://forums.parallax.com/uploads/userpics/915/nCTRZ4MIBWKDB.jpg)
I've been using the ISR based Serial receive code that JonnyMac was kind enough to share on the forums. So far I've had great results when using it but recently ran into a couple problems. One problem I have resolved (while may bite others) and there is still one open issue....
The first problem came up after adding some more code and variables to my program. Everything seemed to be working perfectly but after a couple more edits my program would just hang if I tried using the DELAY_MS routine that was part of the Buf_RX9600.SXB code. After looking at what it was doing I noticed that the problem came up because the BANK was hardcoded in the ISR for the isrFlag variable. It worked fine as long as that variable happened to be in BANK 0 but when I added more variables to the program it got pushed into a different bank which broke the DELAY_MS routine. As a temporary fix I just moved that variable to the front to ensure it would be in BANK 0. I've just noticed a difference in Jon's original ISR based serial code vs his latest posting (besides the timing) for a new version that used an odd baud rate:
Originally:
Check_Tix:
ASM
BANK 0
SETB isrFlag
ENDASM
latest version:
Mark_ISR:
ASM
SETB isrFlag ' (1)
ENDASM
So, is it just best to leave off the BANK 0 instruction all together? Would that have fixed my original problem and allow me to move that flag where ever I want? As I mentioned it seems to be fixed now that i've moved the variable back to BANK 0 but I am looking at the best way to code this so that the program won't break if I move things around. It may also help others who could run into the same problem.
The other issue I am having (and haven't fixed yet) is with the ISR routine itself. It is setup to run every 26us.
' =========================================================================
INTERRUPT NOCODE 38_400 ' run every 26 uS
' =========================================================================
Everything seemed to be working just fine until I started messing with the 16-bit timers built-into the SX48. I am using one of them to generate PWM to control a single motor. To shut off the PWM mode it was suggested that I use TIMER1 TIMER to do this. It seems like that is causing extra Interrupts which may now be throwing off the ISR based Serial code. This also brings up the question as to what other things may generate Interrupts and how to handle them along with the regular ISR code so they all play well together. For my project I don't need any other interrupts other than the one above to receive the Serial characters so this shouldn't be a problem as long as I can ensure that Interrupts are disabled for everything else.
I've gone through the data sheets, been reading the book that G
The first problem came up after adding some more code and variables to my program. Everything seemed to be working perfectly but after a couple more edits my program would just hang if I tried using the DELAY_MS routine that was part of the Buf_RX9600.SXB code. After looking at what it was doing I noticed that the problem came up because the BANK was hardcoded in the ISR for the isrFlag variable. It worked fine as long as that variable happened to be in BANK 0 but when I added more variables to the program it got pushed into a different bank which broke the DELAY_MS routine. As a temporary fix I just moved that variable to the front to ensure it would be in BANK 0. I've just noticed a difference in Jon's original ISR based serial code vs his latest posting (besides the timing) for a new version that used an odd baud rate:
Originally:
Check_Tix:
ASM
BANK 0
SETB isrFlag
ENDASM
latest version:
Mark_ISR:
ASM
SETB isrFlag ' (1)
ENDASM
So, is it just best to leave off the BANK 0 instruction all together? Would that have fixed my original problem and allow me to move that flag where ever I want? As I mentioned it seems to be fixed now that i've moved the variable back to BANK 0 but I am looking at the best way to code this so that the program won't break if I move things around. It may also help others who could run into the same problem.
The other issue I am having (and haven't fixed yet) is with the ISR routine itself. It is setup to run every 26us.
' =========================================================================
INTERRUPT NOCODE 38_400 ' run every 26 uS
' =========================================================================
Everything seemed to be working just fine until I started messing with the 16-bit timers built-into the SX48. I am using one of them to generate PWM to control a single motor. To shut off the PWM mode it was suggested that I use TIMER1 TIMER to do this. It seems like that is causing extra Interrupts which may now be throwing off the ISR based Serial code. This also brings up the question as to what other things may generate Interrupts and how to handle them along with the regular ISR code so they all play well together. For my project I don't need any other interrupts other than the one above to receive the Serial characters so this shouldn't be a problem as long as I can ensure that Interrupts are disabled for everything else.
I've gone through the data sheets, been reading the book that G
Comments
I'm interested in what happens with your timers issue; at the moment I'm working on a program that is going to use the timers for PWM control of motors and I've decided I want to add my buffered serial routines; I haven't done that yet and now will proceed with caution.
Post Edited (JonnyMac) : 2/21/2008 4:47:16 PM GMT
In regards to the banking issue can it be moved to the rxSerial bank since that is already used by the receive code?
'
' Variables
'
idx VAR Byte
char VAR Byte
tmpB1 VAR Byte ' for subs/funcs
tmpB2 VAR Byte
tmpW1 VAR Word
rxSerial VAR Byte (16) ' rx serial data
rxBuf VAR rxSerial(0) ' eight-byte buffer
rxCount VAR rxSerial(8) ' rx bit count
rxDivide VAR rxSerial(9) ' bit divisor timer
rxByte VAR rxSerial(10) ' recevied byte
rxHead VAR rxSerial(11) ' buffer head (write to)
rxTail VAR rxSerial(12) ' buffer tail (read from)
rxBufCnt VAR rxSerial(13) ' # bytes in buffer
flags VAR rxSerial(14)
isrFlag VAR flags.0
' =========================================================================
INTERRUPT NOCODE 38_400 ' run every 26 uS
' =========================================================================
Check_Tix:
ASM
BANK rxSerial ' Set proper BANK for variable
SETB isrFlag
ENDASM
'
' RX UART
'
Receive:
ASM
BANK rxSerial ' MAY NOT NEED THIS ANYMORE
JB rxBufCnt.3, RX_Done ' skip if buffer is full
MOVB C, RX ' sample serial input
TEST rxCount ' receiving now?
JNZ RX_Bit ' yes, get next bit
MOV W, #9 ' no, prep for next byte
SC
MOV rxCount, W ' if start, load bit count
MOV rxDivide, #Baud1x5 ' prep for 1.5 bit periods
At least that way it should be ok no matter where the variable ends up. On that note I suppose it could be in any bank as long as it is specifically called out ahead of time and specified by name so that it will always work.
Thoughts?
I've got a couple things to try this evening regarding the interrupts generated by TIMER1 which I hope will fix the issue I have with that.
Robert