HSERIN using EUSART RX interrupt - how does it really work?


+ Reply to Thread
Results 1 to 8 of 8
  1. #1
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french part)
    Posts
    797

    Default HSERIN using EUSART RX interrupt - how does it really work?

    Hi all,

    I've made this small program to learn how the EUSART RX interrupt works....and it works BUT

    Yes, the code below works but I'm getting confused when I think about having unknown data length to be received. I'm not even sure that this code is really correct.

    In this example, I'm waiting for 5 charaters to be received. As long as 5 characters have not arrived, nothing will be printed out.

    And here is where I'm confused.

    Since the HSERIN command is in the ISR, each time I send a character from the Serial Communiactor, I expect the ISR the receive "at least" one character so the LED should toggle. But no, it doesn't. It seems to wait until all 5 characters have arrived and then, only then, the LED toggles.

    I don't get it....

    How shall I handle this please? What is the correct approach?

    Code:
    ' ====== FUSES ====================================================================================
    ' PIC 16F690 Fuses (MPASM)
    @ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
    @ ERRORLEVEL -306
    
    ' ====== REGISTERS =================================================================================
    OSCCON     = %01110000 'Internal RC set to 8Mhz - Register not to be used with XTal
    OPTION_REG = %10000000 'PORT A&B Pull-Ups (look WPUA & WPUB)
    ANSEL      = %00000000 'Select analog inputs Channels 0 to 7
    ANSELH     = %00000000 'Select analog inputs Channels 8 to 11
    INTCON     = %11000000 'INTERRUPT Control
    PIE1       = %00100000 'Peripheral Interrupts
    
    ' ====== UART SETTINGS ============================================================================
    RCSTA      = %10010000 ' Enable serial port & continuous receive
    TXSTA      = %00100000 ' Enable transmit, BRGH = 0
    SPBRG      = 12        ' 9600 Baud @ 8MHz, 0.16%
    
    ' ====== DEFINES ==================================================================================
    DEFINE OSC 8
    DEFINE NO_CLRWDT 1   ' Don't waste cycles clearing WDT  
    DEFINE HSER_CLOERR 1 ' Automatic clear overrun error 
    
    ' ====== VARIABLES ================================================================================
    LED     VAR PORTB.6
    SData   VAR BYTE(5)
    Print   VAR BIT
    
    '======= INITIALIZE ===============================================================================
    PORTB.5 = 1  ' set to avoid sending serial data garbage
    Print   = 0  ' send out serial data only if some is received
       
    '======= PROGRAM ==================================================================================
    ON INTERRUPT GOTO ISR
    
    MAIN:
        IF PRINT THEN
            Hserout [STR SData\5,13,10]
            Print = 0
        ENDIF    
        GOTO MAIN
    END    
    
    ' ====== INTERRUPT SERVICE ROUTINE ================================================================
        Disable
    ISR:
        HSerin [STR SData\5]
        PRINT = 1
        TOGGLE LED
        RESUME
        ENABLE
    Roger

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    1,840

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    ON INTERRUPT GOTO ISR
    i have great reservation that "on interrupt" will be successful @9600 with a 4mhz osc, use dt ints

    HSerin [STR SData\5]
    puts your 690 in a blocking loop until 5 characters have been received, no matter how long it takes
    its not isr material







    my take

    Code:
    ' ====== FUSES ====================================================================================' PIC 16F690 Fuses (MPASM)
    @ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
    @ ERRORLEVEL -306
    
    
    ' ====== REGISTERS =================================================================================
    OSCCON     = %01110000 'Internal RC set to 8Mhz - Register not to be used with XTal
    OPTION_REG = %10000000 'PORT A&B Pull-Ups (look WPUA & WPUB)
    ANSEL      = %00000000 'Select analog inputs Channels 0 to 7
    ANSELH     = %00000000 'Select analog inputs Channels 8 to 11
    INTCON     = %11000000 'INTERRUPT Control
    ;PIE1       = %00100000 'Peripheral Interrupts
    
    
    ' ====== UART SETTINGS ============================================================================
    RCSTA      = %10010000 ' Enable serial port & continuous receive
    TXSTA      = %00100000 ' Enable transmit, BRGH = 0
    SPBRG      = 12        ' 9600 Baud @ 8MHz, 0.16%
    
    
    ' ====== DEFINES ==================================================================================
    DEFINE OSC 8
    DEFINE NO_CLRWDT 1   ' Don't waste cycles clearing WDT  
    DEFINE HSER_CLOERR 1 ' Automatic clear overrun error 
    
    
    ' ====== VARIABLES ================================================================================
    LED     VAR PORTB.6
    SData   VAR BYTE(5)
    rx_count var byte
    rx_complete var bit
    rx_hit var bit
    ;Print   VAR BIT
    clear
    '======= INITIALIZE ===============================================================================
    PORTB.5 = 1  ' set to avoid sending serial data garbage
    ,Print   = 0  ' send out serial data only if some is received
       
    '======= PROGRAM ==================================================================================
    ON INTERRUPT GOTO ISR
    gosub rx_start
    MAIN:
        IF rx_complete THEN
            Hserout [STR SData\5,13,10]
            gosub rx_start
        ENDIF 
         IF rx_hit THEN 
          TOGGLE LED
          rx_hit=0
         endif  
        GOTO MAIN
    END    
    
    
    rx_start        ;resume /start    rx
        RCSTA.4=0  ;clear any rcsta error
        RCSTA.4=1
        rx_count=0
        rx_complete=0
        PIE1.5=1
    return
    
    
    ' ====== INTERRUPT SERVICE ROUTINE ================================================================
        Disable
    ISR:
        sdata[rx_count]=RCREG
        rx_hit=1
        rx_count=rx_count+1
        if  rx_count==5 then   ;stop rx for now
        rx_complete=1
        PIE1.5=0
        endif
        RESUME
        ENABLE
    This is more entertaining than Free to Air TV

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    1,840

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    since most chips have a rxbuffer you could also take advantage of


    Code:
    ISR:
        rx_hit=1
        while pir1.5
           sdata[rx_count]=RCREG   
           rx_count=rx_count+1    
           if  rx_count==5 then   ;stop rx for now
    
               rx_complete=1
               PIE1.5=0
           endif
        wend
    
        RESUME
        ENABLE
    This is more entertaining than Free to Air TV

  4. #4
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french part)
    Posts
    797

    Default HSERIN using EUSART RX interrupt - how does it really work?

    Thank you Richard,

    Actually, my program works on a 8MHz basis - it should be more than enough to handle 9600bps serial data, no?

    I'd like to stick to the very basics since I'm not an ultra-programming-geek (just a curious guy). I often heard and read about DT's interrupts but it looks "too much" to me, a least, for my so small projects.


    HSerin [STR SData\5]
    puts your 690 in a blocking loop until 5 characters have been received, no matter how long it takes its not isr material
    Thanks a lot for explaining this.


    As far as I read the DS, the RX buffer can store 2 characters. Starting this thread, my example was using a 5 characters but in fact, I will always have unknown data length (I'll read sms messages) - so let's forget the 5 characters story

    Since you refer to it, why is there a buffer of "2" characters? What's its use?


    This is my latest code I modified to receive 1 character at the time giving the chance of handling variable lenght incoming data:
    Code:
    ' ====== FUSES ====================================================================================
    ' PIC 16F690 Fuses (MPASM)
    @ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
    @ ERRORLEVEL -306
    
    ' ====== REGISTERS =================================================================================
    OSCCON     = %01110000 'Internal RC set to 8Mhz - Register not to be used with XTal
    OPTION_REG = %10000000 'PORT A&B Pull-Ups (look WPUA & WPUB)
    ADCON0     = %00000000 'A/D Module
    ANSEL      = %00000000 'Select analog inputs Channels 0 to 7
    ANSELH     = %00000000 'Select analog inputs Channels 8 to 11
    INTCON     = %11000000 'INTERRUPT Control
    PIE1       = %00100000 'Peripheral Interrupts
    
    ' ====== UART SETTINGS ============================================================================
    RCSTA      = %10010000 ' Enable serial port & continuous receive
    TXSTA      = %00100000 ' Enable transmit, BRGH = 0
    SPBRG      = 12        ' 9600 Baud @ 8MHz, 0.16%
    
    ' ====== DEFINES ==================================================================================
    DEFINE OSC 8
    DEFINE NO_CLRWDT 1   ' Don't waste cycles clearing WDT  
    DEFINE HSER_CLOERR 1 ' Automatic clear overrun error 
    
    ' ====== VARIABLES ================================================================================
    LED     VAR PORTB.6
    SData   VAR BYTE(5)
    Print   VAR BIT
    
    '======= INITIALIZE ===============================================================================
    PORTB.5 = 1         ' set to avoid sending serial data garbage
    Print   = 0
    
    '======= PROGRAM ==================================================================================
    ON INTERRUPT GOTO ISR
    
    MAIN:
        IF PRINT THEN
            HSEROUT [SData]
            Print = 0
        ENDIF    
        GOTO MAIN
    END    
    
    ' ====== INTERRUPT SERVICE ROUTINE ================================================================
        Disable
    ISR:
        PRINT = 1
    	HSerin [SData]
    	Resume
        ENABLE

    Looks like a silly question, but, can I trust this code? Will it work @ 100%? Could something make it hang or stop?

    BTW, thanks for your code - I'm playing with it trying to understand it
    Last edited by flotulopex; - 24th January 2021 at 10:28.
    Roger

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,329

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    Since you refer to it, why is there a buffer of "2" characters? What's its use?
    First, there's the actual shiftregister into which the data is shifted bit-by-bit as it's received. You don't have access to this register (AFAIK).
    Once the correct number of bits have been shifted in they are copied to RCREG (where you can read it) and the interrupt flag is set. Now the user code needs to grab the byte from RCREG before a new byte is fully shifted in. So there's your two byte buffer.

    Looks like a silly question, but, can I trust this code? Will it work @ 100%? Could something make it hang or stop?
    Using ON INTERRUPT is tricky since all it does is poll the interrupt flag BETWEEN PBP statements. What that means is that if you have a PBP statement that takes considerable time the execution of the interrupt handler will be postponed for (up to) that amount of time. In your case, I don't see any issue but lets say that, instead of HSEROUT[SData] in the main loop, you had done HSEROUT["The received byte is: ", SData] then the execution time of that complete statement is longer than the time between two received characters and it would not work properly.

    /Henrik.

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    1,840

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    Actually, my program works on a 8MHz basis - it should be more than enough to handle 9600bps serial data, no?
    probably not , on interrupt is not suitable for processing async data streams in any useful way without flow control
    if there is a "real" foreground task being processed incurring data loss is inevitable

    Since you refer to it, why is there a buffer of "2" characters? What's its use?
    a simple fifo buffer gives you a little bit more time to process the rx data without loss
    @9600 its about 100uS at best

    I will always have unknown data length (I'll read sms messages)
    to approach a task like that you need to have a good understanding of what the message data will look like
    eg is there a start chr? is there and end chr eg /n or /r , does the message have its length encoded in it? is there a chksum or crc
    what is the maximum and minimum length

    there is zero benefit in having an isr capture one chr at a time then immediately pass it back to the foreground task.
    your isr would ideally allow the foreground tasks proceed unhindered by the rx process until a message was
    received and ready to process


    dt ints is not difficult the forum abounds with examples
    This is more entertaining than Free to Air TV

  7. #7
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french part)
    Posts
    797

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    Thanks Henrik, thanks Richard.

    I have some homework to do following your info
    Roger

  8. #8
    Join Date
    Apr 2014
    Location
    Northeast
    Posts
    354

    Default Re: HSERIN using EUSART RX interrupt - how does it really work?

    I assume you already found this, but several members compiled a book on using DT Interrupts:

    http://www.picbasic.co.uk/forum/forumdisplay.php?f=41

    Just in case you haven't seen it.

Similar Threads

  1. Need help: hserin, serin and serin2 does not work for me
    By PerlNoerd in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 3rd February 2014, 21:09
  2. HSERIN + interrupt
    By tacbanon in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 21st April 2012, 14:37
  3. HSERIN with/without interrupt
    By macinug in forum Serial
    Replies: 3
    Last Post: - 19th January 2009, 17:03
  4. HSERIN doesnt work
    By wurm in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 29th July 2007, 14:23
  5. USB and Interrupt - can it work together ?
    By Shamir in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 3rd October 2006, 22:24

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts