Announcement

Collapse
No announcement yet.

PIC16F18326 EUART probrem

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PIC16F18326 EUART probrem

    Hello everyone.

    I am trying EUART asynchronous RS232C communication now.

    The CODE of the relevant part is as follows.
    When the PIC receives DATA from PC, it enters an interrupt loop and displays the DATA on the I2C LCD.

    When I send "ABCDEF" by "Serial Communicator" from PC,
    it enter to the interrupt loop, but stops at the line of "Hserin".
    When I send same DATA again, "ABABCD" is displayed on the LCD.
    But it cannot return to the MAIN LOOP from the interrupt loop.

    I think the cause of this probrem is "DEFINE HSER_CLROERR 1".
    According to the instructions (P151);
    As the hardware serial port only has a 2byte input buffer, it can easily overflow if characters are not read from it often enough.
    When this happens, the USART stops accepting new characters and needs to e reset.
    This overflow error can e reset by toggling the CREN bit inthe RCSTA register.
    A DEFINE can be used to automatically clear this error.
    You will not know that an error has occurred and characters may have been lost.

    I guessed the following steps from the characters displayed on the LCD.
    step1 Receive 1 byte (DATA: A) ... go to Interrupt Loop
    step2 Receive 2 bytes (DATA: B), buffer becomes full and stop receiving, DATA: C, D, E cannot be received.
    step3 A and B are transferred to array [0] [1].
    step4 The data is not full of the demanding of "hserin [ str array\6]" and stagnates at that line of hserin
    step5 Receive the second same DATA, received ABCDEF, and transfer to array [2,3,4,5]
    step6 Display "ABABCD" on LCD, lack E and F
    step7 It can't resume to Main loop, because "E,F" still in the buffer.

    I want to solve the problem of not being able to receive data properly when an interrupt occurs and the problem of not being able to return to main from an interrupt.
    Please teach me how to solve it.

    Code:
    #CONFIG
    __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_ON & _FCMEN_ON
    __config _CONFIG2, _MCLRE_OFF & _PWRTE_OFF & _WDTE_ON & _LPBOREN_OFF & _BOREN_ON & _BORV_LOW & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
    __config _CONFIG3, _WRT_OFF & _LVP_OFF
    __config _CONFIG4, _CP_OFF & _CPD_OFF
    
    #ENDCONFIG
    
    OSCCON1 = %00000000
    OSCCON2 = %01100100
    OSCFRQ = %00000110
    define OSC 32
    
    ANSELA = %00000111
    ANSELC = %00000000
    
    TRISA = %00001111
    TRISC = %00101000
    
    INTCON = %11000000 '割込準備
    PIE1 = %00100000
    PIR1.5 = 0
    
    on interrupt goto Interrupt_Loop
    
    '===================================================
    define HSER_TXSTA 24h
    define HSER_RCSTA 90h
    define HSER_BAUD 19200
    define HSER_CLROERR 1
    RCSTA.4=0
    RCSTA.4=1
    '===================================================
    
    RC4PPS = %00010100 'PORTC.4 as TX
    RXPPS   = %00010101 'PORTC.5 as RX
    
    
    Array var byte[8]
    
    MAIN:  ***********MAIN LOOP *********************************
    
      I2CWRITE sda,scl,s_add,cont,[$80] : pause 1
      I2CWRITE sda,scl,s_add,dat,["Checking"] : pause 1
    
      pause 250
    
    goto MAIN
    
    disable '<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
    
    Interrupt_loop:
    
    I2CWRITE sda,scl,s_add,cont,[$01] : pause 1 
    I2CWRITE sda,scl,s_add,dat,["RECEIVED"] : pause 1 
    
    
      hserin [str Array\6]
    
      I2CWRITE sda,scl,s_add,dat,[TWE[0]] : pause 1 
      I2CWRITE sda,scl,s_add,dat,[TWE[1]] : pause 1 
      I2CWRITE sda,scl,s_add,dat,[TWE[2]] : pause 1 
      I2CWRITE sda,scl,s_add,dat,[TWE[3]] : pause 1 
      I2CWRITE sda,scl,s_add,dat,[TWE[4]] : pause 1 
      I2CWRITE sda,scl,s_add,dat,[TWE[5]] : pause 1 
    
      pause 3000 
    
    
    INTCON = %11000000
    PIR1.5 = 0
    RCSTA.4 = 0
    RCSTA.4 = 1
    
    resume
    
    enable
    
    end

  • #2
    All of those PAUSE statements aren't going the interrupt routine any good. You should just receive the character string and set a flag that data has been received . In your main loop check the integrity of the flag and if set, clear it and display the received data. You have 2 milliseconds being wasted after receiving the interrupt and the USART receives the first single character, not to mention the other 6 milliseconds to send the data to the display and then another 3 seconds before you leave the routine.
    Dave Purola,
    N8NTA
    EN82fn

    Comment


    • #3
      Dear Mr.DavidP

      Thank you for advice. I tried to edit code as following.
      You pointed out about "delay" and "pause", so;

      Code:
      Array var byte[8]
      
      MAIN: ***********MAIN LOOP *********************************
      
      I2CWRITE sda,scl,s_add,cont,[$80] : pause 1
      I2CWRITE sda,scl,s_add,dat,["Checking"] : pause 1
      
      Arraywrite array, ["00000000"]
      
      pause 250
      
      goto MAIN
      
      disable '<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
      
      Interrupt_loop:
      
      hserin 500, Time_up, [str Array\6]    '--- Once in the interrupt loop, transfer received data to Array.
      
      Time_up:
      
      I2CWRITE sda,scl,s_add,cont,[$01] : pause 1
      I2CWRITE sda,scl,s_add,dat,["RECEIVED"] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[0]] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[1]] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[2]] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[3]] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[4]] : pause 1
      I2CWRITE sda,scl,s_add,dat,[Array[5]] : pause 1
      
      pause 3000     '--- CHECK LCD ----- 
      
      INTCON = %11000000
      PIR1.5 = 0
      RCSTA.4 = 0
      RCSTA.4 = 1
      
      resume
      
      enable
      I sent "ABCDEF" from PC same as previous test.
      The result is displayed "AB0000"
      "0000" was substituted at Main Loop, so only 2 bytes could be received.

      I set 500mS for Timeup, I send again same data again, LCD displayed "ABABCD"

      after that, because of timeup, resume to MAIN LOOP even though several data still in buffer.

      I thought baud rate was too fast, so I tested at 2400bps, but the result was same.

      What is the problem ????

      Comment


      • #4
        The problem, as David has already tried to explain, is that ON INTERRUPT polls the interrupt flag BETWEEN each PBP statement and you have statements in your main loop that takes a lot (like A LOT) longer to exectute that what it takes the EUSART to fill its buffer. Basically your program transloates to this: (Psuedo code):
        Code:
        MAIN:
           I2CWRITE sda,scl,s_add,cont,[$80]
           If (Interrupt flag is set) GOSUB Interrupt handler
           Pause 1
           If (Interrupt flag is set) GOSUB Interrupt handler
           I2CWRITE sda,scl,s_add,dat,["Checking"]
           If (Interrupt flag is set) GOSUB Interrupt handler
          Pause 1
          If (Interrupt flag is set) GOSUB Interrupt handler
          Arraywrite array, ["00000000"]
          If (Interrupt flag is set) GOSUB Interrupt handler
          Pause 250
          If (Interrupt flag is set) GOSUB Interrupt handler
        Goto MAIN
        The EUSART buffer is 2 bytes deep, at 2400 baud it takes 8ms to fill that buffer (at the orignal 19200 baud that figure is closer to 1ms). If any single command takes longer than that then your buffer WILL overrun before the interrupt handler will execute to actualle GET the characters from the buffer. I don't know how long those I2CWRITE commands takes to execute but that PAUSE 250 you have in there sure is bad.

        /Henrik.

        Comment


        • #5
          Special Thanks to two Senior Members.

          I finally understood the problem.The biggest problem is my poor English reading skills. HAHA.

          After deleting "PAUSE 250", PIC was able to receive data correctly.

          However, the speed requirements of Baud Rate are getting faster and faster.
          It is a weak point of PBP that interrupt reception is not possible until one instruction is completed.

          I have to careful when coding.
          I hope that it will be improved by the next version upgrade.

          Comment


          • #6
            It is NOT a problem with PBP but a problem with the placement of the pause statements. They do NOT belong inside of an interrupt routine. You should service the interrupt as fast as possible and then return to the program. By setting a flag you can then manipulate the data received from the serial interrupt. I have used the USART on an 16F18326 at 57600 baud with NO problems at all for the last year or so..
            Dave Purola,
            N8NTA
            EN82fn

            Comment

            Working...
            X