mytekcontrols
- 25th October 2005, 19:50
The Problem: How can you automatically detect and set the hardware USART to match the incoming baudrate of an external source?
In the example below you will find my initial solution written entirely in PBP. It requires only one character be sent for synchronization (I chose the ascii space character as my baud rate detect character).
'*******************************************
' USART Auto Baud Rate Detection
' Author: Michael St. Pierre
' Date: 10/25/2005
' Notes: Based on Eddy Carroll article,
' April 1989
'*******************************************
DEFINE LOADER_USED 1 ' use for Boot Loader
DEFINE OSC 40
'============================================
' Equates (for PIC18F252 or PIC18F452)
'============================================
baudset var bit
rxdata var byte
Clear
RCIF VAR PIR1.5 ' USART receive interrupt flag
BRGH VAR TXSTA.2 ' High Baud Rate Select bit
OERR VAR RCSTA.1 ' Overrun Error bit
CREN VAR RCSTA.4 ' Continuous Receive Enable bit
'============================================
' Initialize USART
'============================================
' Set-up USART for initial 19.2K Baud Operation for 40 Mhz oscillator
SPBRG = 129
TXSTA = %00100100
RCSTA = %10010000
'============================================
' Program Start (MAIN)
'============================================
mainloop:
While RCIF = 0: Wend ; loop until data present in USART buffer
rxdata = RCREG ; retrieve data.
If baudset = 0 Then ; If this is the initial pass...
Gosub Autobaud ; detect and set baudrate,
baudset = 1 ; deactivate Auto-Baud Rate Detection,
Goto mainloop ; and skip data send.
Endif
TXREG = rxdata ; Send valid data bytes only!
Goto mainloop
'============================================
' Auto Baud Rate Detection Routine
' (Entry Baud Rate set to 19.2K)
'============================================
; A single space " " character required for auto detect function
; !!! No other characters should be sent prior to space !!!
; Format of data upon reception of space " " character:
; 4800 baud: 0 128 (2 bytes)
; 9600 baud: 0 248 (2 bytes)
; 19.2k baud: 32
; 38.4k baud: 244 or 252 (slight amount of uncertainty in data)
Autobaud:
If rxdata = 0 Then ; If 1st byte received = 0 then...
While RCIF = 0: Wend ; Loop until 2nd valid byte received,
rxdata = RCREG ; and fetch data.
Endif
Select Case rxdata
Case 128 ; @4800 Baud (2nd of two data bytes received)
BRGH = 0
SPBRG = 129
Case 248 ; @9600 Baud (2nd of two data bytes received)
BRGH = 0
SPBRG = 64
Case 32 ; @19.2K Baud (1st and only data byte received)
BRGH = 1
SPBRG = 129
Case Else ; @38.4K Baud (1st and only data byte received)
BRGH = 1
SPBRG = 64
End Select
If OERR Then ; If receive buffer overflowed, clear it!
CREN = 0
CREN = 1
Endif
Return ; Done, baud rate now set!
The original idea for this came from an article written by Eddy Carroll www.iol.ie/~ecarroll/autobaud.html in April of 1989. The idea of which was, that a given character would be interpreted in unique bit patterns if sent at different baud rates, and assuming the receiver was set to a "fixed" baud rate.
In my example, I have enabled 4 different baud rate frequencies to be detected (4800, 9600, 19.2K, 38.4K). These just happened to be the 4 that would properly work with an oscillator freq = 40 Mhz, without producing excessive bit errors. Other ranges can be used, but will require a crystal change, and different SPBRG and BRGH settings, and possibly different comparison strings based on the incoming data.
Any ideas on how to impove it?
In the example below you will find my initial solution written entirely in PBP. It requires only one character be sent for synchronization (I chose the ascii space character as my baud rate detect character).
'*******************************************
' USART Auto Baud Rate Detection
' Author: Michael St. Pierre
' Date: 10/25/2005
' Notes: Based on Eddy Carroll article,
' April 1989
'*******************************************
DEFINE LOADER_USED 1 ' use for Boot Loader
DEFINE OSC 40
'============================================
' Equates (for PIC18F252 or PIC18F452)
'============================================
baudset var bit
rxdata var byte
Clear
RCIF VAR PIR1.5 ' USART receive interrupt flag
BRGH VAR TXSTA.2 ' High Baud Rate Select bit
OERR VAR RCSTA.1 ' Overrun Error bit
CREN VAR RCSTA.4 ' Continuous Receive Enable bit
'============================================
' Initialize USART
'============================================
' Set-up USART for initial 19.2K Baud Operation for 40 Mhz oscillator
SPBRG = 129
TXSTA = %00100100
RCSTA = %10010000
'============================================
' Program Start (MAIN)
'============================================
mainloop:
While RCIF = 0: Wend ; loop until data present in USART buffer
rxdata = RCREG ; retrieve data.
If baudset = 0 Then ; If this is the initial pass...
Gosub Autobaud ; detect and set baudrate,
baudset = 1 ; deactivate Auto-Baud Rate Detection,
Goto mainloop ; and skip data send.
Endif
TXREG = rxdata ; Send valid data bytes only!
Goto mainloop
'============================================
' Auto Baud Rate Detection Routine
' (Entry Baud Rate set to 19.2K)
'============================================
; A single space " " character required for auto detect function
; !!! No other characters should be sent prior to space !!!
; Format of data upon reception of space " " character:
; 4800 baud: 0 128 (2 bytes)
; 9600 baud: 0 248 (2 bytes)
; 19.2k baud: 32
; 38.4k baud: 244 or 252 (slight amount of uncertainty in data)
Autobaud:
If rxdata = 0 Then ; If 1st byte received = 0 then...
While RCIF = 0: Wend ; Loop until 2nd valid byte received,
rxdata = RCREG ; and fetch data.
Endif
Select Case rxdata
Case 128 ; @4800 Baud (2nd of two data bytes received)
BRGH = 0
SPBRG = 129
Case 248 ; @9600 Baud (2nd of two data bytes received)
BRGH = 0
SPBRG = 64
Case 32 ; @19.2K Baud (1st and only data byte received)
BRGH = 1
SPBRG = 129
Case Else ; @38.4K Baud (1st and only data byte received)
BRGH = 1
SPBRG = 64
End Select
If OERR Then ; If receive buffer overflowed, clear it!
CREN = 0
CREN = 1
Endif
Return ; Done, baud rate now set!
The original idea for this came from an article written by Eddy Carroll www.iol.ie/~ecarroll/autobaud.html in April of 1989. The idea of which was, that a given character would be interpreted in unique bit patterns if sent at different baud rates, and assuming the receiver was set to a "fixed" baud rate.
In my example, I have enabled 4 different baud rate frequencies to be detected (4800, 9600, 19.2K, 38.4K). These just happened to be the 4 that would properly work with an oscillator freq = 40 Mhz, without producing excessive bit errors. Other ranges can be used, but will require a crystal change, and different SPBRG and BRGH settings, and possibly different comparison strings based on the incoming data.
Any ideas on how to impove it?