Menu

Setup HW UART port in PIC 18F47Q43

ikonsgr74
2025-08-08
2025-08-19
1 2 3 > >> (Page 1 of 3)
  • ikonsgr74

    ikonsgr74 - 2025-08-08

    I'm trying to migrate a code i have for PIC 18F47Q10 to PIC 18F47Q43. I manage to make all needed updates (mostly declare different names for PPS and CLC's) and code is compiled without errors, but for some reason the hw UART port doesn't seem to work (i got no response to either output or input).
    This is the code i use, regarding USART setup, for PIC 18F47Q10 which works ok:

    #chip 18F47q10, 64
    #option explicit
    
        #startup InitPPS, 85
        #define PPSToolPart 18f47q10
    function
        #define USART2_BAUD_RATE 115200
        #define BUFFER_SIZE 2900
        #define USART2_DELAY 0 ms
        #define USART2_BLOCKING
        Sub InitPPS
         UNLOCKPPS
        RX2PPS = 0x0009    'RB1 > RX2
        RB2PPS = 0x000B    'TX2 > RB2
            LOCKPPS
        End Sub
          On Interrupt UsartRX2Ready Call readUSART
    

    And this is the modified code for PIC 18F47Q43:

    #chip 18F47q43, 64
    #option explicit
    
        #startup InitPPS, 85
        #define PPSToolPart 18f47q43
    function
        #define USART2_BAUD_RATE 115200
        #define BUFFER_SIZE 2900
        #define USART2_DELAY 0 ms
        #define USART2_BLOCKING
        Sub InitPPS
         UNLOCKPPS
           RB2PPS = 0x0023    // TX2 > RB2
          U2RXPPS = 0x0009    // RB1 > RX2
          LOCKPPS
        End Sub
          On Interrupt UART2ReceiveInterrupt Call readUSART
    

    For the conversion i used PPS and CLC Designer tools, and for the name of the Interrupt routine (to place received byte into a ring buffer) i consulted the 18F47Q43.dat file in gcbasic\chipdata folder.
    And this is the ASM code i got for INITUSART function, for PIC 18F47Q10:

     ;Source: usart.h (1242)
    INITUSART
    ;Set the default value for USART handler - required when more than one USART
    ;comport = SCRIPT_DEFAULT_COMPORT
        movlw   1
        movwf   COMPORT,ACCESS
    ;PIC USART 2 Init
    ;Set baud rate
    ;SPBRG2 = SPBRGL_TEMP2
        movlw   137
        banksel SPBRG2
        movwf   SPBRG2,BANKED
    ;SPBRGH2 = SPBRGH_TEMP2
        clrf    SPBRGH2,BANKED
    ;BAUD2CON_BRG16 = BRG16_TEMP2
        bsf BAUD2CON,BRG16,BANKED
    ;TX2STA_BRGH = BRGH_TEMP2
        bsf TX2STA,BRGH,BANKED
    ;Enable async mode
    ;Set TX2STA_SYNC Off
        bcf TX2STA,SYNC,BANKED
    ;Set RC2STA_SPEN On
        bsf RC2STA,SPEN,BANKED
    ;Enable Continuous Receive and Transmit Enable bit
    ;Set RC2STA_CREN On
        bsf RC2STA,CREN,BANKED
    ;Set TX2STA_TXEN On
        bsf TX2STA,TXEN,BANKED
        banksel 0
        return 
    

    And for PIC 18F47Q43:

    ;Source: usart.h (1242)
    INITUSART
    ;Set the default value for USART handler - required when more than one USART
    ;comport = SCRIPT_DEFAULT_COMPORT
        movlw   1
        movwf   COMPORT,ACCESS
    ;PIC USART 2 Init
    ;U2BRGH=SPBRGH_TEMP2
        banksel U2BRGH
        clrf    U2BRGH,BANKED
    ;U2BRGL=SPBRGL_TEMP2
        movlw   137
        movwf   U2BRGL,BANKED
    ;U2BRGS = BRGS2_SCRIPT
        bsf U2CON0,U2BRGS,BANKED
    ;ON_U2CON1=1
        bsf U2CON1,ON_U2CON1,BANKED
    ;U2TXEN=1
        bsf U2CON0,U2TXEN,BANKED
    ;U2RXEN=1
        bsf U2CON0,U2RXEN,BANKED
        banksel 0
        return
    
     

    Last edit: ikonsgr74 2025-08-08
  • Anobium

    Anobium - 2025-08-08

    The PPS and the ASM all looks correct. I was comparing here to MPLAB.

    So do the following. Do the basic work ?

    Remove the interrupt. Use a simple get data send data. Does that work ?

        #chip 18F47q43, 64
    #option explicit
    
        #startup InitPPS, 85
        #define PPSToolPart 18f47q43
    
        #define USART2_BAUD_RATE 115200
        #define USART2_DELAY OFF
        #define USART2_BLOCKING
        Sub InitPPS
         UNLOCKPPS
          // PPS is correct.
           RB2PPS = 0x0023    // TX2 > RB2
           U2RXPPS = 0x0009    // RB1 > RX2    
          LOCKPPS
        End Sub
    
        // Not really needed but for testing
        Comport = 2
    
        Do
          If USART2HasData Then
    
            // Send the RX to the TX 
            HserPrint HSerReceiveFrom(2), 2 
          End If
        Loop
    
     
  • Anobium

    Anobium - 2025-08-08

    The PPS and the ASM all looks correct. I was comparing here to MPLAB.

    So do the following. Do the basic work ?

    Remove the interrupt. Use a simple get data send data. Does that work ?

        #chip 18F47q43, 64
    #option explicit
    
        #startup InitPPS, 85
        #define PPSToolPart 18f47q43
    
        #define USART2_BAUD_RATE 115200
        #define USART2_DELAY OFF
        #define USART2_BLOCKING
        Sub InitPPS
         UNLOCKPPS
          // PPS is correct.
           RB2PPS = 0x0023    // TX2 > RB2
           U2RXPPS = 0x0009    // RB1 > RX2    
          LOCKPPS
        End Sub
    
        // Not really needed but for testing
        Comport = 2
    
        Do
          If USART2HasData Then
    
            // Send the RX to the TX 
            HserPrint HSerReceiveFrom(2), 2 
          End If
        Loop
    
     
  • ikonsgr74

    ikonsgr74 - 2025-08-08

    I connect the board with PIC to an amstrad cpc. Using a usb2serial cable (which is verified that works ok) i tried this code instead:

    RESTART:
       If USART2HasData Then
          data_buf=HSerReceive2
            // Send the RX to the TX
            hsersend data_buf,2
            wait 500 ms
            ;HserPrint HSerReceiveFrom(2), 2
    
          End If
    goto restart
    

    The good news is that whenever i send a character to the Amstrad (e.g. PIC's usart port), i get a respond back, BUT not with the character i sent, instead i always get ÿÿ characters as respond to PC terminal...
    Exactly the same behavior i got whe i use HserPrint HSerReceiveFrom(2), 2 instead of hsersend data_buf,2.
    port speed is set to 115200bps at both ends, and it's the only speed in terminal that i get a respond, so most probable baud rate is correctly set.
    Does this give any clue?

     

    Last edit: ikonsgr74 2025-08-08
  • ikonsgr74

    ikonsgr74 - 2025-08-08

    I just try the above code but without the wait. I try to send many characters and USART responds back with the same number of characters, but again are completely irrelevant and not the same every time! For example:
    I sent 3 times '12345' and i got in response:
    ¿ÿ÷¿
    o»÷÷
     ßû¿
    Even when i send i single same char i got a different respond each time, for example i sent 3 times '2' and got:
    ÷
    ¿
    ÿ

     

    Last edit: ikonsgr74 2025-08-08
  • Anobium

    Anobium - 2025-08-08

    Baud Rate calcs.

    MPLAB 64Mhz at 115k
    ~~~
    // BRGL 138;
    U2BRGL = 0x8A;

    // BRGH 0; 
    U2BRGH = 0x00;
    
    GCBASIC  64Mhz at 115k
    

    ;U2BRGH=SPBRGH_TEMP2
    banksel U2BRGH
    clrf U2BRGH,BANKED = 0
    ;U2BRGL=SPBRGL_TEMP2
    movlw 137
    movwf U2BRGL,BANKED = 137

    So, I think the baud rate is correct.
    
    -----------------------------
    
    The setting of Tx, Rx, En and Baud Rate Generator Speed Select look correct.  These all set U2CON0 and U2CON1.
    
    ----------------------
    
    The OSCFreq looks correct. As this impacts the USART this is an important check.  You can inspect the OSCFreq by changing the OSCout in the config and checking with a scope.
    
    --------------------
    
    So, need to rule out the existing INIT and the Recieve. Try this or a variant of this.  This will recieve and send back the data.
    
    What happens ?
    

    chip 18F47q43, 64

    option explicit

    #startup InitPPS, 85
    #define PPSToolPart 18f47q43
    
    #define USART2_BAUD_RATE 115200
    #define USART2_DELAY OFF
    #define USART2_BLOCKING
    Sub InitPPS
     UNLOCKPPS
      // PPS is correct.
       RB2PPS = 0x0023    // TX2 > RB2
       U2RXPPS = 0x0009    // RB1 > RX2    
      LOCKPPS
    End Sub
    
    // Set the UART2 module to the options selected in the user interface.
    
    // P1L 0; 
    U2P1L = 0x00;
    
    // P2L 0; 
    U2P2L = 0x00;
    
    // P3L 0; 
    U2P3L = 0x00;
    
    // BRGS high speed; MODE Asynchronous 8-bit mode; RXEN enabled; TXEN enabled; ABDEN disabled; 
    U2CON0 = 0xB0;
    
    // RXBIMD Set RXBKIF on rising RX input; BRKOVR disabled; WUE disabled; SENDB disabled; ON enabled; 
    U2CON1 = 0x80;
    
    // TXPOL not inverted; FLO off; RXPOL not inverted; RUNOVF RX input shifter stops all activity; STP Transmit 1Stop bit, receiver verifies first Stop bit; 
    U2CON2 = 0x00;
    
    // BRGL 138; 
    U2BRGL = 0x8A;
    
    // BRGH 0; 
    U2BRGH = 0x00;
    
    // STPMD in middle of first Stop bit; TXWRE No error; 
    U2FIFO = 0x00;
    
    // ABDIF Auto-baud not enabled or not complete; WUIF WUE not enabled by software; ABDIE disabled; 
    U2UIR = 0x00;
    
    // ABDOVF Not overflowed; TXCIF 0; RXBKIF No Break detected; RXFOIF not overflowed; CERIF No Checksum error; 
    U2ERRIR = 0x00;
    
    // TXCIE disabled; FERIE disabled; TXMTIE disabled; ABDOVE disabled; CERIE disabled; RXFOIE disabled; PERIE disabled; RXBKIE disabled; 
    U2ERRIE = 0x00;
    
    
    Do
      If USART2HasData Then
    
        // Send the RX to the TX 
        Wait While TX2IF = Off
        U2TXB = U2RXB 
      End If
    Loop
    

    ~~~

     
  • ikonsgr74

    ikonsgr74 - 2025-08-08

    YES! That worked straight!

     
  • Anobium

    Anobium - 2025-08-08

    Ok.

    Isolate the issue by removing the special init. Leave the do-loop. Does the standard init work?

     
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    If i remove all the "Set the UART2 module to the options selected in the user interface." section, and left only the 'do loop', i got no response at all.

     

    Last edit: ikonsgr74 2025-08-09
    • Anobium

      Anobium - 2025-08-09

      To understand the root cause. I need you to put back each line, one at a time, one by one. Which line makes this work?

      Once I know what line is required then I can investigate in the serial initialization code.

      This is exactly what I would be doing to understand the root cause. A bit of a pain, and a slow process, but it will determine what is wrong.

       
      • ikonsgr74

        ikonsgr74 - 2025-08-09

        Well, fortunately i have a PICKI4 which reflashes this test program in half a second, so i don't think it would take long :-)
        Btw, thanks for the explanation about INTON/INTOFF i didn't thought that since there is no interrupt command in source code it will be disable :-)

         
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    btw, i discover another potential bug in the 18F47Q43 asm code: there is no assembly code produced for INTON/INTOFF gcb commands. For example this is the asm i get for 18F47Q410:

    READ_BYTE
    ;INTOFF
        bcf SYSINTSTATESAVE0,0,ACCESS
        btfsc   INTCON,GIE,ACCESS
        bsf SYSINTSTATESAVE0,0,ACCESS
        bcf INTCON,GIE,ACCESS
    ;CLC4POL = 0x80
        movlw   128
        banksel CLC4POL
        movwf   CLC4POL,BANKED
    UNPAUSELOOP3
    ;if IORQ=OFF Then
        btfss   PORTC,6,ACCESS
    ;GOTO UNPAUSELOOP3
        bra UNPAUSELOOP3
    ;END IF
    ;DIR PORTD IN
        setf    TRISD,ACCESS
    ;CLC4POL = 0x00
        clrf    CLC4POL,BANKED
    ;INTON
        btfss   SYSINTSTATESAVE0,0,ACCESS
        bcf INTCON,GIE,ACCESS
        btfsc   SYSINTSTATESAVE0,0,ACCESS
        bsf INTCON,GIE,ACCESS
    ;GOTO RESTART
        goto    RESTART
    

    And this is the asm for 18F47Q43 for exactly the same code:

    READ_BYTE
    ;INTOFF  <------------------NO CODE PRODUCED FOR INTOFF!
    ;CLCSELECT = 0x03
        movlw   3
        banksel CLCSELECT
        movwf   CLCSELECT,BANKED
    ;CLCNPOL = 0x80
        movlw   128
        movwf   CLCNPOL,BANKED
    UNPAUSELOOP3
    ;if IORQ=OFF Then
        btfss   PORTC,6,ACCESS
    ;GOTO UNPAUSELOOP3
        bra UNPAUSELOOP3
    ;END IF
    ;DIR PORTD IN
        setf    TRISD,ACCESS
    ;CLCNPOL = 0x00
        clrf    CLCNPOL,BANKED
    ;INTON             <------------------NO CODE PRODUCED FOR INTON!
    ;GOTO RESTART
        goto    RESTART
    
    • Note: as you can see the setting of CLC registers need more instructions with Q43, as you can't set them directly as with Q10 but instead you have to use the extra CLCSELECT all the time... I really can't understand what were thinking in Microchip.... :-)
     

    Last edit: ikonsgr74 2025-08-09
    • Anobium

      Anobium - 2025-08-09

      This is because the 'On Interrupt....' is not present.

       
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    Ok,i finish tests. The minimum group of registers needed for proper function of UART port are:

    // BRGS high speed; MODE Asynchronous 8-bit mode; RXEN enabled; TXEN enabled; ABDEN disabled;
    U2CON0 = 0xB0;          NEEDED!!
    
    // RXBIMD Set RXBKIF on rising RX input; BRKOVR disabled; WUE disabled; SENDB disabled; ON enabled;
    U2CON1 = 0x80;        NEEEDED!
    
    // BRGL 138;
    U2BRGL = 0x8A;
    
    // BRGH 0;
    U2BRGH = 0x00;
    

    Any of the above removed, UART stops functioning. All others don't seem to affect functioning of the UART.

     
  • Anobium

    Anobium - 2025-08-09

    Thanks.

    Can you write the existing values to eeprom then read the chip to share the results? You will be reading the EEProm with your PK4 to share with me what the USART library is setting. I am reading the important registers - hopefully this will show some differences.

    Sorry, for delays. I am travelling today! And, the signal is very poor when in the car!

    Evan

    This shows the method to write the EEProm.

    #chip 18F47q43, 64
    #option explicit
    #startup InitPPS, 85
    #define PPSToolPart 18f47q43
    
    #define USART2_BAUD_RATE 115200
    #define USART2_DELAY OFF
    #define USART2_BLOCKING
    Sub InitPPS
     UNLOCKPPS
      // PPS is correct.
       RB2PPS = 0x0023    // TX2 > RB2
       U2RXPPS = 0x0009    // RB1 > RX2    
      LOCKPPS
    End Sub
    
    // Write the GCBASIC init values to EEProm
    EPWRITE 0, U2CON0 
    EPWRITE 1, U2CON1
    EPWRITE 3, U2CON2
    
    
    
    // Set the UART2 module to the options selected in the user interface.
    
    // P1L 0; 
    U2P1L = 0x00;
    
    // P2L 0; 
    U2P2L = 0x00;
    
    // P3L 0; 
    U2P3L = 0x00;
    
    // BRGS high speed; MODE Asynchronous 8-bit mode; RXEN enabled; TXEN enabled; ABDEN disabled; 
    U2CON0 = 0xB0;
    
    // RXBIMD Set RXBKIF on rising RX input; BRKOVR disabled; WUE disabled; SENDB disabled; ON enabled; 
    U2CON1 = 0x80;
    
    // TXPOL not inverted; FLO off; RXPOL not inverted; RUNOVF RX input shifter stops all activity; STP Transmit 1Stop bit, receiver verifies first Stop bit; 
    U2CON2 = 0x00;
    
    // BRGL 138; 
    U2BRGL = 0x8A;
    
    // BRGH 0; 
    U2BRGH = 0x00;
    
    // STPMD in middle of first Stop bit; TXWRE No error; 
    U2FIFO = 0x00;
    
    // ABDIF Auto-baud not enabled or not complete; WUIF WUE not enabled by software; ABDIE disabled; 
    U2UIR = 0x00;
    
    // ABDOVF Not overflowed; TXCIF 0; RXBKIF No Break detected; RXFOIF not overflowed; CERIF No Checksum error; 
    U2ERRIR = 0x00;
    
    // TXCIE disabled; FERIE disabled; TXMTIE disabled; ABDOVE disabled; CERIE disabled; RXFOIE disabled; PERIE disabled; RXBKIE disabled; 
    U2ERRIE = 0x00;
    
    
    Do
      If USART2HasData Then
    
        // Send the RX to the TX 
        // Wait While TX2IF = Off
        //  U2TXB = U2RXB
        HserPrint U2RXB 
      End If
    Loop
    
     
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    Ok, i've added the extra code for writing eeprom but it doesn't seem to write anything. The bytes i read from eeprom before pugging PIC to the test board are the same with the bytes after ( first 2 eeprom bytes are set to '0' and all others to 'FF')

     

    Last edit: ikonsgr74 2025-08-09
  • Anobium

    Anobium - 2025-08-09

    They may be zero. Let us check the EE write operations.

    EPWRITE 0, 0x55
    EPWRITE 1, 0x44
    EPWRITE 3, 0x33

    Comment out the following.

    // EPWRITE 0, U2CON0
    // EPWRITE 1, U2CON1
    // EPWRITE 3, U2CON2

    Do you see 0x55, 0x44, 0x33 ?

     
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    eprom byte 0 and 1 have 0x55, 0x44 but all others are 0xff

     
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    So most probable U2CON0 and U2CON1 are set to '0' by init uart routine, but for some reason the 3rd byte is not written to eeprom...

     
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    I tried to write eprom byte 0 with the value of U2CON2 and it also gave me '0', so it seems that all 3 values are set to '0' from the UART init

     
    • Anobium

      Anobium - 2025-08-09

      Ok. let me look at the library again. Please look for an update post from me when i have completed my review.

       
  • ikonsgr74

    ikonsgr74 - 2025-08-09

    ok, thanks.

     
  • Anobium

    Anobium - 2025-08-09

    Can I check ? You are on the latest build?

    Inspect USART.H. Last change 24/12/2024 ? Yes?

     
  • Anobium

    Anobium - 2025-08-10

    The issue is not the configuration but the USART functions. There was a change that set the comport to a Constant. As Constants cannot change the comport being selected was essentially hard coded. I think I know why the happended but this should not have passed testing.


    Attached is an update usart.h file. it is an updated version of usart.h with the following change:

    Updated Default Comport Handling (August 10, 2024):

    • Removed dependency on SCRIPT_DEFAULT_COMPORT constant. Subroutines like HSerGetNum, HSerPrint, and others now use comport as the default value for the optional comport parameter, enabling runtime flexibility for selecting USART ports.

    This change aims to make the library more flexible for multi-USART setups while maintaining compatibility with existing code.

    Please replace your existing USART.H, and test

     
  • Anobium

    Anobium - 2025-08-10

    Here are my test programs.

    Summary of ComplexTest.gcb and SimpleTest.gcb

    SimpleTest.gcb

    Purpose: Tests basic USART2 functionality on a PIC 18F27Q43 microcontroller.

    Key Functionality:
    - Configures USART2 at 115,200 baud with blocking mode and no delay.
    - Initializes PPS for USART2 (TX2 on RB2, RX2 on RB1).
    - Continuously checks for incoming data on USART2 and echoes it back to the transmitter.
    - Sets Comport = 2 explicitly for USART2 operations.

    Focus: Verifies basic send/receive functionality of USART2, acting as a simple echo test for serial communication.

    ComplexTest.gcb

    Purpose: Tests advanced USART2 functionality with a buffered, interrupt-driven data transfer system on a PIC 18F27Q43 microcontroller.

    Key Functionality:
    - Configures USART2 at 115,200 baud with blocking mode and no delay.
    - Initializes Peripheral Pin Select (PPS) for USART2 (TX2 on RB2, RX2 on RB1).
    - Implements a ring buffer (2,900 bytes) to store incoming USART2 data.
    - Uses an interrupt handler (UART2ReceiveInterrupt) to read incoming data into the buffer.
    - Continuously checks the buffer and sends stored data to USART2.
    - Prints version information and USART control register values (U1CON0, U1CON1, U1CON2, U2CON0, U2CON1, U2CON2) for both USART1 and USART2 to verify configuration.
    - Demonstrates dynamic comport switching (USART1 and USART2) for printing diagnostic data.

    Focus: Tests robust serial communication with interrupt-driven buffering, suitable for high-throughput or real-time applications.

    Comparison

    • Complexity: ComplexTest.gcb is more sophisticated, incorporating a ring buffer and interrupt handling for efficient data management, while SimpleTest.gcb focuses on straightforward data echoing.
    • Testing Scope: ComplexTest.gcb tests both USART1 and USART2 diagnostics and buffering, whereas SimpleTest.gcb is limited to USART2 echo functionality.
    • Use Case: ComplexTest.gcb is suited for validating complex serial applications; SimpleTest.gcb is a minimal test for basic USART operation.
     
1 2 3 > >> (Page 1 of 3)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.