USART2 interupt

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

USART2 interupt

Post by garryp4 » Tue Dec 29, 2020 10:13 pm

How can I setup USART2 to process an interrupt? Can I used ISRRX with both USART1 and USART2 at the same time? I need to get data from which ever has it available at the time.

Thanks

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

Re: USART2 interupt

Post by Jerry Messina » Wed Dec 30, 2020 12:27 am

If all you want to do is use ISRRX to handle USART2, then just set the option RX_USART_SELECT:

Code: Select all

#option RX_USART_SELECT = 2
include "isrrx.bas"
If you want to use two uarts then that won't do it.

Do you need to use any other interrupts? By default, two copies of ISRRX would chew up both interrupts on most devices.
I can post a modified ISRRX2.bas tomorrow, and that way you'd be able to handle two uarts.

What device are you interested in and I'll be sure to test it for that one.

garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Re: USART2 interupt

Post by garryp4 » Wed Dec 30, 2020 2:07 pm

Jerry:

Thanks! I am using an 18F47J13 and an 18F27J13. The serial is the only interrupt for this project.

Garry

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

Re: USART2 interupt

Post by Jerry Messina » Wed Dec 30, 2020 2:33 pm

I have a version of ISRRX2 that you can use along with ISRRX which uses both interrupts... you set one as ipHigh and the other as ipLow.
I also have provisions for using both of those modules along with a user-defined ISR so they can share a single interrupt (untested).

I think I have a 27J13 around here somewhere... let me dig it up and I'll make sure it all works before I post them.

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

Re: USART2 interupt

Post by Jerry Messina » Wed Dec 30, 2020 6:13 pm

Garry -

Here's a copy of the new ISRRX2 module, along with updated ISRRX and PPS modules.
There's an example program in there too: J13_isrrx1_isrrx2.bas

Code: Select all

// ISRRX and ISRRX2 example
device = 18F27J13
clock = 32

include "intosc.bas"
#option DIGITALIO_INIT = true   // automatically call SetAllDigital at startup
include "setdigitalio.bas"
include "pps.bas"

// 27J13 (VDD=3V3, 5V tol pins)
// TX1  RC6/RP17
// RX1  RC7/RP18
// TX2  RC4/RP15 (PPS)
// RX2  RC5/RP16 (PPS)

//
// If you are using a device with PPS mapped pins then set the #options
// 'USARTx_TX' and 'USARTx_RX' to match the port pins you're using before
// including the USARTx.bas module... you'll still have to setup the PPS
// NOTE: if the pins have analog capability it is up to the user to set 
// the respective pins to digital IO mode (ie setalldigital)
//

// ISRRX setup
// select USARTx and import library...
#option USART_TX = PORTC.6         // usart TX output
#option USART_RX = PORTC.7         // usart RX input
include "USART.bas"

#option RX_USART_SELECT = 1
#option RX_BUFFER_SIZE = 32
#option RX_PRIORITY = ipHigh
include "ISRRX.bas"

// ISRRX2 setup
// select USARTx and import library...
#option USART2_TX = PORTC.4         // usart2 TX output (pps mapped)
#option USART2_RX = PORTC.5         // usart2 RX input (pps mapped)
include "USART2.bas"

#option RX2_USART_SELECT = 2
#option RX2_BUFFER_SIZE = 32
#option RX2_PRIORITY = ipLow
include "ISRRX2.bas"

dim rxc as byte

// assign uart2 pps pins (18F27J13)
pps.unlock()
pps.assign_output(PPS_TX2, PPS_OUT_RP15)     // PORTC.4
pps.assign_input(PPS_RX2, PPS_IN_RP16)       // PORTC.5

// ISRRX (uart1)
USART.SetBaudrate(br115200)
ISRRX.Initialize()
// ISRRX2 (uart2)
USART2.SetBaudrate(br115200)
ISRRX2.Initialize()

// loop forever...
while true
   // report an error...
   if ISRRX.Overrun() then
      ISRRX.Reset()
   endif

   // read data from the buffer...
   while ISRRX.DataAvailable()
      rxc = ISRRX.ReadByte()
   end while

   // report an error...
   if ISRRX2.Overrun() then
      ISRRX2.Reset()
   endif

   // read data from the buffer...
   while ISRRX2.DataAvailable()
      rxc = ISRRX2.ReadByte()
   end while
end while

There are provisions in the new ISRRX modules to add a user-defined interrupt routine so that you can combine them into a single ISR,
but I didn't include an example of that for now.

Just unzip the files ISRRX.bas, ISRRX2.bas, and PPS.bas into the UserLibrary folder.

Let me know how it goes and if it all works for you I'll include these in the next update.
Attachments
18F27J13_ISRRX.zip
(16.91 KiB) Downloaded 116 times

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

Re: USART2 interupt

Post by Jerry Messina » Thu Dec 31, 2020 4:51 pm

Here's an example of using the new user-defined interrupt feature of ISRRX and ISRRX2 to share a single ISR, freeing up the low-priority interrupt for other uses.

Code: Select all

// ISRRX and ISRRX2 example using a single ISR
// requires ISRRX and ISRRX2 v1.3 or later
device = 18F27J13
clock = 32

include "intosc.bas"
#option DIGITALIO_INIT = true   // automatically call SetAllDigital at startup
include "setdigitalio.bas"
include "pps.bas"

// 27J13 (VDD=3V3, 5V tol pins)
// TX1  RC6/RP17
// RX1  RC7/RP18
// TX2  RC4/RP15 (PPS)
// RX2  RC5/RP16 (PPS)

//
// If you are using a device with PPS mapped pins then set the #options
// 'USARTx_TX' and 'USARTx_RX' to match the port pins you're using before
// including the USARTx.bas module... you'll still have to setup the PPS
// NOTE: if the pins have analog capability it is up to the user to set 
// the respective pins to digital IO mode (ie setalldigital)
//

// set option true to use a single user-defined ISR for both ISRRX and ISRRX2
#option ISRRX_USER_ISR = true
#if (ISRRX_USER_ISR = true)
  #option RX_USER_ISR = true
  #option RX_PRIORITY = ipHigh
  #option RX2_USER_ISR = true
  #option RX2_PRIORITY = ipHigh

  #if (RX_PRIORITY <> RX2_PRIORITY)
    #error ISRRX_USER_ISR, "this demo requires both ISRRX and ISRRX2 to have the same priority"
  #endif
#endif

// ISRRX setup
// select USART1 and import library...
#option USART_TX = PORTC.6         // usart TX output
#option USART_RX = PORTC.7         // usart RX input
include "USART.bas"

#option RX_USART_SELECT = 1
#option RX_BUFFER_SIZE = 32
#option RX_PRIORITY = ipHigh
include "ISRRX.bas"

// ISRRX2 setup
// select USART2 and import library...
#option USART2_TX = PORTC.4         // usart2 TX output (pps mapped)
#option USART2_RX = PORTC.5         // usart2 RX input (pps mapped)
include "USART2.bas"

#option RX2_USART_SELECT = 2
#option RX2_BUFFER_SIZE = 32
#option RX2_PRIORITY = ipLow
include "ISRRX2.bas"


// on RX data event, replace '.' with '-'
event OnData()
   if (ISRRX.DataChar = ".") then
      ISRRX.DataChar = "-"
   endif   
end event

// on RX2 data event, replace '.' with '+'
event OnData2()
   if (ISRRX2.DataChar = ".") then
      ISRRX2.DataChar = "+"
   endif   
end event

// shared user-defined ISR 
#if (ISRRX_USER_ISR = true)
interrupt UserRX1RX2(ISRRX.PriorityLevel)
    if (USART.RCIF = 1) and (USART.RCIE = 1) then
        ISRRX.Rx_intr_handler()
    endif
    if (USART2.RCIF = 1) and (USART2.RCIE = 1) then
        ISRRX2.Rx_intr_handler()
    endif
end interrupt    
#endif

dim rxc as byte

// assign uart2 pps pins (18F27J13)
pps.unlock()
pps.assign_output(PPS_TX2, PPS_OUT_RP15)     // PORTC.4
pps.assign_input(PPS_RX2, PPS_IN_RP16)       // PORTC.5

// ISRRX (uart1)
USART.SetBaudrate(br115200)
ISRRX.Initialize(OnData)
// ISRRX2 (uart2)
USART2.SetBaudrate(br115200)
ISRRX2.Initialize(OnData2)

// enable shared ISR handler
#if (ISRRX_USER_ISR = true)
  enable(UserRX1RX2)
#endif

// loop forever...
while true
   // report an error...
   if ISRRX.Overrun() then
      ISRRX.Reset()
   endif

   // read data from the buffer...
   while ISRRX.DataAvailable()
      rxc = ISRRX.ReadByte()
   end while

   // report an error...
   if ISRRX2.Overrun() then
      ISRRX2.Reset()
   endif

   // read data from the buffer...
   while ISRRX2.DataAvailable()
      rxc = ISRRX2.ReadByte()
   end while
end while

garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Re: USART2 interupt

Post by garryp4 » Sat Jan 02, 2021 3:42 pm

Jerry:

Thanks! I will try it out tomorrow.

garryp4
Posts: 125
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Re: USART2 interupt

Post by garryp4 » Sun Jan 03, 2021 7:03 pm

Jerry:

I took a crack at ti but think I am not coding it correctly. The circuit has usart1 connected to hterm and usart2 to a Digi Zigbee radio. I know it all works because my program does send and receive from both ports. I want to use the interrupts because I never know when data will come across either port.

Here is your example with changes I tried. I noted the lines I am not usre about with "*********' in the comments so are easier to find.

Code: Select all

// ISRRX and ISRRX2 example using a single ISR
// requires ISRRX and ISRRX2 v1.3 or later
Device = 18F27J13
Clock = 8

Include "intosc.bas"
#option DIGITALIO_INIT = true   // automatically call SetAllDigital at startup
Include "setdigitalio.bas"
Include "pps.bas"
Include "DOWNFIELD_RADIO.bas"

// 27J13 (VDD=3V3, 5V tol pins)
// TX1  RC6/RP17
// RX1  RC7/RP18
// TX2  RC4/RP15 (PPS)
// RX2  RC5/RP16 (PPS)

//
// If you are using a device with PPS mapped pins then set the #options
// 'USARTx_TX' and 'USARTx_RX' to match the port pins you're using before
// including the USARTx.bas module... you'll still have to setup the PPS
// NOTE: if the pins have analog capability it is up to the user to set 
// the respective pins to digital IO mode (ie setalldigital)
//

// set option true to use a single user-defined ISR for both ISRRX and ISRRX2
#option ISRRX_USER_ISR = true
#if (ISRRX_USER_ISR = true)
  #option RX_USER_ISR = true
  #option RX_PRIORITY = ipHigh
  #option RX2_USER_ISR = true
  #option RX2_PRIORITY = ipHigh

  #if (RX_PRIORITY <> RX2_PRIORITY)
    #error ISRRX_USER_ISR, "this demo requires both ISRRX and ISRRX2 to have the same priority"
  #endif
#endif

// ISRRX setup
// select USART1 and import library...
'#option USART_TX = PORTC.6         // usart TX output
'#option USART_RX = PORTC.7         // usart RX input
Include "USART.bas"

#option RX_USART_SELECT = 1
#option RX_BUFFER_SIZE = 32
#option RX_PRIORITY = ipHigh
Include "ISRRX.bas"

// ISRRX2 setup
// select USART2 and import library...
#option USART2_TX = PORTB.1            ' usart2 TX output (pps mapped) 
#option USART2_RX = PORTB.0            ' usart2 RX input (pps mapped) 
Include "USART2.bas"

#option RX2_USART_SELECT = 2
#option RX2_BUFFER_SIZE = 32
#option RX2_PRIORITY = ipLow
Include "ISRRX2.bas"

Config IOL1WAY = OFF
  
// on RX data event, replace '.' with '-'
Event OnData()
  usart.read(message1)           ' ********** What am I doing wrong here?
  USART.write(message1)

'   If (ISRRX.DataChar = ".") Then
'      ISRRX.DataChar = "-"
'   EndIf   
End Event

// on RX2 data event, replace '.' with '+'
Event OnData2()
  ISRRX2.ReadStr(message2)
  USART.write(message2)
  
'   If (ISRRX2.DataChar = ".") Then
'      ISRRX2.DataChar = "+"
'   EndIf   
End Event

// shared user-defined ISR 
#if (ISRRX_USER_ISR = true)
Interrupt UserRX1RX2(ISRRX.PriorityLevel)
    If (USART.RCIF = 1) And (USART.RCIE = 1) Then
        ISRRX.RX_intr_handler()
    EndIf
    If (USART2.RCIF = 1) And (USART2.RCIE = 1) Then
        ISRRX2.RX_intr_handler()
    EndIf
End Interrupt    
#endif

Private Dim
  message1     As String,
  message2     As String
'  rxc          As Byte
  
// assign uart2 pps pins (18F27J13)
  pps.unlock()
  pps.assign_input(PPS_RX2, PPS_IN_RP3)   ' RB.0
  pps.assign_output(PPS_TX2, PPS_OUT_RP4) ' RB.1
  pps.lock()

  
'pps.unlock()
'pps.assign_output(PPS_TX2, PPS_OUT_RP15)     // PORTC.4
'pps.assign_input(PPS_RX2, PPS_IN_RP16)       // PORTC.5


'************
' Digi XBee radio is on serial 2 PPS. RADIO_INIT puts a message to 
' hterm so it works. Been doing the same with the radio for years
DOWNFIELD_RADIO.RADIO_INIT


// ISRRX (uart1)
USART.SetBaudrate(br9600)
USART.ReadTerminator = "*"
ISRRX.Initialize(OnData)
// ISRRX2 (uart2)
'USART2.SetBaudrate(br115200)
USART2.SetBaudrate(br9600)
USART2.ReadTerminator = "*"
ISRRX2.Initialize(OnData2)

// enable shared ISR handler
#if (ISRRX_USER_ISR = true)
  Enable(UserRX1RX2)
#endif

message1 = ""
message2 = ""

// loop forever...
While true
   // report an error...
   If ISRRX.Overrun() Then
      ISRRX.Reset()
   EndIf

   // read data from the buffer...
   While ISRRX.DataAvailable()
     USART2.write("&",message1,",*")          ' ********** this correct? 
     message1 = ""
'     rxc = ISRRX.ReadByte()
   End While

   // report an error...
   If ISRRX2.Overrun() Then
      ISRRX2.Reset()
   EndIf

   // read data from the buffer...
   While ISRRX2.DataAvailable()
     USART.write("&",message2,",*")
     message2 = ""
'     rxc = ISRRX2.ReadByte()
   End While
End While
I greatly appreciate your time and talent!

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

Re: USART2 interupt

Post by Jerry Messina » Mon Jan 04, 2021 12:50 am

Two things...

- Once you're using ISRRX then all read data has to come from the buffering in that module. Don't use UART.Read anything, you have to use the read routines in ISRRX
- The ISRRX OnData event is called each time a char comes in, so you normally wouldn't try to read anything inside it.

To be honest, I normally don't use any of the read routines in ISRRX except for ReadByte(). You have to wait for DataAvailable() to signal that there's a char in the buffer, and all various ReadXXXX routines don't do that. I do all the message building and char detection in my own routines so I don't have any simple examples of doing that.


Here's a simple example that echos chars from uart1 <--> uart2

Code: Select all

// ISRRX and ISRRX2 example using a single ISR
// requires ISRRX and ISRRX2 v1.3 or later
Device = 18F27J13
Clock = 8

Include "intosc.bas"
#option DIGITALIO_INIT = true   // automatically call SetAllDigital at startup
Include "setdigitalio.bas"
Include "pps.bas"
Include "DOWNFIELD_RADIO.bas"

// 27J13 (VDD=3V3, 5V tol pins)
// TX1  RC6/RP17
// RX1  RC7/RP18
// TX2  RC4/RP15 (PPS)
// RX2  RC5/RP16 (PPS)

//
// If you are using a device with PPS mapped pins then set the #options
// 'USARTx_TX' and 'USARTx_RX' to match the port pins you're using before
// including the USARTx.bas module... you'll still have to setup the PPS
// NOTE: if the pins have analog capability it is up to the user to set 
// the respective pins to digital IO mode (ie setalldigital)
//

// set option true to use a single user-defined ISR for both ISRRX and ISRRX2
#option ISRRX_USER_ISR = true
#if (ISRRX_USER_ISR = true)
  #option RX_USER_ISR = true
  #option RX_PRIORITY = ipHigh
  #option RX2_USER_ISR = true
  #option RX2_PRIORITY = ipHigh

  #if (RX_PRIORITY <> RX2_PRIORITY)
    #error ISRRX_USER_ISR, "this demo requires both ISRRX and ISRRX2 to have the same priority"
  #endif
#endif

// ISRRX setup
// select USART1 and import library...
#option USART_TX = PORTC.6         // usart TX output
#option USART_RX = PORTC.7         // usart RX input
Include "USART.bas"

#option RX_USART_SELECT = 1
#option RX_BUFFER_SIZE = 32
#option RX_PRIORITY = ipHigh
Include "ISRRX.bas"

// ISRRX2 setup
// select USART2 and import library...
#option USART2_TX = PORTB.1            ' usart2 TX output (pps mapped) 
#option USART2_RX = PORTB.0            ' usart2 RX input (pps mapped) 
Include "USART2.bas"

#option RX2_USART_SELECT = 2
#option RX2_BUFFER_SIZE = 32
#option RX2_PRIORITY = ipLow
Include "ISRRX2.bas"

Config IOL1WAY = OFF
  
// shared user-defined ISR 
#if (ISRRX_USER_ISR = true)
Interrupt UserRX1RX2(ISRRX.PriorityLevel)
    If (USART.RCIF = 1) And (USART.RCIE = 1) Then
        ISRRX.RX_intr_handler()
    EndIf
    If (USART2.RCIF = 1) And (USART2.RCIE = 1) Then
        ISRRX2.RX_intr_handler()
    EndIf
End Interrupt    
#endif

dim  rxc as byte
  
// assign uart2 pps pins (18F27J13)
  pps.unlock()
  pps.assign_input(PPS_RX2, PPS_IN_RP3)   ' RB.0
  pps.assign_output(PPS_TX2, PPS_OUT_RP4) ' RB.1
  pps.lock()

'************
' Digi XBee radio is on serial 2 PPS. RADIO_INIT puts a message to 
' hterm so it works. Been doing the same with the radio for years
DOWNFIELD_RADIO.RADIO_INIT


// ISRRX (uart1)
USART.SetBaudrate(br9600)
ISRRX.Initialize()
// ISRRX2 (uart2)
USART2.SetBaudrate(br9600)
ISRRX2.Initialize()

// enable shared ISR handler
#if (ISRRX_USER_ISR = true)
  Enable(UserRX1RX2)
#endif

// loop forever...
While true
   // reset any input errors
   If ISRRX.Overrun() Then
      ISRRX.Reset()
   EndIf

   // read data from the uart1 buffer and send it to uart2...
   While ISRRX.DataAvailable()
      rxc = ISRRX.ReadByte()
      USART2.WriteByte(rxc)
   End While

   // reset any input errors
   If ISRRX2.Overrun() Then
      ISRRX2.Reset()
   EndIf

   // read data from the uart2 buffer and send it to uart2...
   While ISRRX2.DataAvailable()
      rxc = ISRRX2.ReadByte()
      USART.WriteByte(rxc)
   End While
End While

Post Reply