Interrupts

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Interrupts

Post by Widgetman » Tue Mar 15, 2011 12:50 pm

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

Jerry Messina
Swordfish Developer
Posts: 1471
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Tue Mar 15, 2011 6:35 pm

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)

Code: Select all

const 
   ipLow = 1, 
   ipHigh = 2 
 
interrupt OnTimer1(ipLow) 
   // code statements here
end interrupt 
 
interrupt OnTimer3(ipHigh) 
   // code statements here
end interrupt 
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.

Code: Select all

Interrupt ISR(ipLow)
     If Timer0.InterruptFlag =1 Then
        Timer0.SInterrupt()      
     EndIf
End Interrupt

dim TMR0IP as INTCON2.2
and add the following before calling Timer0.Initialize()

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
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?)

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Thanks Jerry

Post by Widgetman » Wed Mar 16, 2011 2:03 pm

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 :)

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Few More Questions

Post by Widgetman » Wed Mar 16, 2011 4:05 pm

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

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

trial # 2

Post by Widgetman » Wed Mar 16, 2011 4:45 pm

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

Jerry Messina
Swordfish Developer
Posts: 1471
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Wed Mar 16, 2011 5:50 pm

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

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

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Thanks

Post by Widgetman » Wed Mar 16, 2011 6:25 pm

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. :)

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Post by Widgetman » Thu Mar 17, 2011 1:53 pm

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

Jerry Messina
Swordfish Developer
Posts: 1471
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Thu Mar 17, 2011 2:46 pm

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

Code: Select all

Interrupt OnTimer1(ipLow)
// code statements here
End Interrupt

Interrupt OnTimer3(ipHigh)
// code statements here
End Interrupt 
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

Code: Select all

dim   SPBRGRegister As SPBRG.AsWord,

Public Sub SetBaudrate(pSPBRG As SPBRGRegister = br19200)
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

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   
I should point out that not all chips have a 16-bit BRG, so the above won't compile without some changes for those.

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Thanks

Post by Widgetman » Thu Mar 17, 2011 5:08 pm

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

Jerry Messina
Swordfish Developer
Posts: 1471
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Thu Mar 17, 2011 5:19 pm

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).

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

It's Alive !!!!!

Post by Widgetman » Thu Mar 17, 2011 5:20 pm

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

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Another Question

Post by Widgetman » Fri Mar 18, 2011 11:42 am

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

Jerry Messina
Swordfish Developer
Posts: 1471
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Fri Mar 18, 2011 12:59 pm

Could you post the whole file? I need to see the rest of it.

Widgetman
Posts: 136
Joined: Sun Dec 16, 2007 7:39 pm
Location: Florida

Thanks Jerry

Post by Widgetman » Fri Mar 18, 2011 1:24 pm

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

Post Reply