Interrupts
Moderators: David Barker, Jerry Messina
Interrupts
Hi All,
I am currently on a quest to get a simple timer working toggling a LED, and I ran across a wonderful piece of code written by Darryl Quinn that seems to do the job quite well. I did however run into a issue now when I try to add in a ISRRX module. It seems that if I leave in the ENABLE(ISR) statement in the code below it gives me a compiler error of the interrupt is already in use. If I comment that line out I do not get a blinky LED any more even though I think the ISRRX.Initialize enables interrupts. Has anyone run across this before, and is there a way to get these two modules to play well together ? Any thoughts or comments would be greatly appreciated.
Thanks
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR()
INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
INTCON.7=1
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 8000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
'ISRRX.Reset()
// main
Utils.SetAllDigital()
Output(LED)
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
ISRRX.Initialize // init the ISRRX module!
USART.SetBaudrate(br4800)
Enable(ISR)
While true
If SecCount = DelayTime Then
Toggle(LED1)
SecCount = 0
End If
Wend
I am currently on a quest to get a simple timer working toggling a LED, and I ran across a wonderful piece of code written by Darryl Quinn that seems to do the job quite well. I did however run into a issue now when I try to add in a ISRRX module. It seems that if I leave in the ENABLE(ISR) statement in the code below it gives me a compiler error of the interrupt is already in use. If I comment that line out I do not get a blinky LED any more even though I think the ISRRX.Initialize enables interrupts. Has anyone run across this before, and is there a way to get these two modules to play well together ? Any thoughts or comments would be greatly appreciated.
Thanks
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR()
INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
INTCON.7=1
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 8000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
'ISRRX.Reset()
// main
Utils.SetAllDigital()
Output(LED)
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
ISRRX.Initialize // init the ISRRX module!
USART.SetBaudrate(br4800)
Enable(ISR)
While true
If SecCount = DelayTime Then
Toggle(LED1)
SecCount = 0
End If
Wend
-
- Swordfish Developer
- Posts: 1471
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
I thought you were pretty close before, but since you've changed horses...
The 18F supports two interrupt priority levels, high and low. By default, if you're only using one you don't have to do anything. If you have two priority levels, you have to assign the priorities in the ISR declaration something like this (from the manual)
In addition to that, each peripheral has an interrupt priority bit to assign it to the high or low vector, which is usually found in one of the IPR registers (a few of them aren't, like TMR0IP which is found in INTCON2). Again, by default the register settings default to high-priority.
ISRRX is setup to use the high-priority interrupt by default, so you need to setup the TMR0 intr to use the low priority one.
and add the following before calling Timer0.Initialize()
I removed the lines 'INTCON.7=0' and 'INTCON.7=1' that were in ISR(). This bit is the Global Interrupt Enable bit (GIE). The code would have disabled the high-priority interrupt while inside ISR(), which usually isn't a good thing.
Something else to watch out for. The 'while' loop at the end
has potential problems. In this case, you will probably find that it "works ok", but there are a number of things that can go wrong with that seemingly simple code. (hint: can the processor read or write SecCount in a single operation?)
The 18F supports two interrupt priority levels, high and low. By default, if you're only using one you don't have to do anything. If you have two priority levels, you have to assign the priorities in the ISR declaration something like this (from the manual)
Code: Select all
const
ipLow = 1,
ipHigh = 2
interrupt OnTimer1(ipLow)
// code statements here
end interrupt
interrupt OnTimer3(ipHigh)
// code statements here
end interrupt
ISRRX is setup to use the high-priority interrupt by default, so you need to setup the TMR0 intr to use the low priority one.
Code: Select all
Interrupt ISR(ipLow)
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
End Interrupt
dim TMR0IP as INTCON2.2
Code: Select all
// main
Utils.SetAllDigital()
Low(LED) // make LED an output, and set it low
Low(LED1) // make LED1 an output, and set it low
TMR0IP = 0 // set tmr0 intr to low priority
Timer0.Initialize(LEDFlash)
I removed the lines 'INTCON.7=0' and 'INTCON.7=1' that were in ISR(). This bit is the Global Interrupt Enable bit (GIE). The code would have disabled the high-priority interrupt while inside ISR(), which usually isn't a good thing.
Something else to watch out for. The 'while' loop at the end
Code: Select all
While true
If SecCount = DelayTime Then
Toggle(LED1)
SecCount = 0
End If
wend
Thanks Jerry
Hi,
Thanks a bunch for evaluating this for me and breaking it down. I will work through it and see where I get. I will try to stay on this horse and see where it takes me
Thanks a bunch for evaluating this for me and breaking it down. I will work through it and see where I get. I will try to stay on this horse and see where it takes me
Few More Questions
Hi Jerry,
I had a couple more questions if you had time to answer them. I went through my routine, and made the changes you pointed out. I now get the LED to blink as expected every 1 second. I also went back to the ISRRX routine using ReadSerial() from the examples I found previously. The part I do not understand is when I call ReadSerial() from my main loop on startup my code crawls off in a hole yet the LED still blinks every second. Obviously when I send charcters to the development card it does not show me any data on the RX side. I made a change on the RX routine thinking it needed to be a event. It now does not crawl off in a hole, but I still do not RX any bytes when I send them from the PC. Is there a trick to getting the ISSRX to run besides calling the ISRRX.Initialize ?? I also wanted to make sure OnTimer3 is for the ISSRX. Is that correct ?
Thanks
RX Routine:
Event ReadSerial()
While ISRRX.DataAvailable
SData(SDataSize) = ISRRX.ReadByte()
Inc(SDataSize)
Inc (ByteCount)
Wend
If SDataSize > 0 Then
For Index = 0 To (SDataSize - 1)
RXData(Index) = SData(Index)
Next
End If
Toggle(LED1)
' Test Code To Verify 12 Bytes received In Packet
If ByteCount = 12 Then
For Index = 0 To (SDataSize - 1)
USART.Write(RXData(Index))
Next
ByteCount = 0 ' Clear Byte Counter After 12 Bytes Came In
SDataSize = 0 ' Clear Byte Index Only After 12 Bytes Came in
PacketFlag = true ' Set Flag To Indicate Packet received
TOGGLE(led1) '(Led Never Toggled To Indicate Packet Received)
'ISRRX.Reset ' Clear Buffer After 12 Bytes received
End If
End Event
Main Code:
If SecCount = DelayTime Then
Toggle(LED1)
SecCount = 0
End If
I had a couple more questions if you had time to answer them. I went through my routine, and made the changes you pointed out. I now get the LED to blink as expected every 1 second. I also went back to the ISRRX routine using ReadSerial() from the examples I found previously. The part I do not understand is when I call ReadSerial() from my main loop on startup my code crawls off in a hole yet the LED still blinks every second. Obviously when I send charcters to the development card it does not show me any data on the RX side. I made a change on the RX routine thinking it needed to be a event. It now does not crawl off in a hole, but I still do not RX any bytes when I send them from the PC. Is there a trick to getting the ISSRX to run besides calling the ISRRX.Initialize ?? I also wanted to make sure OnTimer3 is for the ISSRX. Is that correct ?
Thanks
RX Routine:
Event ReadSerial()
While ISRRX.DataAvailable
SData(SDataSize) = ISRRX.ReadByte()
Inc(SDataSize)
Inc (ByteCount)
Wend
If SDataSize > 0 Then
For Index = 0 To (SDataSize - 1)
RXData(Index) = SData(Index)
Next
End If
Toggle(LED1)
' Test Code To Verify 12 Bytes received In Packet
If ByteCount = 12 Then
For Index = 0 To (SDataSize - 1)
USART.Write(RXData(Index))
Next
ByteCount = 0 ' Clear Byte Counter After 12 Bytes Came In
SDataSize = 0 ' Clear Byte Index Only After 12 Bytes Came in
PacketFlag = true ' Set Flag To Indicate Packet received
TOGGLE(led1) '(Led Never Toggled To Indicate Packet Received)
'ISRRX.Reset ' Clear Buffer After 12 Bytes received
End If
End Event
Main Code:
If SecCount = DelayTime Then
Toggle(LED1)
SecCount = 0
End If
trial # 2
Hi,
Ok I made a tweak to the code posted in the earlier message. I looked in ISSRX.bas for the Initialize routine and it does a Enable(OnRX) so I changed my ReadSerial event to match the name. It did not seem to make a difference. I think my RX Interrupt is not getting turned on, but I am unsure how to tell. Any ideas would be greatly appreciated. I really wanna learn how this all works. I enjoy playing around with PIC parts and Swordfish is a wonderful tool to allow ya to do this.
Thanks
Event OnRX()
While ISRRX.DataAvailable
SData(SDataSize) = ISRRX.ReadByte()
Inc(SDataSize)
Inc (ByteCount)
'Toggle(LED1)
Wend
If SDataSize > 0 Then
For Index = 0 To (SDataSize - 1)
RXData(Index) = SData(Index)
Next
End If
Toggle(LED1)
' Test Code To Verify 12 Bytes received In Packet
If ByteCount = 12 Then
For Index = 0 To (SDataSize - 1)
USART.Write(RXData(Index)) ' (Never See Any Charcters Sent)
Next
ByteCount = 0 ' Clear Byte Counter After 12 Bytes Came In
SDataSize = 0 ' Clear Byte Index Only After 12 Bytes Came in
PacketFlag = true ' Set Flag To Indicate Packet received
TOGGLE(led1) ' (Does Not Toggle Still)
'ISRRX.Reset ' Clear Buffer After 12 Bytes received
End If
End Event
Ok I made a tweak to the code posted in the earlier message. I looked in ISSRX.bas for the Initialize routine and it does a Enable(OnRX) so I changed my ReadSerial event to match the name. It did not seem to make a difference. I think my RX Interrupt is not getting turned on, but I am unsure how to tell. Any ideas would be greatly appreciated. I really wanna learn how this all works. I enjoy playing around with PIC parts and Swordfish is a wonderful tool to allow ya to do this.
Thanks
Event OnRX()
While ISRRX.DataAvailable
SData(SDataSize) = ISRRX.ReadByte()
Inc(SDataSize)
Inc (ByteCount)
'Toggle(LED1)
Wend
If SDataSize > 0 Then
For Index = 0 To (SDataSize - 1)
RXData(Index) = SData(Index)
Next
End If
Toggle(LED1)
' Test Code To Verify 12 Bytes received In Packet
If ByteCount = 12 Then
For Index = 0 To (SDataSize - 1)
USART.Write(RXData(Index)) ' (Never See Any Charcters Sent)
Next
ByteCount = 0 ' Clear Byte Counter After 12 Bytes Came In
SDataSize = 0 ' Clear Byte Index Only After 12 Bytes Came in
PacketFlag = true ' Set Flag To Indicate Packet received
TOGGLE(led1) ' (Does Not Toggle Still)
'ISRRX.Reset ' Clear Buffer After 12 Bytes received
End If
End Event
-
- Swordfish Developer
- Posts: 1471
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
You're mixing up events and ISR's. A good read of the manual sections on those topics might help (http://www.sfcompiler.co.uk/downloads/SFManual.pdf).
Events are typically used as a way to extend the function of an isr without having to modify the original module code. They're a form of indirect subroutine call.
Enable() and Disable() apply to interrupt routines. As the names imply, they set/clear the interrupt enable flag for the high/low priority interrupt, depending on the priority of the interrupt() routine name that you pass them.
The ReadSerial routine shouldn't be an event. It also has some of the same buffer index issues as it originally did. Since it's hard to troubleshoot and discuss little snippets of code, I've tried to consolidate the two different routines you've been talking about into one. It compiles, but I didn't test it. See how/if it works
Events are typically used as a way to extend the function of an isr without having to modify the original module code. They're a form of indirect subroutine call.
Enable() and Disable() apply to interrupt routines. As the names imply, they set/clear the interrupt enable flag for the high/low priority interrupt, depending on the priority of the interrupt() routine name that you pass them.
The ReadSerial routine shouldn't be an event. It also has some of the same buffer index issues as it originally did. Since it's hard to troubleshoot and discuss little snippets of code, I've tried to consolidate the two different routines you've been talking about into one. It compiles, but I didn't test it. See how/if it works
Code: Select all
Device = 18F25J10 // Setup the device/clock information
Clock = 8
Config FOSC = HSPLL
Config FOSC2 = ON
include "usart.bas"
include "isrrx.bas"
include "timer0.bas"
include "utils.bas"
Dim RED_LED As PORTC.2
Dim GREEN_LED As PORTC.1
dim PacketFlag as boolean
dim ByteCount as byte
dim RXData(32) as byte
dim DelayTime as word
dim SecCount as word
dim i as byte
//timer0 interrupt priority
dim TMR0IP as INTCON2.2
const
ipLow = 1,
ipHigh = 2
// event used by timer0 interrupt
// called by Timer0.SInterrupt()
Event LEDFlash()
Toggle(RED_LED)
SecCount = SecCount + 1000
End Event
Interrupt Timer0_ISR(ipLow)
If Timer0.InterruptFlag = 1 Then
Timer0.SInterrupt()
EndIf
End Interrupt
//main entry point
// setup pic pins
Utils.SetAllDigital()
// make led pins outputs, and set them low
low(RED_LED)
low(GREEN_LED)
// setup led flash timer
DelayTime = 8000
SecCount = 0
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
// enable timer0 interrupt
Enable(Timer0_ISR)
// setup serial port
USART.SetBaudrate(br4800) // init uart
ISRRX.Initialize() // init the ISRRX module
// main loop
PacketFlag = false
ByteCount = 0
while true
if (SecCount >= DelayTime) then
Toggle(GREEN_LED)
SecCount = 0
endif
if (ISRRX.DataAvailable()) then
RXData(ByteCount) = ISRRX.ReadByte()
inc(ByteCount)
if (ByteCount = 12) then
PacketFlag = true
endif
endif
if (PacketFlag) then
// echo packet back out the uart
for i = 0 To (ByteCount-1)
USART.Write(RXData(i))
next
if ((RXData(0) = $FE) and (RXData(1) = $1E) and (RXData(3) = $14)) then
' Do Something It Matches
endif
// prepare for next packet
ByteCount = 0
PacketFlag = false
endif
end while
Thanks
Hi,
Thanks a bunch Jerry. I will play with it and see how it works so I can better understand this process. This has been a good learning experience about Interrupts for me. Hopefully I will see charcters come in while the LED Blinks.
Thanks a bunch Jerry. I will play with it and see how it works so I can better understand this process. This has been a good learning experience about Interrupts for me. Hopefully I will see charcters come in while the LED Blinks.
Hi All,
Well I guess I am stumped again. I tried the Code Jerry was so kind to post for me yesterday. I added in a line to print Hello every 5 seconds and also to echo back what is received any other time. When I connect to the serial port of the CCS development card I am using I get garbage charcters no matter what I try. I even tried disabling the timero before I write Hello and then re-enable it when I am done thinking the timer was affecting the TX routines. Does anyone have a simple serial routine to send a message that also uses ISRRX so I can test my hardware or does anyone else see anything wrong with this code. Any thoughts are greatly appreciated.
Thanks
// device and clock...
Device = 18F67J60
Clock = 25
Config FOSC = HSPLL
Config FOSC2 = ON
Config CP0 = OFF // Turn Code Protect On And Off
Include "DL_Timer.bas"
Include "utils.bas"
Include "USART.bas"
Include "Convert.bas"
Include "isrrx.bas"
Dim LED As PORTB.5
Dim LED1 As PORTB.4
Dim RXData(14) As Byte
Dim SData(14) As Byte
Dim SDataSize As Byte
Dim ByteCount As Integer
Dim result As Boolean
Dim DelayTime As Word
Dim SecCount As Integer
Dim I As Integer
Dim Index As Byte
// variables...
Dim PacketFlag As Boolean
Dim RX_BYTE As Byte
Dim TMR0IP As INTCON2.2
Const ipLow = 1, ipHigh = 2
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR(ipLow)
'INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
' INTCON.7=1
End Interrupt
Interrupt OnTimer1(ipLow)
// code statements here
End Interrupt
Interrupt OnTimer3(ipHigh)
// code statements here
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 10000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
Output(LED)
Output(LED1)
TMR0IP = 0 // set tmr0 intr to low priority
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
Enable(ISR) ' Start Interrupts
USART.SetBaudrate(br4800)
ISRRX.Initialize // init the ISRRX module!
While true
If SecCount = DelayTime Then
'Timer0.dISABLED()
USART.Write("Hello",13,10)
'Timer0.eNABLED()
Toggle(LED1)
SecCount = 0
End If
If ISRRX.DataAvailable() Then
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
USART.Write(RXData(ByteCount) )
End If
Wend
Well I guess I am stumped again. I tried the Code Jerry was so kind to post for me yesterday. I added in a line to print Hello every 5 seconds and also to echo back what is received any other time. When I connect to the serial port of the CCS development card I am using I get garbage charcters no matter what I try. I even tried disabling the timero before I write Hello and then re-enable it when I am done thinking the timer was affecting the TX routines. Does anyone have a simple serial routine to send a message that also uses ISRRX so I can test my hardware or does anyone else see anything wrong with this code. Any thoughts are greatly appreciated.
Thanks
// device and clock...
Device = 18F67J60
Clock = 25
Config FOSC = HSPLL
Config FOSC2 = ON
Config CP0 = OFF // Turn Code Protect On And Off
Include "DL_Timer.bas"
Include "utils.bas"
Include "USART.bas"
Include "Convert.bas"
Include "isrrx.bas"
Dim LED As PORTB.5
Dim LED1 As PORTB.4
Dim RXData(14) As Byte
Dim SData(14) As Byte
Dim SDataSize As Byte
Dim ByteCount As Integer
Dim result As Boolean
Dim DelayTime As Word
Dim SecCount As Integer
Dim I As Integer
Dim Index As Byte
// variables...
Dim PacketFlag As Boolean
Dim RX_BYTE As Byte
Dim TMR0IP As INTCON2.2
Const ipLow = 1, ipHigh = 2
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR(ipLow)
'INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
' INTCON.7=1
End Interrupt
Interrupt OnTimer1(ipLow)
// code statements here
End Interrupt
Interrupt OnTimer3(ipHigh)
// code statements here
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 10000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
Output(LED)
Output(LED1)
TMR0IP = 0 // set tmr0 intr to low priority
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
Enable(ISR) ' Start Interrupts
USART.SetBaudrate(br4800)
ISRRX.Initialize // init the ISRRX module!
While true
If SecCount = DelayTime Then
'Timer0.dISABLED()
USART.Write("Hello",13,10)
'Timer0.eNABLED()
Toggle(LED1)
SecCount = 0
End If
If ISRRX.DataAvailable() Then
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
USART.Write(RXData(ByteCount) )
End If
Wend
-
- Swordfish Developer
- Posts: 1471
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
First off, when I showed the example of how to set the interrupt priorities, I should have been more clear that it was an example only. Remove this from your code
Now, as to the usart issue. There are a number of settings that control the usart baud rate generator. The defaults in USART.bas are
#option USART_BRGH = true
#option USART_BRG16 = false
At 25MHz and 4800 baud with those settings, you're getting a 27% error in the baud rate. What you need is
#option USART_BRGH = true
#option USART_BRG16 = true
That will give you an error of 0%. Include those two lines before the "include USART.BAS" statement in your file.
HOWEVER, there is a bug in the SF USART.bas module. In 16-bit mode, the SetBaudrate() routine is declared as
These statements treat the two SPBRG and SPBRGH registers as a single 16-bit word, so the two registers MUST be contiguous in the memory map. On some PICs (like the 67J60 and 4685), they are NOT... they're in two different areas. When it does the 16-bit write, it writes to a completely different register!
Here's a modified version of the USART.BAS file that I think should address this. Note that I haven't had a chance to test this out (I use a different serial module in my stuff), so it may not be 100% correct. If you place it in your project subdirectory (instead of the SF library dir), SF should use it instead.
USART.BAS
I should point out that not all chips have a 16-bit BRG, so the above won't compile without some changes for those.
Code: Select all
Interrupt OnTimer1(ipLow)
// code statements here
End Interrupt
Interrupt OnTimer3(ipHigh)
// code statements here
End Interrupt
#option USART_BRGH = true
#option USART_BRG16 = false
At 25MHz and 4800 baud with those settings, you're getting a 27% error in the baud rate. What you need is
#option USART_BRGH = true
#option USART_BRG16 = true
That will give you an error of 0%. Include those two lines before the "include USART.BAS" statement in your file.
HOWEVER, there is a bug in the SF USART.bas module. In 16-bit mode, the SetBaudrate() routine is declared as
Code: Select all
dim SPBRGRegister As SPBRG.AsWord,
Public Sub SetBaudrate(pSPBRG As SPBRGRegister = br19200)
Here's a modified version of the USART.BAS file that I think should address this. Note that I haven't had a chance to test this out (I use a different serial module in my stuff), so it may not be 100% correct. If you place it in your project subdirectory (instead of the SF library dir), SF should use it instead.
USART.BAS
Code: Select all
{
*****************************************************************************
* Name : USART Library *
* Author : David John Barker *
* Notice : Copyright (c) 2003 Mecanique *
* : All Rights Reserved *
* Date : 21/01/06
* ; 1.5b - fix set baudrate for chips where BRGH/L are not contiguous
* Version : 1.5 Reworked for silicon error *
* : 1.4 Removed TXIF from WriteItem(Str) and replaced with PIR1, 4 *
* : 1.3 Added support for USART_BRG16 *
* Notes : 1.2 Supports single USART devices. For devices with multiple *
* : USARTs, this module with map to USART1 *
*****************************************************************************
}
Module USART
Include "system.bas"
// calculate clock...
Const FOSC = _clock * 1000000
// low speed or high speed (BRGH)...
#if IsOption(USART_BRGH) And Not (USART_BRGH in (true, false))
#error USART_BRGH, "Invalid option. BRGH must be TRUE or FALSE."
#endif
#option USART_BRGH = true
#if USART_BRGH = true
Const USART_MODE = $24
#else
Const USART_MODE = $20
#endif
// 8 bit or 16 bit (BRG16 only supported with EUSART modules)...
#if IsOption(USART_BRG16) And Not (USART_BRG16 in (true, false))
#error USART_BRG16, "Invalid option. BRG16 must be TRUE or FALSE."
#endif
#option USART_BRG16 = false
#if Not USART_BRG16 And Not USART_BRGH // BRG16 = 0, BRGH = 0
Const FMULT = 64
#elseif USART_BRG16 And Not USART_BRGH // BRG16 = 1, BRGH = 0
Const FMULT = 16
#elseif Not USART_BRG16 And USART_BRGH // BRG16 = 0, BRGH = 1
Const FMULT = 16
#else // BRG16 = 1, BRGH = 1
Const FMULT = 4
#endif
// map registers to USART(x)
#if _usart = 0
#error _device + " does not support USART"
// single USART...
#elseif _usart = 1
Public Dim
SPBRG_LO as SPBRG, // <<****** V1.5B MOD
SPBRG_HI as SPBRGH, // <<****** V1.5B MOD
#if USART_BRG16
BRG16 As BAUDCON.3,
#endif
RCRegister As RCREG,
TXRegister As TXREG,
TXStatus As TXSTA,
RCStatus As RCSTA,
#if _device in (18F1220, 18F1320)
RCInput As TRISB.Booleans(4),
TXInput As TRISB.Booleans(1)
#else
RCInput As TRISC.Booleans(7),
TXInput As TRISC.Booleans(6)
#endif
// MCU has more than one USART...
#else
Public Dim // -> USART2
SPBRG_LO as SPBRG1, // <<****** V1.5B MOD
SPBRG_HI as SPBRGH1, // <<****** V1.5B MOD
#if USART_BRG16
BRG16 As BAUDCON1.3, // as BAUDCON2
#endif
RCRegister As RCREG1, // as RCREG2
TXRegister As TXREG1, // as TXREG2
RCStatus As RCSTA1, // as TXSTA2
TXStatus As TXSTA1, // as TXSTA2
RCInput As TRISC.Booleans(7), // as TRISG (2)
TXInput As TRISC.Booleans(6) // as TRISG (1)
#endif
Dim // -> USART2
PIR As PIR1, // as PIR3
PIE As PIE1, // as PIE3
IPR As IPR1 // as IPR3
// public baudrate constants...
#if USART_BRG16
Public Const
br300 As Word = FOSC / (FMULT * (300 + 1)) - 1 + 0.5,
br600 As Word = FOSC / (FMULT * (600 + 1)) - 1 + 0.5,
br1200 As Word = FOSC / (FMULT * (1200 + 1)) - 1 + 0.5,
br2400 As Word = FOSC / (FMULT * (2400 + 1)) - 1 + 0.5,
br4800 As Word = FOSC / (FMULT * (4800 + 1)) - 1 + 0.5,
br9600 As Word = FOSC / (FMULT * (9600 + 1)) - 1 + 0.5,
br19200 As Word = FOSC / (FMULT * (19200 + 1)) - 1 + 0.5,
br38400 As Word = FOSC / (FMULT * (38400 + 1)) - 1 + 0.5,
br57600 As Word = FOSC / (FMULT * (57600 + 1)) - 1 + 0.5,
br115200 As Word = FOSC / (FMULT * (115200 + 1)) - 1 + 0.5
#else
Public Const
br300 As Byte = FOSC / (FMULT * (300 + 1)) - 1 + 0.5,
br600 As Byte = FOSC / (FMULT * (600 + 1)) - 1 + 0.5,
br1200 As Byte = FOSC / (FMULT * (1200 + 1)) - 1 + 0.5,
br2400 As Byte = FOSC / (FMULT * (2400 + 1)) - 1 + 0.5,
br4800 As Byte = FOSC / (FMULT * (4800 + 1)) - 1 + 0.5,
br9600 As Byte = FOSC / (FMULT * (9600 + 1)) - 1 + 0.5,
br19200 As Byte = FOSC / (FMULT * (19200 + 1)) - 1 + 0.5,
br38400 As Byte = FOSC / (FMULT * (38400 + 1)) - 1 + 0.5,
br57600 As Byte = FOSC / (FMULT * (57600 + 1)) - 1 + 0.5,
br115200 As Byte = FOSC / (FMULT * (115200 + 1)) - 1 + 0.5
#endif
// alias public bitnames to TXSTA(x)...
Public Dim
CSRC As TXStatus.7,
TX9 As TXStatus.6,
TXEN As TXStatus.5,
SYNC As TXStatus.4,
BRGH As TXStatus.2,
TRMT As TXStatus.1,
TX9D As TXStatus.0
// alias public bitnames to RCSTA(x)...
Public Dim
SPEN As RCStatus.7,
RX9 As RCStatus.6,
SREN As RCStatus.5,
CREN As RCStatus.4,
ADDEN As RCStatus.3,
FERR As RCStatus.2,
OERR As RCStatus.1,
RX9D As RCStatus.0
// alias public interrupt flags...
Public Dim
RCIF As PIR.5, // receive buffer full
TXIF As PIR.4, // transmit buffer empty
RCIE As PIE.5, // receive interrupt enable
TXIE As PIE.4, // transmit interrupt enable
RCIP As IPR.5, // receive interrupt priority
TXIP As IPR.4 // transmit interrupt priority
// public boolean flags...
Public Dim
DataAvailable As PIR.Booleans(5), // RCIF
ReadyToSend As PIR.Booleans(4), // TXIF
ContinousReceive As RCStatus.Booleans(4), // CREN
Overrun As RCStatus.Booleans(1), // OERR
FrameError As RCStatus.Booleans(2), // FERR
RCIEnable As PIE.Booleans(5), // RCIE
TXIEnable As PIE.Booleans(4), // TXIE
RCIPHigh As IPR.Booleans(5), // RCIP
TXIPHigh As IPR.Booleans(4) // TXIP
Public Dim
ReadTerminator As Char // read string terminator
{
****************************************************************************
* Name : SetBaudrate *
* Purpose : Sets the hardware USART baudrate *
* : Pass SPBRG constant, as defined above. For example, br115200 *
// <<****** V1.5B MODIFIED for non-contiguous BRG registers
****************************************************************************
}
Public Sub SetBaudrate(pSPBRG As word = br19200)
SPBRG_LO = pSPBRG.byte0 // <<****** V1.5B MOD
SPBRG_HI = pSPBRG.byte1 // <<****** V1.5B MOD
RCStatus = $90 // serial port enable, continuous receive
RCInput = true // receive pin is input
TXInput = false // transmit pin is output
TXStatus = USART_MODE // high or low speed
#if USART_BRG16
BRG16 = 1
#endif
End Sub
{
****************************************************************************
* Name : ClearOverrun *
* Purpose : Clear USART overrun error by resetting receive flag *
****************************************************************************
}
Public Sub ClearOverrun()
If Overrun Then
CREN = 0 // disable continuous receive
CREN = 1 // enable continous receive
EndIf
End Sub
{
****************************************************************************
* Name : ReadByte *
* Purpose : Read a byte from the hardware USART *
* : Waits for USART data, return byte in RCREG(x) *
****************************************************************************
}
Public Function ReadByte() As RCRegister
Repeat
ClrWDT
Until DataAvailable
End Function
{
****************************************************************************
* Name : ReadBoolean *
* Purpose : Read a boolean from the hardware USART *
****************************************************************************
}
Public Function ReadBoolean() As Boolean
Result = Boolean(ReadByte)
End Function
{
****************************************************************************
* Name : ReadWord *
* Purpose : Read a word from the hardware USART *
****************************************************************************
}
Public Function ReadWord() As Word
Result.Bytes(0) = ReadByte
Result.Bytes(1) = ReadByte
End Function
{
****************************************************************************
* Name : ReadLongWord *
* Purpose : Read a long word from the hardware USART *
****************************************************************************
}
Public Function ReadLongWord() As LongWord
Result.Bytes(0) = ReadByte
Result.Bytes(1) = ReadByte
Result.Bytes(2) = ReadByte
Result.Bytes(3) = ReadByte
End Function
{
****************************************************************************
* Name : ReadFloat *
* Purpose : Read a float from the hardware USART *
****************************************************************************
}
Public Function ReadFloat() As Float
Result.Bytes(0) = ReadByte
Result.Bytes(1) = ReadByte
Result.Bytes(2) = ReadByte
Result.Bytes(3) = ReadByte
End Function
{
****************************************************************************
* Name : WriteByte *
* Purpose : Write a byte value to the hardware USART *
* : Wait until ready to send is enabled, then send WREG byte *
****************************************************************************
}
Public Sub WriteByte(pValue As WREG)
Repeat
ClrWDT
Until ReadyToSend
TXRegister = WREG
End Sub
{
****************************************************************************
* Name : WriteBoolean *
* Purpose : Write a boolean value to the hardware USART *
****************************************************************************
}
Public Sub WriteBoolean(pValue As Boolean)
WriteByte(Byte(pValue))
End Sub
{
****************************************************************************
* Name : WriteWord *
* Purpose : Write a word value to the hardware USART *
****************************************************************************
}
Public Sub WriteWord(pValue As Word)
WriteByte(pValue.Bytes(0))
WriteByte(pValue.Bytes(1))
End Sub
{
****************************************************************************
* Name : WriteLongWord *
* Purpose : Write a word value to the hardware USART *
****************************************************************************
}
Public Sub WriteLongWord(pValue As LongWord)
WriteByte(pValue.Bytes(0))
WriteByte(pValue.Bytes(1))
WriteByte(pValue.Bytes(2))
WriteByte(pValue.Bytes(3))
End Sub
{
****************************************************************************
* Name : WriteFloat *
* Purpose : Write a floating point number to the hardware USART *
****************************************************************************
}
Public Sub WriteFloat(pValue As Float)
WriteByte(pValue.Bytes(0))
WriteByte(pValue.Bytes(1))
WriteByte(pValue.Bytes(2))
WriteByte(pValue.Bytes(3))
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a boolean from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As Boolean)
pValue = Boolean(ReadByte)
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a byte from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As Byte)
pValue = ReadByte
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a shortint from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As ShortInt)
pValue = ReadByte
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a word from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As Word)
pValue = ReadWord
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read an integer from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As Integer)
pValue = ReadWord
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a long word from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As LongWord)
pValue = ReadLongWord
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a long integer from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As LongInt)
pValue = ReadLongWord
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a floating point number from the hardware USART *
****************************************************************************
}
Sub ReadItem(ByRef pValue As Float)
pValue = ReadFloat
End Sub
{
****************************************************************************
* Name : ReadItem (OVERLOAD) *
* Purpose : Read a string from the hardware USART. Use ReadTerminator *
* : to specify the input string terminator character. *
* : 1.5 Reworked for silicon error *
****************************************************************************
}
Sub ReadItem(ByRef pText As String)
Dim TextPtr As POSTINC0
Dim TextAddr As FSR0
Dim Value As Byte
TextAddr = AddressOf(pText)
Value = ReadByte
While Value <> Byte(ReadTerminator)
TextPtr = Value
Value = ReadByte
Wend
TextPtr = null
End Sub
{
****************************************************************************
* Name : Read (COMPOUND) *
* Purpose : Read an item from the hardware USART *
****************************************************************************
}
Public Compound Sub Read(ReadItem)
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a boolean value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As Boolean)
WriteByte(Byte(pValue))
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a byte value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As WREG)
WriteByte(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a short int value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As ShortInt)
WriteByte(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a word value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As Word)
WriteWord(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write an integer value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As Integer)
WriteWord(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a long word to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As LongWord)
WriteLongWord(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a long integer to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As LongInt)
WriteLongWord(pValue)
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a floating point number to the hardware USART *
****************************************************************************
}
Sub WriteItem(pValue As Float)
WriteByte(pValue.Bytes(0))
WriteByte(pValue.Bytes(1))
WriteByte(pValue.Bytes(2))
WriteByte(pValue.Bytes(3))
End Sub
{
****************************************************************************
* Name : WriteItem (OVERLOAD) *
* Purpose : Write a string value to the hardware USART *
****************************************************************************
}
Sub WriteItem(pText As String)
FSR0 = AddressOf(pText)
#if WDT
ASM
movf POSTINC0, W
bz $ + 12
ClrWDT
btfss PIR, 4
bra $ - 4
movwf TXRegister
bra $ - 12
End ASM
#else
ASM
movf POSTINC0, W
bz $ + 10
btfss PIR, 4
bra $ - 2
movwf TXRegister
bra $ - 10
End ASM
#endif
End Sub
{
****************************************************************************
* Name : Write (COMPOUND) *
* Purpose : Write an item to the hardware USART *
****************************************************************************
}
Public Compound Sub Write(WriteItem)
{
****************************************************************************
* Name : WaitFor *
* Purpose : Wait for a byte value to be received *
****************************************************************************
}
Public Function WaitFor(pValue As Byte) As Boolean
result = ReadByte = pValue
End Function
{
****************************************************************************
* Name : WaitForTimeout *
* Purpose : Wait for a byte value to be received, with timeout value in *
* : milliseconds *
****************************************************************************
}
Public Function WaitForTimeout(pValue As Byte, pTimeout As Word) As Boolean
Dim Counter As Byte
Dim Timeout As Word
ClearOverrun
Result = false
Counter = 10
Repeat
Timeout = pTimeout
While Timeout > 0
If DataAvailable And (RCRegister = pValue) Then
Result = true
Exit
EndIf
DelayUS(100)
Dec(Timeout)
Wend
Dec(Counter)
Until Counter = 0
End Function
{
****************************************************************************
* Name : WaitForCount *
* Purpose : Wait for pAmount bytes to be received. The incoming data is *
* : stored in pArray *
****************************************************************************
}
Public Sub WaitForCount(ByRef pArray() As Byte, pCount As Word)
Dim Index As Word
ClearOverrun
Index = 0
While pCount > 0
pArray(Index) = ReadByte
Dec(pCount)
Inc(Index)
Wend
End Sub
{
****************************************************************************
* Name : WaitForStr *
* Purpose : Wait for a string to be received *
****************************************************************************
}
Public Sub WaitForStr(pStr As String)
Dim Index As Byte
ClearOverrun
Index = 0
While pStr(Index) <> null
If WaitFor(pStr(Index)) Then
Inc(Index)
Else
Index = 0
EndIf
Wend
End Sub
{
****************************************************************************
* Name : WaitForStrCount *
* Purpose : Wait for pAmount characters to be received. The incoming data *
* : is stored in pStr *
****************************************************************************
}
Public Sub WaitForStrCount(ByRef pStr As String, pCount As Word)
Dim Index As Byte
ClearOverrun
Index = 0
While pCount > 0
pStr(Index) = ReadByte
Dec(pCount)
Inc(Index)
Wend
pStr(Index) = null
End Sub
{
****************************************************************************
* Name : WaitForStrTimeout *
* Purpose : Wait for a string to be received, with timeout value in *
* : milliseconds *
****************************************************************************
}
Public Function WaitForStrTimeout(pStr As String, pTimeout As Word) As Boolean
Dim Counter, StrIndex As Byte
Dim Timeout As Word
Dim Ch As Byte
ClearOverrun
Result = false
StrIndex = 0
Counter = 10
Repeat
Timeout = pTimeout
While Timeout > 0
Ch = pStr(StrIndex)
If Ch = 0 Then
result = true
Exit
ElseIf DataAvailable Then
If Ch = RCRegister Then
Inc(StrIndex)
Else
StrIndex = 0
EndIf
EndIf
DelayUS(100)
Dec(Timeout)
Wend
Dec(Counter)
Until Counter = 0
End Function
{
****************************************************************************
* Name : DataAvailableTimeout *
* Purpose : Checks to see if a byte value has been received, with *
* : timeout in milliseconds *
****************************************************************************
}
Public Function DataAvailableTimeout(pTimeout As Word) As Boolean
Dim Counter As Byte
Dim Timeout As Word
ClearOverrun
Counter = 10
Repeat
Timeout = pTimeout
While (Timeout > 0) And Not DataAvailable
DelayUS(100)
Dec(Timeout)
Wend
Dec(Counter)
Until (Counter = 0) Or DataAvailable
result = DataAvailable
End Function
{
****************************************************************************
* Name : Rep *
* Purpose : Write a byte value, pAmount times *
****************************************************************************
}
Public Sub Rep(pValue, pAmount As Byte)
While pAmount > 0
WriteByte(pValue)
Dec(pAmount)
Wend
End Sub
{
****************************************************************************
* Name : Skip *
* Purpose : Read pAmount bytes *
****************************************************************************
}
Public Sub Skip(pAmount As Byte)
Dim Value As Byte
While pAmount > 0
Value = ReadByte
Dec(pAmount)
Wend
End Sub
// module initialisation...
ReadTerminator = null
#if _device in (18F1220, 18F1320)
ADCON1 = $60
#endif
Thanks
Hi,
Thanks for pointing that out Jerry and looking at it. I thought when ya specified the clock rate and part the compiler handled the Bit Error % for me. I will try the changes you suggested and see what I get.
Thanks
Thanks for pointing that out Jerry and looking at it. I thought when ya specified the clock rate and part the compiler handled the Bit Error % for me. I will try the changes you suggested and see what I get.
Thanks
-
- Swordfish Developer
- Posts: 1471
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
It does to a certain extent, but not completely. The decision to use 16-bit mode and the high speed baud rate is left to the user, and for some really slow rates at faster clocks, it's not really an option.
In my experience, your almost always better off using the 16-bit BRG with BRGH=1 (so set both those options true). I can't remember a case where this wasn't true (but I'm sure there are some).
In my experience, your almost always better off using the 16-bit BRG with BRGH=1 (so set both those options true). I can't remember a case where this wasn't true (but I'm sure there are some).
It's Alive !!!!!
Wheeeee!!!!!!!
Well Jerry is truly DA MAN!!!!!!
I finally got Hello World to come out with interrupts running thx to all here, and espically Jerry. I look forward to playing more with the Swordfish Compiler in the future, and hopefully I will get better at writing code.
Thanks again
Well Jerry is truly DA MAN!!!!!!
I finally got Hello World to come out with interrupts running thx to all here, and espically Jerry. I look forward to playing more with the Swordfish Compiler in the future, and hopefully I will get better at writing code.
Thanks again
Another Question
Hi,
Well I played around all nite with the interrupt routines running together and charcters definitly seems to come and go while the LED blinks. I did however run into a issue when trying to pull all of the bytes out of the RX buffer. It seems when I loop after a packet is received, and try to write the bytes out one at a time it gets through about 8 bytes then quits. If I send another packet into the unit from the PC I see the rest of the 1st packet come out and part of the second. I have added code to check the packet count and on the first packet it definitly see a count of 12 in length before it sets the flag. Is it possible the one second timer is messing up the routine pulling out bytes and sending them to the TX port ?
Thanks
While true
If SecCount = DelayTime Then
USART.Write("Hello World",$13,$10)
Toggle(LED1)
SecCount = 0
End If
While ISRRX.DataAvailable()
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
If (ByteCount = 12) Then
PacketFlag = true
' ISRRX.Reset
EndIf
Wend
If (PacketFlag) Then
'PacketFlag = false
USART.Write("Byte Count Value Is ",HexToStr(ByteCount),$13,$10)
' Timer0.Disabled()
// echo packet back out the uart
For I = 0 To (ByteCount-1)
USART.Write(RXData(I))
DelayMS(1)
Next
'USART.Write($13,$10)
If ((RXData(0) = $FE) And (RXData(1) = $13) And (RXData(3) = $04)) Then
USART.Write("MATCH",$13,$10)
Toggle(LED1)
EndIf
// prepare for next packet
ByteCount = 0
PacketFlag = false
' Timer0.Enabled()
EndIf
Wend
Well I played around all nite with the interrupt routines running together and charcters definitly seems to come and go while the LED blinks. I did however run into a issue when trying to pull all of the bytes out of the RX buffer. It seems when I loop after a packet is received, and try to write the bytes out one at a time it gets through about 8 bytes then quits. If I send another packet into the unit from the PC I see the rest of the 1st packet come out and part of the second. I have added code to check the packet count and on the first packet it definitly see a count of 12 in length before it sets the flag. Is it possible the one second timer is messing up the routine pulling out bytes and sending them to the TX port ?
Thanks
While true
If SecCount = DelayTime Then
USART.Write("Hello World",$13,$10)
Toggle(LED1)
SecCount = 0
End If
While ISRRX.DataAvailable()
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
If (ByteCount = 12) Then
PacketFlag = true
' ISRRX.Reset
EndIf
Wend
If (PacketFlag) Then
'PacketFlag = false
USART.Write("Byte Count Value Is ",HexToStr(ByteCount),$13,$10)
' Timer0.Disabled()
// echo packet back out the uart
For I = 0 To (ByteCount-1)
USART.Write(RXData(I))
DelayMS(1)
Next
'USART.Write($13,$10)
If ((RXData(0) = $FE) And (RXData(1) = $13) And (RXData(3) = $04)) Then
USART.Write("MATCH",$13,$10)
Toggle(LED1)
EndIf
// prepare for next packet
ByteCount = 0
PacketFlag = false
' Timer0.Enabled()
EndIf
Wend
-
- Swordfish Developer
- Posts: 1471
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Thanks Jerry
Hi Jerry,
Here is my whole serial test file. Thanks for taking a peek. I can sent the same 12 byte packet over and over manually and it repeats spitting out the same 7-8 bytes before it quits consistently. Like I said earlier when I send the packet again the rest of the previous packet comes out and part of the current one.
Packet I send manuallyfrom TX Window:
FE 1F 00 04 FE 1F 00 08 FE 1F 00 10
CODE:
// device and clock...
Device = 18F67J60
Clock = 25
Config FOSC = HSPLL
Config FOSC2 = ON
Config CP0 = OFF // Turn Code Protect On And Off
#option USART_BRGH = true
#option USART_BRG16 = true
Include "DL_Timer.bas"
Include "utils.bas"
Include "USARTM.bas"
Include "Convert.bas"
Include "isrrx.bas"
Dim LED As PORTB.5
Dim LED1 As PORTB.4
Dim VID_SWITCH As PORTB.3
Dim RXData(12) As byte
Dim ByteCount As Integer
Dim result As Boolean
Dim DelayTime As Word
Dim SecCount As Integer
Dim I As Integer
Dim Index As Byte
// variables...
Dim PacketFlag As Boolean
Dim RX_BYTE As Byte
Dim TMR0IP As INTCON2.2
Const ipLow = 1, ipHigh = 2
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR(ipLow)
'INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
' INTCON.7=1
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 10000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
Output(LED)
Output(LED1)
Output(VID_SWITCH)
USART.SetBaudrate(br4800)
ISRRX.Initialize // init the ISRRX module!
TMR0IP = 0 // set tmr0 intr to low priority
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
Enable(ISR) ' Start Interrupts
While true
If SecCount = DelayTime Then
USART.Write("Hello World",13,10)
Toggle(LED1)
SecCount = 0
End If
While ISRRX.DataAvailable()
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
If (ByteCount = 12) Then
PacketFlag = true
ISRRX.Reset
EndIf
Wend
If (PacketFlag) Then
'PacketFlag = false
'USART.Write("Byte Count Value Is ",DecToStr(ByteCount), 13 ,10)
' Timer0.Disabled()
// echo packet back out the uart
For I = 0 To (ByteCount-1)
USART.WritebYTE(RXData(I))
'DelayMS(1)
Next
If ((RXData(0) = $FE) And (RXData(1) = $1F) And (RXData(3) = $04)) Then
USART.Write("MATCH",$13,$10)
Toggle(LED1)
EndIf
// prepare for next packet
ByteCount = 0
PacketFlag = false
' Timer0.Enabled()
EndIf
Wend
Here is my whole serial test file. Thanks for taking a peek. I can sent the same 12 byte packet over and over manually and it repeats spitting out the same 7-8 bytes before it quits consistently. Like I said earlier when I send the packet again the rest of the previous packet comes out and part of the current one.
Packet I send manuallyfrom TX Window:
FE 1F 00 04 FE 1F 00 08 FE 1F 00 10
CODE:
// device and clock...
Device = 18F67J60
Clock = 25
Config FOSC = HSPLL
Config FOSC2 = ON
Config CP0 = OFF // Turn Code Protect On And Off
#option USART_BRGH = true
#option USART_BRG16 = true
Include "DL_Timer.bas"
Include "utils.bas"
Include "USARTM.bas"
Include "Convert.bas"
Include "isrrx.bas"
Dim LED As PORTB.5
Dim LED1 As PORTB.4
Dim VID_SWITCH As PORTB.3
Dim RXData(12) As byte
Dim ByteCount As Integer
Dim result As Boolean
Dim DelayTime As Word
Dim SecCount As Integer
Dim I As Integer
Dim Index As Byte
// variables...
Dim PacketFlag As Boolean
Dim RX_BYTE As Byte
Dim TMR0IP As INTCON2.2
Const ipLow = 1, ipHigh = 2
Event LEDFlash()
Toggle(LED)
SecCount = SecCount + 1000
End Event
Interrupt ISR(ipLow)
'INTCON.7=0
If Timer0.InterruptFlag =1 Then
Timer0.SInterrupt()
EndIf
' INTCON.7=1
End Interrupt
PacketFlag = false
ByteCount = 0
DelayTime = 10000
SecCount = 0
// setup serial port, ISRRX, etc
// clear buffer to start
Output(LED)
Output(LED1)
Output(VID_SWITCH)
USART.SetBaudrate(br4800)
ISRRX.Initialize // init the ISRRX module!
TMR0IP = 0 // set tmr0 intr to low priority
Timer0.Initialize(LEDFlash)
Timer0.SetPrescaler(Timer0.PS256)
Timer0.EightBit = 0
Timer0.Preload=49911
Timer0.EnableInterrupt()
Timer0.Enabled()
Enable(ISR) ' Start Interrupts
While true
If SecCount = DelayTime Then
USART.Write("Hello World",13,10)
Toggle(LED1)
SecCount = 0
End If
While ISRRX.DataAvailable()
RXData(ByteCount) = ISRRX.ReadByte()
Inc(ByteCount)
If (ByteCount = 12) Then
PacketFlag = true
ISRRX.Reset
EndIf
Wend
If (PacketFlag) Then
'PacketFlag = false
'USART.Write("Byte Count Value Is ",DecToStr(ByteCount), 13 ,10)
' Timer0.Disabled()
// echo packet back out the uart
For I = 0 To (ByteCount-1)
USART.WritebYTE(RXData(I))
'DelayMS(1)
Next
If ((RXData(0) = $FE) And (RXData(1) = $1F) And (RXData(3) = $04)) Then
USART.Write("MATCH",$13,$10)
Toggle(LED1)
EndIf
// prepare for next packet
ByteCount = 0
PacketFlag = false
' Timer0.Enabled()
EndIf
Wend