by Olin Lathrop [olin_piclist at COGNIVIS.COM]
[This is] a snippet from an include file containing a much larger collection of macros and such, so you need to set up some assembler state before calling the UART_BAUD macro. It looks like it needs FREQ_OSC, which is the oscillator frequency in Hz, and FAM_17 which is 1 on 17C family devices and 0 elsewhere.
I've used this a number of times with 16C devices successfully. I've just recently modified it to handle 17C devices but don't have target boards to test yet. I can't therefore absolutely promise I didn't introduce a bug, but you can't complain for the price...
;********************
;
; Macro UART_BAUD <baud>
;
; This macro sets assembler variables to indicate the best baud rate
; generator configuration for the USART in asynchronous mode, given the
; desired baud rate and the oscillator frequency. No code is generated.
; The following assembler variables are set:
;
; VAL_SPBRG - Value for the SPBRG baud rate generator register.
;
; BAUD_REAL - Real (not desired) baud rate resulting from the
; selected settings.
;
; VAL_TXSTA - Value for the TXSTA regisIB4 In addition to
; selecting the proper baud rate generator configuration, this
; value also selects the following:
;
; Asynchronous mode
; 8 bits per character
; transmitter enabled
;
; This macro produces an assembly time warning if the closest available
; baud rate is more then 2.9% from the desired baud rate (off by 25% of
; a bit time in the middle of the last bit). It produces an assembly
; error if the baud rate error is 5.8% or higher.
;
uart_baud macro baud
local err ;baud rate error in parts per 1000
;
; Init values assuming will use high speed mode.
;
if fam_17 ;17Cxx family doesn't have high speed mode
val_txsta set (1 << txen) ;set TXSTA register value
else
val_txsta set (1 << txen) | (1 << brgh) ;init TX config for high speed mode
endif
val_spbrg set freq_osc * 16 / baud - 256 ;find divider value, 8 fraction bits
val_spbrg set (val_spbrg + 128) >> 8 ;round and scale to final SPBRG value
baud_real set freq_osc / (16 * (val_spbrg + 1)) ;find actual selected baud rate
;
; Switch to low speed mode if the baud rate generator value would require
; more than 8 bits to represent, or this chip has not high speed mode.
;
if (val_spbrg > 255) || fam_17 ;too slow for high speed mode or no HS ?
if ! fam_17
val_txsta set val_txsta & ~(1 << brgh) ;disable high speed mode
endif
val_spbrg set freq_osc * 4 / baud - 256 ;find divider value, 8 fraction bits
val_spbrg set (val_spbrg + 128) >> 8 ;round and scale to final SPBRG value
if val_spbrg > 255 ;clip at largest allowable baud rate generator value
val_spbrg set 255
endif
baud_real set freq_osc / (64 * (val_spbrg + 1)) ;find actual selected baud rate
endif
err set (1000 * (baud_real - baud)) / baud ;baud rate err in parts/1000
if err < 0
err set -err ;make absolute value of error
endif
if err > 58
error "Baud rate error exceeds 5.8%"
endif
if err > 29
messg "WARNING: Baud rate error exceeds 2.9%"
endif
endm
See:
Questions: