News:

;) This forum is the property of Proton software developers

Main Menu

UART receive interrupt problem

Started by rox, Feb 11, 2021, 12:54 PM

Previous topic - Next topic

rox

Hi Everybody,
I'm troubleshooting my code this whole day and failed to find why my receive interrupt is not working/triggering, i have a LED toggling on Recvd interrupt to see if it will activate. TX HRSOUT is working, here below my code. appreciate any help.
'

;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Device = 18F25K22

Config_Start
  FOSC = HSMP ;HS oscillator (medium power 4-16 MHz)
  PLLCFG = On ;Oscillator multiplied by 4
  PRICLKEN = On ;Primary clock enabled
  FCMEN = OFF ;Fail-Safe Clock Monitor disabled
  IESO = OFF ;Oscillator Switchover mode disabled
  PWRTEN = OFF ;Power up timer disabled
  BOREN = SBORDIS ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
  BORV = 190 ;VBOR set to 1.90 V nominal
  WDTEN = OFF ;Watch dog timer is always disabled. SWDTEN has no effect.
  WDTPS = 32768 ;1:32768
  CCP2MX = PORTC1 ;CCP2 input/output is multiplexed with RC1
  PBADEN = On ;PORTB<5:0> pins are configured as analog input channels on Reset
  CCP3MX = PORTB5 ;P3A/CCP3 input/output is multiplexed with RB5
  HFOFST = On ;HFINTOSC output and ready status are not delayed by the oscillator stable status
  T3CMX = PORTC0 ;T3CKI is on RC0
  P2BMX = PORTB5 ;P2B is on RB5
  MCLRE = EXTMCLR ;MCLR pin enabled, RE3 input pin disabled
  STVREN = On ;Stack full/underflow will cause Reset
  LVP = OFF ;Single-Supply ICSP disabled
  XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF ;Disabled
  Cp0 = OFF ;Block 0 (000800-001FFFh) not code-protected
  CP1 = OFF ;Block 1 (002000-003FFFh) not code-protected
  CP2 = OFF ;Block 2 (004000-005FFFh) not code-protected
  CP3 = OFF ;Block 3 (006000-007FFFh) not code-protected
  CPB = OFF ;Boot block (000000-0007FFh) not code-protected
  CPD = OFF ;Data EEPROM not code-protected
  WRT0 = OFF ;Block 0 (000800-001FFFh) not write-protected
  WRT1 = OFF ;Block 1 (002000-003FFFh) not write-protected
  WRT2 = OFF ;Block 2 (004000-005FFFh) not write-protected
  WRT3 = OFF ;Block 3 (006000-007FFFh) not write-protected
  WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
  WRTB = OFF ;Boot Block (000000-0007FFh) not write-protected
  WRTD = OFF ;Data EEPROM not write-protected
  EBTR0 = OFF ;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
  EBTR1 = OFF ;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
  EBTR2 = OFF ;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
  EBTR3 = OFF ;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
  EBTRB = OFF ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------

 Xtal 64
'
Declare Reminders = Off
 Declare Bootloader = Off
 '
 OSCCON.3 = 1
 OSCCON.0 = 0
 OSCCON2= 0b10000100
 
    TRISA  = 0b00011101              ' PORTA[0] analog imput
    PORTA  = 0b00011101
    TRISB  = 0b00000000              '
    PORTB  = 0b00000000
    TRISC  = 0b11000111              '
    PORTC  = 0b11000111
    TRISE = 1
    PORTE = 1
    CM1CON0 = 0                     ' Disable comp1
    CM2CON0 = 0                     ' Disable comp2
    ANSELA = 1                      'analog input on porta.0
    ADCON0 = 1                      'Analog at AN0, enable ADC
    ADCON1 = 0b00001000             'A/D VREF+ connected to internal signal, FVR BUF2
    ADCON2 = 0b10100111             'right justify result, 2TAD, Fosc 64
'    VREFCON0 = 0b11010000            'fixed voltage ref enabled with value 1,024v
'   Declare Adin_Res = 10 ' 10-bit ADC result required
'    Declare Adin_Tad = FRC ' RC oscillator chosen for the ADC
   Declare Adin_Stime = 50 ' Allow 50us sample time
 
  'Software Serial
 Declare RsOut_Pin PORTC.3
 Declare RsOut_Mode false
 Declare Serial_Baud 9600
 '
 
 
'Timer0
'Prescaler 1:16; TMR0 Preload = 6; Actual Interrupt Time : 1 ms
    T0CON  = 0xC5;
    TMR0L  = 0x06
    '
'Timer2
'Prescaler 1:1; Postscaler 1:2; TMR2 Preload = 199; Actual Interrupt Time : 100 us
    T2CON  = 0x34;
    PR2    = 228;
    PIE1.1 = 1            ' Enable interrupt TMR2 to PR2 match interrupt
    TMR2 = 0                'TMR2 Holding register = 0
    T2CON.2 = 0             'disable Tmr 2
    '
     IPR1.5 = 1                             ' USART HAS HIGH PRIORITY
    INTCON2bits_TMR0IP = 0                 ' Timer0 Interrupt to Low priority
   ' IPR1bits_TMR1IP = 0                    ' Timer1 Interrupt to low priority
    IPR1.1 = 1                             ' TMR2 to PR2 Match to high priority
    RCONbits_IPEN = 1                      ' Enable priority levels on interrupts
    INTCONbits_GIEL = 1                    ' Enable low priority peripheral interrupts
    INTCONbits_GIE = 1                     ' Enable global interrupts
   
;Calculated Baudrate = 9598 @ Xtal 64MHz, Error = -0.02%
RCSTA1     = 144 ; Enable continuous receive
TXSTA1     = 36  ; Enable transmit, BRGH = 1
SPBRG1     = 130 ; Baud Rate Generator Low Byte Value
SPBRGH1    = 6   ; Baud Rate Generator High Byte Value
BAUDCON1.3 = 1   ; Enable the 16 bit Baud Rate Generator
'
 PIE1.5 = 1  'Enable receive interrupt on USART

' PIE3.5 = 1  'enable uart 2 interrupt on usart
 Movf RCREG1,W  'Clear the RCREG
 Movf RCREG2,w
 '
 ' Variables
 
  Dim wFlags                      As Word
  Dim DegC                        As Word
  Dim bTMR0                       As Byte
  Dim bTMR1                       As Byte
  Dim bTMR2                       As Byte
  Dim bTMR3                       As Byte
  Dim bInput                      As Byte
  Dim bTMR101                     As Byte
  Dim wFlagsQ                     As Word
  Dim wInt1S                      As Word
 

' Alias/ Modifiers
  Symbol fMbNewFrame              wFlags.0
  Symbol fInt1mS                  wFlags.1
  Symbol fInt1S                   wFlags.2
  Symbol fTMR0                    wFlags.3
  Symbol fTMR0_Dn                 wFlags.4
  Symbol fTMR1_Dn                 wFlags.5
  Symbol fTMR2_Dn                 wFlags.6
  Symbol fTMR3_Dn                 wFlags.7
  Symbol fAC_Contactor            wFlags.8
  Symbol fTMR101                  wFlags.9
  Symbol fTMR101_Dn               wFlags.10
  '
 
    On_Hardware_Interrupt GoTo Isr
    On_Low_Interrupt GoTo LowISR
   
    GoTo Init
 '------------------
  Isr:
    Context Save
  ' ---------- USART Causes Interrupt ---------
If RCSTA1.1 = 1 Or RCSTA1.2 = 1 Then                ' If USART error then clear the error flag
     RCSTA1.4 = 0
     RCSTA1.4 = 1
     
EndIf
If PIR1.5 = 1 Then       'Interrupt_Source_RX USART2, pir1.5 for uasrt 1
   Toggle PORTB.0
     Clear _bTmr2Ticks   'Reset tmr 2 Int counter
     T2CON.2 = 1  'Enable Timer2
     _bMBbuffer[_MBlength] = RCREG1
     
     _MBlength  = _MBlength  + 1
     If _MBlength  > 15 Then _MBlength  = 0     'reached maximum mbBuffer
EndIf
''----------- Timer 2 Causes Interrupt ------
'MB RTU calculation for silent interval between mssgs:
'Silent Interval = 1 / 9600(bps) * 11(bits) * 3.5(ct) = 4.01 [ms] 'minimum
If PIR1.1 = 1 Then  '100 uS/interrupt (0.1 ms)
   Clear PIR1.1        ' tmr2 to pr2 occured and reset
    _bTmr2Ticks = _bTmr2Ticks + 1
    If _bTmr2Ticks > 50 Then  '
    Set _fMBnewFrame   'no new char on USART => end of modbus frame, clear in software
         T2CON.2 = 0  'Timer2 disable
         
    EndIf
EndIf
Context Restore
'
LowISR:
Context Save
'---------- Timer 0 causes interrupt --------
  If INTCON.2 = 1 Then
    INTCON.2=0
    TMR0L  = 0x06;
    Set fInt1mS
   
    wInt1S = wInt1S + 1
    If wInt1S = 1000 Then
       wInt1S = 0
       Set fInt1S
    EndIf
 EndIf

'
    Context Restore
'--------------------------------
     

 Init:       'Initialization:
 
 Clear                               'clear all memory
 Clrwdt
 DelayMS 100
 '
 INTCON  = 0b11100000
 '
 Clrwdt
 _uID = 1

 
 RsOut "OK",13
 HRSOut1 "HRSOUT OK"

 
 Do
 ' Toggle PORTB.0
  GoSub InputMap
  GoSub Timers
  GoSub Analog
  GoSub Logic
  GoSub OutputMap
  GoSub ModbusMap
  If _fMBnewFrame = 1 Then GoSub Modbus
 
 
 Loop
 '
 'Subroutines
  Include "Modbus_RTU.inc"
 '
  InputMap:
  If fTMR0_Dn = 1 Then
     fTMR0_Dn = 0

     bInput.0 = ~ PORTA.3
     bInput.1 = ~ PORTA.2
     bInput.2 = ~ PORTC.2
     bInput.3 = ~ PORTA.4
     bInput.4 = ~ PORTC.1
     bInput.5 = ~ PORTC.0
  End If
Return
'-----------------
Logic:
 If bInput.0 = 1 Then        'NC contact of under/overvoltage relay
     fAC_Contactor = 0
     fTMR101_Dn = 0
 Else
     fTMR101 = 1
     If fTMR101_Dn = 1 Then
        fTMR101 = 0
        fAC_Contactor = 1   ' energize relay after delay
     EndIf
 EndIf

Return
'------------
Timers:

' 1 mS timers
 If fInt1mS = 1 Then
    fInt1mS = 0
    'timers here
    bTMR0 = bTMR0 + 1   'Timer 0
      If bTMR0 >= 5 Then '5mS timer
        fTMR0_Dn = 1
        bTMR0 = 0
      EndIf
      '
       bTMR1 = bTMR1 + 1   'Timer 1
      If bTMR1 >= 10 Then
        fTMR1_Dn = 1
        bTMR1 = 0
      End If
      '
       bTMR2 = bTMR2 + 1
      If bTMR2 = 5 Then
        fTMR2_Dn = 1
        bTMR2 = 0
      End If
      '
      bTMR3 = bTMR3 + 1
      If bTMR3 = 100 Then
        fTMR3_Dn = 1
        bTMR3 = 0
      End If
   
 EndIf
 '
 ' 1 Sec timers
  If fInt1S = 1 Then
     fInt1S = 0
     ' timers here
     If fTMR101 = 1 Then
        bTMR101 = bTMR101 + 1
        If bTMR101 >= 5 Then
           fTMR101_Dn = 1
           bTMR101 = 0
        EndIf
     EndIf
     '
     
     
  EndIf
 
 Return
 '-------------------------
 
'---------------------------
OutputMap:
 
  If fTMR1_Dn = 1 Then
     fTMR1_Dn = 0
     '
  '  PORTB.0 = wFlagsQ.0
    PORTB.1 = wFlagsQ.1
    '
    If fAC_Contactor = 1 Or wFlagsQ.2 = 1 Then
       PORTB.2 = 1
    Else
        PORTB.2 = 0
    EndIf
     '
    PORTB.3 = wFlagsQ.3
    PORTB.4 = wFlagsQ.4
    PORTB.5 = wFlagsQ.5
   
  End If

Return
'-----------------------------
Analog:
 If fTMR2_Dn = 1 Then
    fTMR2_Dn = 0
    '
 VREFCON0 = 0b10110000    'fixed voltage ref enabled with value 1,024v   
 While VREFCON0.6 =0:Wend
 DegC = ADIn 0
 VREFCON0.7 = 0   'turn off vref   
   
 EndIf
Return
'-----------------------------
ModbusMap:
 If fTMR3_Dn = 1 Then
      fTMR3_Dn = 0
      '
       wFlagsQ.0 = _wMBcoil.0
       wFlagsQ.1 = _wMBcoil.1
       wFlagsQ.2 = _wMBcoil.2
       wFlagsQ.3 = _wMBcoil.3
       wFlagsQ.4 = _wMBcoil.4
       wFlagsQ.5 = _wMBcoil.5

      _wMBreg[0] = DegC
      _wMBreg[1] = _wMBcoil

 EndIf
Return

Thanks, Rox

Compiler Version: 3.7.5.5

rox

Hi, the issue on RX interrupt is now resolved, it's a hardware issue. now code dev/testing continues.

Thanks.

Stephen Moss

You have RCSTA1.4 = 0 immediately followed by RCSTA1.4 = 1, setting the same bit to a 0 and then immediately to a 1 makes no sense to me, should they be different bits? Generally I try to avoid writing to the same register in consecutive commands as there is always the risk of pipe-lining issues where it tries to do the second before the first has finished.

I cannot see where you are resetting the interrupt flag (PIR1.5 = 0) in your ISR but as you now have it working, either I missed it or you have corrected that.
You may want to consider aliasing the interrupt bit to something that may be clearer in code and using that instead, i.e. Symbol Rx_IF = PIR1.5. Then instead of...
If PIR1.5 = 1 you would use If Rx_IF = 1

The PIC 24 devices are cool in that you can decide which interrupts are high and low priority and create an individual ISR for each peripheral, which can make it easier to find when you want to make changes than having to find some thing like If PIR1.5 = 1 among a collection of interrupts for many peripherals all placed in a single ISR. For the the interrupt in question it would be something like...

ISR USART1interrupt
Do interrupt stuff here to test the USAR1 interrupt bits, handle and clear the relevant USART1 interrupts
EndISR

See the interrupts section of the Proton24 manual (page 438) for details

tumbleweed

QuoteYou have RCSTA1.4 = 0 immediately followed by RCSTA1.4 = 1, setting the same bit to a 0 and then immediately to a 1 makes no sense to me, should they be different bits? Generally I try to avoid writing to the same register in consecutive commands as there is always the risk of pipe-lining issues where it tries to do the second before the first has finished.
Toggling CREN (RCSTA.4) is one way you clear a receive OVERRUN error. There are no such execution pipeline issues. That only applies to fetching instructions, not executing them.

QuoteI cannot see where you are resetting the interrupt flag (PIR1.5 = 0) in your ISR but as you now have it working, either I missed it or you have corrected that
With the PIC18, the RCIF bit is read-only, so writing to it has no effect. You clear it by reading the RCREG.

wirecut

Leo.
Luck does not exist: there is a moment when talent meets opportunity. SENECA