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: