PIC Specific RS232 Setup Macro

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: