pic_serial.h File Reference
Interrupt driven fifo serial support.
More...
Go to the source code of this file.
Detailed Description
Put the following into your config.h
- - - - - - - - - - - - - - - - - - - - pic_serial defines
- - - - - - - - - - - - - - - - - - - -
define SERIAL_TX_BUFFER_SIZE 20 define SERIAL_RX_BUFFER_SIZE 4
Use this define if you want fine-grained control of what happens in the serial port define SERIAL_DEBUG_ON
Use this define if you are debugging in the IDE simulator and don't want it to hang waiting for serial interrupts that will never come... define SERIAL_IDE_DEBUG
Use thie define if you want to drop a character if the TX buffer is full, rather than the default behaviour, which is to wait until the TX buffer has a spare spot. define SERIAL_DISCARD_ON_TX_FULL_DURING_INT
- - - - - - - - - - - - - - - - - - - -
Put the following in your ISR
serial_handle_tx_isr(); serial_handle_rx_isr();
Put the following in your system setup routine
serial_setup(uns8/16 req_spbrg);
Define Documentation
#define BRGH_HIGH_SPEED 1 |
#define serial_handle_rx_isr |
( |
|
) |
if (pir1.RCIF) { serial_rx_isr(); pir1.RCIF = 0; } |
#define serial_handle_tx_isr |
( |
|
) |
if (pir1.TXIF) { serial_tx_isr(); } |
#define serial_print_debug |
( |
string, |
|
|
variable |
|
) |
serial_print_str(string); serial_print_int(variable); serial_print_nl(); |
Function Documentation
uns8 even_7bit_parity |
( |
uns8 |
in |
) |
|
00063 {
00064
00065 uns8 t;
00066
00067
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.
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];
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
00401
00402
00403
00404
00405 }
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 |
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 |
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!
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!
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 }
void serial_print_str_rom |
( |
rom char * |
str |
) |
|
Send a null terminated rom string out the serial port
- Parameters:
-
| str | the rom string to be sent |
void serial_print_var |
( |
char * |
str, |
|
|
uns16 |
i | |
|
) |
| | |
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) &&
00245 test_bit(pir1, TXIF)) {
00246 txreg = c;
00247 } else {
00248 tx_next = tx_end + 1;
00249 if (tx_next == SERIAL_TX_BUFFER_SIZE) {
00250 tx_next = 0;
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) {
00258
00259
00260
00261 #ifndef SERIAL_DISCARD_ON_TX_FULL_DURING_INT
00262 if (!intcon.GIE) {
00263 serial_handle_tx_isr();
00264 }
00265 #endif
00266 }
00267 my_store_gie = intcon.GIE;
00268 kill_interrupts();
00269
00270 tx_buffer[tx_end] = c;
00271 tx_end = tx_next;
00272
00273 set_bit(pie1, TXIE);
00274 intcon.GIE = my_store_gie;
00275 }
00276 }
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
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)) {
00306 clear_bit(rcsta, CREN);
00307 _asm {
00308 MOVF _rcreg,W
00309 MOVF _rcreg,W
00310 MOVF _rcreg,W
00311 }
00312 #ifdef SERIAL_DEBUG
00313 rx_hard_overflow++;
00314 #endif
00315 set_bit(rcsta, CREN);
00316 } else {
00317 if (test_bit(rcsta, FERR)) {
00318 #ifdef SERIAL_DEBUG
00319 rx_framing_error++;
00320 #endif
00321 }
00322 rx_next = rx_end + 1;
00323 if (rx_next == SERIAL_RX_BUFFER_SIZE) {
00324 rx_next = 0;
00325 }
00326 if (rx_next != rx_start) {
00327 rx_buffer[rx_end] = rcreg;
00328 rx_end = rx_next;
00329 } else {
00330 _asm MOVF _rcreg,W
00331 #ifdef SERIAL_DEBUG
00332 rx_soft_overflow++;
00333 #endif
00334 }
00335 }
00336 }
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:
-
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
00194
00195
00196
00197 txsta.BRGH = 1;
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;
00204 #endif
00205 clear_bit(txsta, SYNC);
00206 set_bit(rcsta, SPEN);
00207
00208
00209
00210 clear_bit(txsta, TX9);
00211 clear_bit(txsta, TX9D);
00212
00213 set_bit(txsta, TXEN);
00214
00215
00216
00217 clear_bit(rcsta, RX9);
00218 clear_bit(rcsta, FERR);
00219
00220 _asm {
00221 MOVF _rcreg,W
00222 MOVF _rcreg,W
00223 MOVF _rcreg,W
00224 }
00225
00226 clear_bit(rcsta, CREN);
00227 set_bit(rcsta, CREN);
00228
00229 set_bit(pie1, RCIE);
00230
00231 }
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
Tests to see if the serial transmit fifo is full.
- Returns:
- true (non zero) if tx fifo is full, false (zero) otherwise
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) {
00285 return;
00286 }
00287 tx_next = tx_start + 1;
00288 if (tx_next == SERIAL_TX_BUFFER_SIZE) {
00289 tx_next = 0;
00290 }
00291 if (tx_end == tx_next) {
00292 clear_bit(pie1, TXIE);
00293 }
00294 txreg = tx_buffer[tx_start];
00295 tx_start = tx_next;
00296
00297 }