pic_serial.c File Reference

Include dependency graph for pic_serial.c:

Functions

uns8 bin2Hex (uns8 x)
uns8 even_7bit_parity (uns8 in)
 Change 7th bit (MSB) to give even parity.
uns8 odd_7bit_parity (uns8 in)
 Change 7th bit (MSB) to give od parity.
uns8 serial_getc (void)
 Retrieve a character from the serial port.
void serial_print_int (uns16 i)
 Print a 16 bit number to the serial port.
void serial_print_int_hex (uns8 i)
 Print an 8 bit number in hex to the serial port.
void serial_print_int_hex_16bit (uns16 i)
 Print a 16 bit number in hex to the serial port.
void serial_print_nl ()
 Print a newline.
void serial_print_spc ()
 Print a space.
void serial_print_str (rom char *str)
void serial_print_str (char *str)
 Print a string out to the serial port.
void serial_print_var (char *str, uns16 i)
void serial_putc (uns8 c)
 Transmit a single character.
uns8 serial_rx_avail ()
 Tests if the serial rx fifo has a character available.
void serial_rx_isr ()
 Serial receive interrupt service routine.
void serial_setup (uns8 req_spbrg)
 Configure the pic for serial communicaitons.
uns8 serial_tx_empty ()
 Tests if the serial tx fifo is empty.
void serial_tx_isr ()
 Serial transmit interrupt service routine.

Variables

uns8 rx_buffer [SERIAL_RX_BUFFER_SIZE]
uns8 rx_end = 0
uns8 rx_start = 0
uns8 tx_buffer [SERIAL_TX_BUFFER_SIZE]
uns8 tx_end = 0
uns8 tx_start = 0

Function Documentation

uns8 bin2Hex ( uns8  x  )  [inline]

00130 {
00131    if (x < 10) {
00132      return '0' + x;
00133    } else {
00134      return 'A' -10 +  x;
00135    }
00136 }

Here is the caller graph for this function:

uns8 even_7bit_parity ( uns8  in  ) 

00063                                {
00064 
00065 uns8 t; 
00066  
00067  //return ((((((in)^(((in)<<4)|((in)>>4)))+0x41)|0x7C)+2)&0x80);
00068 
00069   
00070 asm {
00071     
00072     bcf    _in,7  ;assume the parity is even
00073       ;Note: for odd parity, use bsf
00074  ; assume the bits in byte_to_send are abcdefgh
00075 
00076     swapf  _in,W  ;W = efghabcd
00077     xorwf  _in,W  ;W = ea.fb.gc.hd.ea.fb.gc.hd
00078                            ; where ea means e^a, etc
00079     movwf  _t               ;
00080     rlf    _t,F            ;t = fb.gc.hd.ea.fb.gc.hd.??
00081     rlf    _t,F             ;t = gc.hd.ea.fb.gc.hd.??.ea
00082     xorwf  _t,F             ;t = gcea.hdfb.gcea.hdfb.gcea.?.?
00083                            ;again, gcea means g^c^e^a
00084     rlf    _t,W             ;w = hdfb.gcea.hdfb.gcea.hdfb.?.fb
00085     xorwf  _t,W             ;w = abcdefgh.abcdefgh.....
00086                            ;ie, the upper 5-bits of w each contain
00087                            ;the parity calculation.
00088     andlw  0x80            ;We only need one of them
00089     bcf   _in,7  ;set bit 7 to 0 in preparation for or-ing with our result    
00090     iorwf _in,F  ;copy it to the MSB of the byte to send.
00091 
00092 }
00093     return in;
00094 
00095 
00096 }

uns8 odd_7bit_parity ( uns8  in  ) 

00100                               {
00101 
00102 uns8 t;
00103 
00104 asm {
00105     bsf    _in,7  ;assume the parity is odd
00106 
00107  ; assume the bits in "in" are abcdefgh
00108 
00109     swapf  _in,W  ;W = efghabcd
00110     xorwf  _in,W  ;W = ea.fb.gc.hd.ea.fb.gc.hd
00111                            ; where ea means e^a, etc
00112     movwf  _t               ;
00113     rlf    _t,F            ;t = fb.gc.hd.ea.fb.gc.hd.??
00114     rlf    _t,F             ;t = gc.hd.ea.fb.gc.hd.??.ea
00115     xorwf  _t,F             ;t = gcea.hdfb.gcea.hdfb.gcea.?.?
00116                            ;again, gcea means g^c^e^a
00117     rlf    _t,W             ;w = hdfb.gcea.hdfb.gcea.hdfb.?.fb
00118     xorwf  _t,W             ;w = abcdefgh.abcdefgh.....
00119                            ;ie, the upper 5-bits of w each contain
00120                            ;the parity calculation.
00121     andlw  0x80            ;We only need one of them
00122     bcf   _in,7  ;set bit 7 to 0 in preparation for or-ing with our result
00123     iorwf _in,F  ;copy it to the MSB of the byte to send.
00124 }
00125     return in;
00126 }   

uns8 serial_getc ( void   ) 

Retrieve character from the serial port. Note that if there is nothing in the fifo, this function will wait until a character is received - and this will never happen if interrupts are turned off when this is called! So, be careful not to call getc during a critical section or during an ISR unless* you're sure there's something in the fifo. You can do this by calling the serial_rx_avail() routine. In any other situation, you can call getc() and happily wait for a character to arrive.

00341 {
00342     uns8 rx_char, rx_next;
00343     
00344     while(rx_end == rx_start);  // wait until there is something received
00345 
00346     start_crit_sec();   // make sure nobody else can muck with the buffer
00347     
00348     rx_char = rx_buffer[rx_start];  // get character from the front of the buffer
00349     rx_start++; // increment fifo start
00350     if (rx_start == SERIAL_RX_BUFFER_SIZE) {    // if we're at the end
00351         rx_start = 0;   // then wrap to the beginning
00352     }
00353     
00354     end_crit_sec(); // now they can muck with the buffer
00355     
00356     return (rx_char);   // return the result we first thought of
00357 
00358 }   // -- getc    

Here is the caller graph for this function:

void serial_print_int ( uns16  i  ) 

Print a 16 bit unsigned number in decimal to the serial port

Parameters:
i the 16 bit number to be printed

00386                                {
00387 
00388 char buffer[6]; // up to 5 characters plus \0
00389 uns8 count = 5;
00390     buffer[5] = '\0';
00391     do {
00392         count--;
00393         buffer[count] = '0' + i % 10;
00394         i = i / 10;
00395     } while (i > 0);    
00396     while (buffer[count]) {
00397         serial_putc(buffer[count]);
00398         count++;
00399     }  
00400     //serial_print_str(&buffer[count]); //  print it out 
00401 //  for(count = 0 ; str[count] != 0; count++)
00402  //   {
00403  //   }
00404 
00405 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_int_hex ( uns8  i  ) 

Print a 8 bit unsigned number in hex to the serial port

Parameters:
i 8 bit number to be printed

00407                                   {
00408 
00409     serial_putc(bin2Hex(i >> 4));
00410     serial_putc(bin2Hex((i & 0x0f)));
00411     
00412 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_int_hex_16bit ( uns16  i  ) 

Print a 16 bit unsigned number in hex to the serial port

Parameters:
i 16 bit number to be printed

00414                                          {
00415     serial_print_int_hex(i >> 8);
00416     serial_print_int_hex(i & 0xff);
00417 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_nl (  ) 

Print a new line out the serial port - if you do this often, this routine can be used to save a couple of instructions. Always helps!

00425                        {
00426         serial_putc('\n');
00427 }       

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_spc (  ) 

Print a space out the serial port - if you do this often, this routine can be used to save a couple of instructions. Always helps!

00420                         {
00421         serial_putc(' ');
00422 }

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_str ( rom char *  str  ) 

00374                                      {
00375 
00376 uns8 count;
00377 
00378     for(count = 0 ; str[count] != 0; count++)
00379     {
00380         serial_putc(str[count]);
00381     }
00382 }    

Here is the call graph for this function:

void serial_print_str ( char *  str  ) 

Send a null terminated string out the serial port

Parameters:
str the string to be sent

00362                                  {
00363 
00364 uns8 count;
00365 
00366     for(count = 0 ; str[count] != 0; count++)
00367     {
00368         serial_putc(str[count]);
00369     }
00370 }    

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_print_var ( char *  str,
uns16  i 
)

00429                                           {
00430     serial_print_str(str);
00431     serial_print_int(i);
00432     serial_print_nl();
00433 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void serial_putc ( uns8  c  ) 

Sends a single character out the serial connection. It is sent straight out if possible, otherwise put into the fifo. Note that if you fill the fifo while interrupts are off (eg, in an interrupt routine or a critical section) then this routine will hang the pic, since it's waiting for an interrupt to clear the fifo, which never comes... The moral is to keep your fifo big enough or don't send too much while interrupts are off (eg, in an interrupt response routine). Of course, you *can* send things in an ISR - just don't fill the fifo up.

Parameters:
c the character to transmit

00237 {
00238 uns8 tx_next;
00239 bit  my_store_gie;
00240 #ifdef SERIAL_IDE_DEBUG
00241 return;
00242 #endif
00243 
00244     if ((tx_end == tx_start) &&  // Nothing in the fifo
00245         test_bit(pir1, TXIF)) {  // And txreg is empty
00246         txreg = c;               // then no need for fifo, just send straight out 
00247     } else { // else put it in the fifo  
00248         tx_next = tx_end + 1;   // get next buffer position
00249         if (tx_next == SERIAL_TX_BUFFER_SIZE) { // if we're at the end
00250             tx_next = 0;    // wrap to the beginning
00251         }
00252         #ifdef SERIAL_DISCARD_ON_TX_FULL_DURING_INT
00253             if ((!intcon.GIE) && (tx_next == tx_start)) {
00254                 return;
00255             }
00256         #endif  
00257         while (tx_next == tx_start) { // wait for clearing
00258                                      // Note, if buffer is full
00259                                      // this will wait for ever
00260                                      // if interrupts are disabled!
00261             #ifndef SERIAL_DISCARD_ON_TX_FULL_DURING_INT
00262                 if (!intcon.GIE) {  // we're in an interrupt
00263                     serial_handle_tx_isr(); // so handle it ourselves
00264                 }
00265             #endif  
00266         }       
00267         my_store_gie = intcon.GIE;  // store interrupt state
00268         kill_interrupts();  // turn off global interrupts
00269         
00270         tx_buffer[tx_end] = c; // put it in
00271         tx_end = tx_next;  // move pointer along
00272         
00273         set_bit(pie1, TXIE); // turn on interrupt for transmitting
00274         intcon.GIE = my_store_gie;  // restore interrupt state
00275     } // -- else put it in the fifo
00276 } 

Here is the caller graph for this function:

uns8 serial_rx_avail ( void   ) 

Tests to see if the serial receive fifo has a character available. Useful to call before getc() if interrupts are not enabled in that section of code.

Returns:
true (non zero) if there are one or more characters waiting in the fifo queue, false (zero) otherwise

00435 { return rx_start != rx_end; }

Here is the caller graph for this function:

void serial_rx_isr ( void   ) 

This routine needs to be called from your interrupt() routine when the receive hardware interrupt occurs in order to put received bytes into the fifo buffer.

00301 {
00302    uns8 rx_next;
00303     
00304 
00305     if (test_bit(rcsta, OERR)) {    // overrun error?
00306         clear_bit(rcsta, CREN); // clear error
00307         _asm    {   
00308             MOVF    _rcreg,W    // clear any received characters
00309             MOVF    _rcreg,W
00310             MOVF    _rcreg,W
00311         }
00312         #ifdef SERIAL_DEBUG
00313         rx_hard_overflow++; // increment error count if in debug mode
00314         #endif
00315         set_bit(rcsta, CREN);   // reset error indicator
00316     } else {
00317         if (test_bit(rcsta, FERR)) {    // framing error?
00318             #ifdef SERIAL_DEBUG
00319             rx_framing_error++; // increment error count if in debug mode
00320             #endif
00321         }   
00322         rx_next = rx_end + 1;   // get next buffer position 
00323         if (rx_next == SERIAL_RX_BUFFER_SIZE) { // if we're at the end
00324             rx_next = 0;    // then wrap to the beginning
00325         }
00326         if (rx_next != rx_start) { // if space in the fifo
00327             rx_buffer[rx_end] = rcreg; // put it in
00328             rx_end = rx_next;  // and move pointer along
00329         } else {    // else, there isn't space
00330             _asm MOVF   _rcreg,W // and just clear it, we've lost it
00331             #ifdef SERIAL_DEBUG
00332             rx_soft_overflow++; // increment error count if in debug mode
00333             #endif
00334         }   // -- no space in the fifo
00335     }   // -- no overrun error
00336 }   // -- serial_load_rx

void serial_setup ( uns8  req_spbrg  ) 

Configures the pic and gets ready for interrupt-driven serial communications. Includes setting the tris bits appropriately, and getting the baud rate generator set up. After calling this you can immediately start sending and receiving bytes.

Parameters:
brgh See sprg defines earlier in pic_serial.h

00143 {
00144 #ifdef _PIC16F88
00145     set_bit(trisb, 5);
00146     set_bit(trisb, 2);
00147     #define TRIS_SET
00148 #endif
00149 #ifdef _PIC16F876A
00150     set_bit(trisc,6);
00151     set_bit(trisc,7);
00152     #define TRIS_SET
00153 #endif
00154 #ifdef _PIC18F2620
00155     set_bit(trisc,6);
00156     set_bit(trisc,7);
00157     #define TRIS_SET
00158 #endif
00159 #ifdef _PIC18F4520
00160     set_bit(trisc,6);
00161     set_bit(trisc,7);
00162     #define TRIS_SET
00163 #endif
00164 #ifdef _PIC18F4550
00165     set_bit(trisc,6);
00166     set_bit(trisc,7);
00167     #define TRIS_SET
00168 #endif
00169 #ifdef _PIC18F67J50
00170     clear_bit(trisc,6);
00171     set_bit(trisc,7);
00172     #define TRIS_SET
00173 #endif
00174 #ifdef _PIC18F25K20
00175     set_bit(trisc,6);
00176     set_bit(trisc,7);
00177     #define TRIS_SET
00178 #endif
00179 #ifdef _PIC18F26K20
00180     set_bit(trisc,6);
00181     set_bit(trisc,7);
00182     #define TRIS_SET
00183 #endif
00184 #ifdef _PIC18F14K50
00185     set_bit(trisb,5);
00186     #define TRIS_SET
00187 #endif
00188 #ifndef TRIS_SET
00189     #warning "You must set tris bits for serial use yourself, I don't know your pic"
00190     #warning "Please send your tris bits in so they can be included in the library"
00191 #endif
00192 
00193     //kill_interrupts();
00194     
00195     
00196     
00197     txsta.BRGH = 1; // set baud rate generator (high/low speed)
00198     #ifdef BRG16_REQUIRED
00199         set_bit(baudcon, BRG16);
00200         spbrg = req_spbrg & 0xff;
00201         spbrgh = req_spbrg >> 8;
00202     #else
00203         spbrg = req_spbrg;  // set serial port baud rate generator value
00204     #endif
00205     clear_bit(txsta, SYNC); // turn off syncronous reception
00206     set_bit(rcsta, SPEN);   // enable serial port
00207 
00208     // Configure tx
00209 
00210     clear_bit(txsta, TX9);  // Turn off 9 bit receiption
00211     clear_bit(txsta, TX9D); // Clear 9th bit data
00212 
00213     set_bit(txsta, TXEN);   // enable sending of serial data 
00214 
00215     // configure rx
00216     
00217     clear_bit(rcsta, RX9);  // disable 9 bit receiption
00218     clear_bit(rcsta, FERR); // clear any framing errors
00219 
00220     _asm    {   // clear rcreg buffer
00221         MOVF    _rcreg,W
00222         MOVF    _rcreg,W
00223         MOVF    _rcreg,W
00224     }
00225 
00226     clear_bit(rcsta, CREN); 
00227     set_bit(rcsta, CREN);   // pulse low to clear any errors    
00228 
00229     set_bit(pie1, RCIE);    // enable receive interrupt
00230     
00231 }

Here is the caller graph for this function:

uns8 serial_tx_empty ( void   ) 

Tests to see if the serial transmit fifo is empty.

Returns:
true (non zero) if tx fifo is empty, false (zero) otherwise

00436 { return tx_start == tx_end; }

Here is the caller graph for this function:

void serial_tx_isr ( void   ) 

This routine needs to be called from your interrupt() routine when the transmit hardware interrupt occurs in order to send bytes that are waiting in the fifo buffer.

00281 {
00282 uns8 tx_next;
00283 
00284     if (tx_end == tx_start) { // anything in the fifo?
00285        return; // nope
00286     }
00287     tx_next = tx_start + 1; // get next position
00288     if (tx_next == SERIAL_TX_BUFFER_SIZE) { // if we're at the end of the buffer
00289         tx_next = 0;    // wrap to the beginning
00290     }
00291     if (tx_end == tx_next) {    // if we've only got one character to send
00292         clear_bit(pie1, TXIE);  // then turn off interrupts
00293     }       
00294     txreg = tx_buffer[tx_start];    // transmit the character
00295     tx_start = tx_next; // move start position of fifo
00296 
00297 }   /* \ \  */

Here is the caller graph for this function:


Variable Documentation

uns8 rx_buffer[SERIAL_RX_BUFFER_SIZE]

Receive fifo

uns8 rx_end = 0

Receive fifo end point

uns8 rx_start = 0

Receive fifo start point

uns8 tx_buffer[SERIAL_TX_BUFFER_SIZE]

Transmit fifo

uns8 tx_end = 0

Transmit fifo end point

uns8 tx_start = 0

Transmit fifo start point


Generated on Fri Aug 19 09:08:28 2011 for Pic Pack Library by  doxygen 1.6.1