Skip to content

High speed RS232 for PIC

Seizing immense

If we take an arbitrary clock frequency and an arbitrary baud rate, the transmitter routine would still look similar to one of the examples given above. The only differences would be specific delays. It is reasonable to let compiler calculate these delays and place them in the routine body. Now our challenge is to write a macro that would produce transmitter routine for any specified baud rate at any specific clock frequency. What would be input for this macro? Clock frequency, baud rate, number of bits, port, pin, and space level (0 or 1). Since all applications in PIC work on the same clock J, we may pass it to our macro via a global constant or a definition. Other parameters may not be considered as global. For example, there may be a need of two transmitter routines sending via different ports with different speeds (such as main communication channel (slow) and debug output channel (fast)). Considering this, the first line of macro may look like:
RS_bodySEND macro speed, bits, port, pin, spacelvl

Next what we have to do is calculating instruction cycles per bit (CBP) and alignment. CBP is simply clock divided by speed (with fractional part ignored). To calculate alignment we will code a loop that accumulates and compares required bit lengths to the length achieved with CBP. If difference is greater than 0.5 IC, an alignment bit is set.

RS_calcCONST macro speed, bits
  local cycles, align
  local i, c
cycles = CLOCK / (speed / .25)          ; ((CLOCK / 4) / speed ) * 100
RS_CYCLESPERBIT set cycles / .100
i = 0
c = 0
align = 0
  while( i <= bits )                    ; bit alignment for all bits + stop bit
c = c + RS_CYCLESPERBIT
i++
   if( (i * cycles) - (c * .100) >= .50 )
align = align | (1 << (i-1) )           ; set alignment bit
c++
   endif
 endw
RS_BITALIGNMENT set align
 endm

Now we have to decide which template routine to use: looped or linear. RS_CYCLESPERBIT gives as a guidance: 10 and more may be achieved with the looped, lesser – only with the linear. As a result, the main macro is ready:

RS_bodySEND macro speed, bits, port, pin, spacelvl
     RS_calcCONST speed, bits
RS_#v(speed)SEND
     movwf    RS_DATA                          ; put data to rotation buffer
  if(RS_CYCLESPERBIT < .10)
     RS_bodySEND2_9 speed, bits, port, pin, spacelvl
  else
     RS_bodySEND10_H speed, bits, port, pin, spacelvl
  endif
  if( spacelvl )
     bcf      port, pin                        ; sending stop bit
  else
     bsf      port, pin                        ; sending stop bit
  endif
 endm

RS_DELAY0WC

addlw -.1 ; 4
skpz ; 5
goto RS_DELAY0WC ; 6
return ; 7

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*

*