News:

;) This forum is the property of Proton software developers

Main Menu

What would be the best way to change UART baudrate in code?

Started by marekf, Jan 12, 2024, 07:13 PM

Previous topic - Next topic

marekf

Typically I use compiler directive
Declare Hserial_Baud 9600to set up the serial baudrate.

I would like to allow for changing the UART baudrate in the program using one of 5 standard options 9600, 19200, 38400, etc...
There is HSerialx_ChangeBaud command, but it requires a constant. I get compile error when trying to use a variable.
What would be the best way to change baudrate programmatically based on a varible stored in eeprom?
I guess setting up the registers directly is an option, but I am wondering if there is a better approach?

trastikata

As far as I know changing the registers inline is the best option.

John Drew

Quote from: trastikata on Jan 12, 2024, 08:51 PMAs far as I know changing the registers inline is the best option.
Agreed, it's quick and easy. I haven't the code (using my phone) if you need it I'll look it up tomorrow.
John

top204

The HSerialx_ChangeBaud commands require a constant value as a parameter because there is more to choosing the Baud rate values for the peripheral's SFRs than a simple calculation. And placing it in variables for the microcontroller to calculate would take quite a bit of code space if more accuracy is required and particular SFRs to be loaded correctly on particular devices.

For example, the Baud generator needs to be chosen for which one is best depending on the device's operating frequency and the Baud error percentage after the calculations of using different generators. The compiler uses 64-bit floating point variables for its internal Baud calculations, and different bits need to be altered in the peripheral's SFRs depending on the Baud generator chosen, and extra SFRs need to be manipulated for a different size Baud generator. i.e. 8-bit or 16-bit etc... Also, microchip have altered how the USARTs work in the newer devices and they have totally different SFRs and mechanisms.

So one way to alter a USART's Baud rate dymanically is to let the compiler do the work for you. See the code listing below for one way of doing it:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' A demonstration of a procedure to change the Baud rate of USART1 dynamically using a variable's value.
'
' Written for the Positron8 compiler by Les Johnson.
'
    Device = 18F25K20                               ' Tell the compiler what device to compile for
    Declare Xtal = 16                               ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Setup USART1
'
    Declare Hserial1_Baud = 9600                    ' Set the Baud rate to 9600
    Declare HRSOut1_Pin = PORTC.6                   ' Set the TX pin
'
' Create any variables for the demo here
'
    Dim bMyBaud As Byte                             ' Holds a value for the Baud rate required (1 to 5)

'-------------------------------------------------------------------------
' The main program starts here
'
Main:
    USART1_ChangeBaud(c9600_Baud)                   ' Set the Baud rate of USART1 to 9600
    HRsoutLn "Hello World at 9600 Baud"
    DelayMs 500

    USART1_ChangeBaud(c19200_Baud)                  ' Set the Baud rate of USART1 to 19200
    HRsoutLn "Hello World at 19200 Baud"
    DelayMs 500

    USART1_ChangeBaud(c38400_Baud)                  ' Set the Baud rate of USART1 to 38400
    HRsoutLn "Hello World at 38400 Baud"
    DelayMs 500

    USART1_ChangeBaud(c57600_Baud)                  ' Set the Baud rate of USART1 to 57600
    HRsoutLn "Hello World at 57600 Baud"
    DelayMs 500

    bMyBaud = c115200_Baud                          ' \
    USART1_ChangeBaud(bMyBaud)                      ' / Set the Baud rate of USART1 to 115200 using a variable to hold the Baud required
    HRsoutLn "Hello World at 115200 Baud"

'-------------------------------------------------------------------------
' Change the Baud rate of USART1 dymanically
' Input     : pBaud holds the Baud rate to use: (1 is 9600, 2 is 19200, 3 is 38400, 4 is 57600, 5 is 115200)
' Output    : None
' Notes     : Uses a crude method of implementing the compiler's HSerial1_ChangeBaud command for better calculations of the Baud value and Baud generator
'
Proc USART1_ChangeBaud(pBaud As Byte)
Global Symbol c9600_Baud = 1
Global Symbol c19200_Baud = 2
Global Symbol c38400_Baud = 3
Global Symbol c57600_Baud = 4
Global Symbol c115200_Baud = 5

    Select pBaud                                    ' Compare the value held in pBaud
        Case c9600_Baud                             ' Is 9600 Baud required?
            HSerial1_ChangeBaud(9600)               ' Yes. So change the Baud rate of USART1

        Case c19200_Baud                            ' Is 19200 Baud required?
            HSerial1_ChangeBaud(19200)              ' Yes. So change the Baud rate of USART1

        Case c38400_Baud                            ' Is 38400 Baud required?
            HSerial1_ChangeBaud(38400)              ' Yes. So change the Baud rate of USART1 

        Case c57600_Baud                            ' Is 57600 Baud required?
            HSerial1_ChangeBaud(57600)              ' Yes. So change the Baud rate of USART1

        Case c115200_Baud                           ' Is 115200 Baud required?
            HSerial1_ChangeBaud(115200)             ' Yes. So change the Baud rate of USART1
    EndSelect
EndProc


marekf

Unfortunately HSerial1_ChangeBaud() function worked only up to 19200 with PIC18F6722 at 4MHz.
I ended up manipulating registers directly with calculated values like so:

'Sample to demonstrate the Baud rate change.
Device = 18F6722
Xtal = 4

Declare Hserial_Baud 9600    ' Set the baud rate for UART1 to 9600
Declare Hserial_Clear = On    ' Clear the overflow error bit automatically
Declare HRSOut1_Pin = PORTC.6 ' Set the TX pin

Dim bdrate As Byte

'main program
Main:
    bdrate = 1                                      ' Set the Baud rate of USART1 to 9600
    EWrite 210,[bdrate]
    DelayMS 250
    GoSub setbaudrate
    HRsoutLn "Hello at 9600 Baud"
    DelayMs 1000

    bdrate = 2                                      ' Set the Baud rate of USART1 to 19200
    EWrite 210,[bdrate]
    DelayMS 250
    GoSub setbaudrate
    HRsoutLn "Hello at 19200 Baud"
    DelayMs 1000

    bdrate = 3                                      ' Set the Baud rate of USART1 to 38400
    EWrite 210,[bdrate]
    DelayMS 250
    GoSub setbaudrate
    HRsoutLn "Hello at 38400 Baud"
    DelayMs 1000

    bdrate = 4                                      ' Set the Baud rate of USART1 to 57600
    EWrite 210,[bdrate]
    DelayMS 250
    GoSub setbaudrate
    HRsoutLn "Hello at 57600 Baud"
    DelayMs 1000

    bdrate = 5                                      ' Set the Baud rate of USART1 to 115200
    EWrite 210,[bdrate]
    DelayMS 250
    GoSub setbaudrate
    HRsoutLn "Hello at 115200 Baud"


setbaudrate:
    bdrate = ERead 210
    Select bdrate
        Case 1
            'HSerial1_ChangeBaud 9600
            ;Calculated Baudrate = 9615 @ Xtal 4MHz, Error = 0.16%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 32      ; Enable transmit, BRGH = 0
            SPBRG = 25      ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
        Case 2
            'HSerial1_ChangeBaud 19200
            ;Calculated Baudrate = 19231 @ Xtal 4MHz, Error = 0.16%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 32      ; Enable transmit, BRGH = 0
            SPBRG = 12      ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
        Case 3
            'HSerial1_ChangeBaud 38400 <- this does not work!
            ;Calculated Baudrate = 38462 @ Xtal 4MHz, Error = 0.16%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 36      ; Enable transmit, BRGH = 0
            SPBRG = 25      ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
        Case 4
            'HSerial1_ChangeBaud 57600 <- this does not work!
            ;Calculated Baudrate = 58824 @ Xtal 4MHz, Error = 2.13%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 36      ; Enable transmit, BRGH = 0
            SPBRG = 16      ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
        Case 5
            'HSerial1_ChangeBaud 115200 <- this does not work!
            ;Calculated Baudrate = 111111 @ Xtal 4MHz, Error = -3.55%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 36      ; Enable transmit, BRGH = 0
            SPBRG = 8        ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
        Case Else
            'HSerial1_ChangeBaud 9600
            ;Calculated Baudrate = 9615 @ Xtal 4MHz, Error = 0.16%
            RCSTA = 144      ; Enable continuous receive
            TXSTA = 32      ; Enable transmit, BRGH = 0
            SPBRG = 25      ; Baud Rate Generator Low Byte Value
            SPBRGH = 0      ; Baud Rate Generator High Byte Value
            BAUDCON.3 = 1    ; Enable the 16 bit Baud Rate Generator
    EndSelect
Return