PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pic24_uart.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 
31 
32 
33 #include "pic24_clockfreq.h"
34 #include "pic24_uart.h"
35 #include "pic24_ports.h"
36 #include "pic24_unittest.h"
37 #include "pic24_delay.h"
38 
39 // Only include if this UART exists.
40 #if (NUM_UART_MODS >= 1)
41 
42 
43 // Documentation for this file. If the \file tag is not present,
44 // this file will not be documented.
45 // Note: place this comment below the #if NUM_UART_MODS so Doxygen
46 // will only see it once.
47 /** \file
48 * UART support functions.
49 * \par Interrupt-driven TX/RX
50 * By default, the UART functions use polling for both RX and TX.
51 * Define the macro UARTx_TX_INTERRUPT (i.e., UART1_TX_INTERRUPT) in your project file if you want interrupt-driven TX for the UARTx (i.e., UART1) module.
52 * For interrupt-driven TX, macro UARTx_TX_FIFO_SIZE sets the TX software FIFO size (default 32), and UARTx_TX_INTERRUPT_PRIORITY sets the priority (default 1).
53 * \par
54 * Define the macro UARTx_RX_INTERRUPT (i.e., UART1_RX_INTERRUPT) in your project file if you want interrupt-driven RX for the UARTx (i.e., UART1) module.
55 * For interrupt-driven RX, macro UARTx_RX_FIFO_SIZE sets the RX software FIFO size (default 32), and UARTx_RX_INTERRUPT_PRIORITY sets the priority (default 1).
56 */
57 
58 
59 /*********************************************************
60  * Public functions intended to be called by other files *
61  *********************************************************/
62 /**
63 * Check UART1 RX for error, call \em reportError() if error found.
64 *
65 */
66 void checkRxErrorUART1(void) {
67  uint8_t u8_c;
68  //check for errors, reset if detected.
69  if (U1STAbits.PERR) {
70  u8_c = U1RXREG; //clear error
71  reportError("UART1 parity error\n");
72  }
73  if (U1STAbits.FERR) {
74  u8_c = U1RXREG; //clear error
75  reportError("UART1 framing error\n");
76  }
77  if (U1STAbits.OERR) {
78  U1STAbits.OERR = 0; //clear error
79  reportError("UART1 overrun error\n");
80  }
81 }
82 
83 
84 
85 
86 #ifdef UART1_TX_INTERRUPT
87 /**
88 
89 */
90 #ifndef UART1_TX_FIFO_SIZE
91 #define UART1_TX_FIFO_SIZE 32 //choose a size
92 #endif
93 
94 #ifndef UART1_TX_INTERRUPT_PRIORITY
95 #define UART1_TX_INTERRUPT_PRIORITY 1
96 #endif
97 
98 volatile uint8_t au8_txFifo1[UART1_TX_FIFO_SIZE];
99 volatile uint16_t u16_txFifo1Head = 0;
100 volatile uint16_t u16_txFifo1Tail = 0;
101 
102 /**
103 * Output \em u8_c to UART1 TX.
104 * \param u8_c Character to write
105 */
106 void outChar1(uint8_t u8_c) {
107  uint16_t u16_tmp;
108 
109  u16_tmp = u16_txFifo1Head;
110  u16_tmp++;
111  if (u16_tmp == UART1_TX_FIFO_SIZE) u16_tmp = 0; //wrap if needed
112  while (u16_tmp == u16_txFifo1Tail)
113  doHeartbeat();
114 
115  au8_txFifo1[u16_tmp] = u8_c; //write to buffer
116  u16_txFifo1Head = u16_tmp; //update head
117  _U1TXIE = 1; //enable interrupt
118 }
119 
120 void _ISR _U1TXInterrupt (void) {
121  if (u16_txFifo1Head == u16_txFifo1Tail) {
122  //empty TX buffer, disable the interrupt, do not clear the flag
123  _U1TXIE = 0;
124  } else {
125  //at least one free spot in the TX buffer!
126  u16_txFifo1Tail++; //increment tail pointer
127  if (u16_txFifo1Tail == UART1_TX_FIFO_SIZE)
128  u16_txFifo1Tail = 0; //wrap if needed
129  _U1TXIF = 0; //clear the interrupt flag
130  //transfer character from software buffer to transmit buffer
131  U1TXREG = au8_txFifo1[u16_txFifo1Tail];
132  }
133 }
134 
135 
136 #else
137 /**
138 * Output \em u8_c to UART1 TX.
139 * \param u8_c Character to write
140 */
141 void outChar1(uint8_t u8_c) {
142  //wait for transmit buffer to be empty
144  doHeartbeat();
145  U1TXREG = u8_c;
146 }
147 #endif
148 
149 #ifdef UART1_RX_INTERRUPT
150 //Interrupt driven RX
151 #ifndef UART1_RX_FIFO_SIZE
152 #define UART1_RX_FIFO_SIZE 32 //choose a size
153 #endif
154 
155 #ifndef UART1_RX_INTERRUPT_PRIORITY
156 #define UART1_RX_INTERRUPT_PRIORITY 1
157 #endif
158 
159 volatile uint8_t au8_rxFifo1[UART1_RX_FIFO_SIZE];
160 volatile uint16_t u16_rxFifo1Head = 0;
161 volatile uint16_t u16_rxFifo1Tail = 0;
162 
163 /**
164 * Return true if character is ready to be read
165 */
166 uint8_t isCharReady1(void) {
167  return(u16_rxFifo1Head != u16_rxFifo1Tail);
168 }
169 
170 /**
171 * Wait for a byte to be available from UART1 RX.
172 * \return Character read from UART1 RX.
173 */
174 uint8_t inChar1(void) {
175  while (u16_rxFifo1Head == u16_rxFifo1Tail)
176  doHeartbeat();
177  u16_rxFifo1Tail++;
178  if (u16_rxFifo1Tail == UART1_RX_FIFO_SIZE) u16_rxFifo1Tail=0; //wrap
179  return au8_rxFifo1[u16_rxFifo1Tail]; //return the character
180 }
181 
182 void _ISR _U1RXInterrupt (void) {
183  int8_t u8_c;
184 
185  _U1RXIF = 0; //clear the UART RX interrupt bit
187  u8_c = U1RXREG; //read character
188  u16_rxFifo1Head++; //increment head pointer
189  if (u16_rxFifo1Head == UART1_RX_FIFO_SIZE)
190  u16_rxFifo1Head = 0; //wrap if needed
191  if (u16_rxFifo1Head == u16_rxFifo1Tail) {
192  //FIFO overrun!, report error
193  reportError("UART1 RX Interrupt FIFO overrun!");
194  }
195  au8_rxFifo1[u16_rxFifo1Head] = u8_c; //place in buffer
196 }
197 
198 #else
199 /**
200 * Return true if character is ready to be read
201 */
203  return(IS_CHAR_READY_UART1());
204 }
205 
206 /**
207 * Wait for a byte to be available from UART1 RX.
208 * \return Character read from UART1 RX.
209 */
211  //do heartbeat while waiting for character.
212  // Use a do-while to insure error checks
213  // are always run.
214  while (!IS_CHAR_READY_UART1())
215  doHeartbeat();
217  return U1RXREG; //read the receive register
218 }
219 #endif
220 
221 
222 
223 /** Chose a default BRGH for UART1, used by
224  * \ref configUART1 to set up UART1.
225  */
226 #ifndef DEFAULT_BRGH1
227 #define DEFAULT_BRGH1 DEFAULT_BRGH
228 #endif
229 
230 #if (DEFAULT_BRGH1 != 0) && (DEFAULT_BRGH1 != 1)
231 #error Invalid value specified for DEFAULT_BRGH1
232 #endif
233 
234 
235 /** Configure the UART. Settings chosen:
236  * - TX is on RP11
237  * - RX is on RP10
238  * - Format is 8 data bits, no parity, 1 stop bit
239  * - CTS, RTS, and BCLK not used
240  *
241  * \param u32_baudRate The baud rate to use.
242  */
243 void configUART1(uint32_t u32_baudRate) {
244 #ifdef _NOFLOAT
245  uint32_t u32_brg;
246 #else
247  float f_brg;
248 #endif
249 
250  /************************* UART config ********************/
251  // See comments in the #warning statements below for
252  // instructions on how to modify this configuration.
253  // More information on each of these board is given
254  // in the HARDWARE_PLATFORM section of pic24_libconfig.h.
255 #if (HARDWARE_PLATFORM == EXPLORER16_100P)
256  // There's nothing to do, since pins on these boards are
257  // mapped to fixed ports.
258 #elif (1 == 1)
259  // The following pin mappings will apply only to UART 1.
260  // Change them as necessary for your device.
261  #if (HARDWARE_PLATFORM == DANGEROUS_WEB)
262  CONFIG_RP14_AS_DIG_PIN(); // RX RP pin must be digital
263  CONFIG_U1RX_TO_RP(14); // U1RX <- RP14
264  CONFIG_RP15_AS_DIG_PIN(); // TX RP pin must be digital
265  CONFIG_U1TX_TO_RP(15); // U1TX -> RP15
266  CONFIG_RP10_AS_DIG_PIN(); // RX RP pin must be digital
267  // turn off any analog functionality on these pins
268  // (may be needed if pin is hardmapped and RPx does
269  // not exist)
270  DISABLE_U1TX_ANALOG();
271  DISABLE_U1RX_ANALOG();
272  #elif (HARDWARE_PLATFORM == STARTER_BOARD_28P)
273  CONFIG_RP9_AS_DIG_PIN(); // RX RP pin must be digital
274  CONFIG_U1RX_TO_RP(9); // U1RX <- RP9
275  CONFIG_RP8_AS_DIG_PIN(); // TX RP pin must be digital
276  CONFIG_U1TX_TO_RP(8); // U1TX -> RP8
277  // turn off any analog functionality on these pins
278  // (may be needed if pin is hardmapped and RPx does
279  // not exist)
280  DISABLE_U1TX_ANALOG();
281  DISABLE_U1RX_ANALOG();
282  #elif (HARDWARE_PLATFORM == DEFAULT_DESIGN)
283  #if ( defined(__PIC24E__) || defined(__dsPIC33E__))
284  CONFIG_U1RX_TO_RP(42); //U1RX <- RP42
285  CONFIG_RP43_AS_DIG_PIN(); //TX RP pin must be digital
286  CONFIG_U1TX_TO_RP(43); //U1TX -> RP43
287  #else
288  CONFIG_U1RX_TO_RP(10); //U1RX <- RP10
289  CONFIG_RP11_AS_DIG_PIN(); //TX RP pin must be digital
290  CONFIG_U1TX_TO_RP(11); //U1TX -> RP11
291  #endif
292  // turn off any analog functionality on these pins
293  // (may be needed if pin is hardmapped and RPx does
294  // not exist)
295  DISABLE_U1TX_ANALOG();
296  DISABLE_U1RX_ANALOG();
297  #else
298  #error Unknown hardware platform.
299  #endif
300 #else
301  #warning UART1 pin mappings not defined. See comments below for more info.
302  // If your device has more than one UART, ****** CHANGE THE MAPPING ******
303  // since multiple UARTs can not share the same pins. In particular:
304  // 1. Change the statement #if (1 == 1) to #if 1
305  // 2. Change the pin numbers above
306  // to something valid for your device.
307  // If your device does not have remappable I/O,
308  // (typical for >44 pin packages), skip this step --
309  // the UART I/O pins are already assigned to something
310  // valid.
311 #endif
312 
313  // First, disable the UART, clearing all errors, terminating
314  // any in-progress transmissions/receptions, etc.
315  // In particular, this clears UTXEN.
316  U1MODE = (0u << 15); // UARTEN = 0 to disable.
317 
318  /* Configure UART baud rate, based on \ref FCY.
319  * NOTE: Be careful about using BRGH=1 - this uses only four clock
320  * periods to sample each bit and can be very intolerant of
321  * baud rate % error - you may see framing errors. BRGH is selected
322  * via the DEFAULT_BRGH1 define above.
323  */
324 #ifdef _NOFLOAT
325  u32_brg = FCY/u32_baudRate;
326 #if (DEFAULT_BRGH1 == 0)
327  if ((u32_brg & 0x0FL) >= 8) u32_brg = u32_brg/16;
328  else u32_brg = u32_brg/16 - 1;
329 #else
330  if ((brg & 0x03L) >= 2) u32_brg = u32_brg/4;
331  else u32_brg = u32_brg/4 - 1;
332 #endif
333  ASSERT(u32_brg < 65536);
334  U1BRG = u32_brg;
335 #else
336 #if (DEFAULT_BRGH1 == 0)
337  f_brg = (((float) FCY)/((float) u32_baudRate)/16.0) - 1.0;
338 #else
339  f_brg = (((float) FCY)/((float) u32_baudRate)/4.0) - 1.0;
340 #endif
341  ASSERT(f_brg < 65535.5);
342  U1BRG = roundFloatToUint16(f_brg);
343 #endif
344 
345  // Set up the UART mode register
346  U1MODE =
347  (1u << 15) | // UARTEN = 1 (enable the UART)
348  (0u << 13) | // USIDL = 0 (continue operation in idle mode)
349  (0u << 12) | // IREN = 0 (IrDA encoder and decoder disabled)
350  (0u << 11) | // RTSMD = 0 (UxRTS# in flow control mode. Given
351  // the UEN setting below, this doesn't matter.)
352  (0b00 << 8) | // UEN = 00 (UxTX and UxRx pins are enabled and used;
353  // used; UxCTS, UxRTS, and BCLKx pins are
354  // controlled by port latches)
355  (0u << 7) | // WAKE = 0 (Wake-up on start bit detect during
356  // sleep mode disabled)
357  (0u << 6) | // LPBACK = 0 (UARTx loopback mode is disabled)
358  (0u << 5) | // ABAUD = 0 (Auto-baud disabled)
359  (0u << 4) | // URXINV = 0 (Receve polarity inversion bit:
360  // UxRX idle state is 1)
361  (DEFAULT_BRGH1 << 3) | // BRGH (High/low baud rate select bit:
362  // 1 = high speed, 0 = low speed)
363  (0b00 << 1) | // PDSEL = 00 (8-bit data, no parity)
364  (0u << 0); // STSEL = 0 (1 stop bit)
365 
366  // Set up the UART status and control register
367  U1STA =
368  (0u << 15) | // UTXISEL1 = 0 (See bit 13 below for explanation)
369  (0u << 14) | // UTXINV = 0 (UxTX idle state is 1 (though docs
370  // say 0))
371  (0u << 13) | // UTXISEL0 = 0 (With bit 15 above, UTXISEL = 00:
372  // Interrupt generated when any character
373  // is transferred to the Transmit Shift Register).
374  (0u << 11) | // UTXBRK = 0 (Sync break transmission disabled)
375  (1u << 10) | // UTXEN = 0 (UARTx transmitter enabled. NOTE: per
376  // the data sheet, this must be set *AFTER* UARTEN
377  // is set to 1 (see UxMODE assignment above).
378  (0b00 << 6) | // URXISEL = 00 (Interrupt flag bit is set when a
379  // character is received)
380  (0u << 5) | // ADDEN = 0 (Address detect mode disabled)
381  (0u << 1); // OERR = 0 (Clear any overrun errors)
382 
383  // Delay 1 ms (at least one bit time) before beginning transmission,
384  // since the UxTX pin is initially configured as an input on device
385  // reset. It needs to be high for at least one bit time before
386  // a character is sent in order for the start bit to be recognized.
387  // See 24H FRM Sec. 17.5 for more details.
388  ASSERT(u32_baudRate >= 1000L);
389  // Note: If the baud rate is less than 1000, this delay
390  // isn't long encough. The alternative is to use floating-point
391  // math to compute the correct delay, which seems worse than the
392  // problem.
393  DELAY_MS(1);
394 
395  // Clear any errors
396  U1STAbits.OERR = 0;
397  while (U1STAbits.PERR || U1STAbits.FERR) {
398  U1RXREG; //clear errors by reading RXREG
399  }
400 
401  // Set up interrupts if requested
402 #ifdef UART1_RX_INTERRUPT
403  _U1RXIF = 0; //clear the flag
404  _U1RXIP = UART1_RX_INTERRUPT_PRIORITY; //choose a priority
405  _U1RXIE = 1; //enable the interrupt
406 #endif
407 #ifdef UART1_TX_INTERRUPT
408  //do not clear the U1TXIF flag!
409  _U1TXIP = UART1_TX_INTERRUPT_PRIORITY; //choose a priority
410  //do not enable the interrupt until we try to write to the UART
411 #endif
412 
413 }
414 
415 #endif // #if (NUM_UARTS >= 1)
416 
417 
418 
419 
420 /*
421  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
422  * All rights reserved.
423  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
424  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
425  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
426  *
427  * Permission to use, copy, modify, and distribute this software and its
428  * documentation for any purpose, without fee, and without written agreement is
429  * hereby granted, provided that the above copyright notice, the following
430  * two paragraphs and the authors appear in all copies of this software.
431  *
432  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
433  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
434  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
435  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
436  *
437  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
438  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
439  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
440  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
441  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
442  *
443  * Please maintain this header in its entirety when copying/modifying
444  * these files.
445  *
446  *
447  */
448 
449 
450 
451 
452 #include "pic24_clockfreq.h"
453 #include "pic24_uart.h"
454 #include "pic24_ports.h"
455 #include "pic24_unittest.h"
456 #include "pic24_delay.h"
457 
458 // Only include if this UART exists.
459 #if (NUM_UART_MODS >= 2)
460 
461 
462 // Documentation for this file. If the \file tag is not present,
463 // this file will not be documented.
464 // Note: place this comment below the #if NUM_UART_MODS so Doxygen
465 // will only see it once.
466 /** \file
467 * UART support functions.
468 * \par Interrupt-driven TX/RX
469 * By default, the UART functions use polling for both RX and TX.
470 * Define the macro UARTx_TX_INTERRUPT (i.e., UART1_TX_INTERRUPT) in your project file if you want interrupt-driven TX for the UARTx (i.e., UART1) module.
471 * For interrupt-driven TX, macro UARTx_TX_FIFO_SIZE sets the TX software FIFO size (default 32), and UARTx_TX_INTERRUPT_PRIORITY sets the priority (default 1).
472 * \par
473 * Define the macro UARTx_RX_INTERRUPT (i.e., UART1_RX_INTERRUPT) in your project file if you want interrupt-driven RX for the UARTx (i.e., UART1) module.
474 * For interrupt-driven RX, macro UARTx_RX_FIFO_SIZE sets the RX software FIFO size (default 32), and UARTx_RX_INTERRUPT_PRIORITY sets the priority (default 1).
475 */
476 
477 
478 /*********************************************************
479  * Public functions intended to be called by other files *
480  *********************************************************/
481 /**
482 * Check UART2 RX for error, call \em reportError() if error found.
483 *
484 */
485 void checkRxErrorUART2(void) {
486  uint8_t u8_c;
487  //check for errors, reset if detected.
488  if (U2STAbits.PERR) {
489  u8_c = U2RXREG; //clear error
490  reportError("UART2 parity error\n");
491  }
492  if (U2STAbits.FERR) {
493  u8_c = U2RXREG; //clear error
494  reportError("UART2 framing error\n");
495  }
496  if (U2STAbits.OERR) {
497  U2STAbits.OERR = 0; //clear error
498  reportError("UART2 overrun error\n");
499  }
500 }
501 
502 
503 
504 
505 #ifdef UART2_TX_INTERRUPT
506 /**
507 
508 */
509 #ifndef UART2_TX_FIFO_SIZE
510 #define UART2_TX_FIFO_SIZE 32 //choose a size
511 #endif
512 
513 #ifndef UART2_TX_INTERRUPT_PRIORITY
514 #define UART2_TX_INTERRUPT_PRIORITY 1
515 #endif
516 
517 volatile uint8_t au8_txFifo2[UART2_TX_FIFO_SIZE];
518 volatile uint16_t u16_txFifo2Head = 0;
519 volatile uint16_t u16_txFifo2Tail = 0;
520 
521 /**
522 * Output \em u8_c to UART2 TX.
523 * \param u8_c Character to write
524 */
525 void outChar2(uint8_t u8_c) {
526  uint16_t u16_tmp;
527 
528  u16_tmp = u16_txFifo2Head;
529  u16_tmp++;
530  if (u16_tmp == UART2_TX_FIFO_SIZE) u16_tmp = 0; //wrap if needed
531  while (u16_tmp == u16_txFifo2Tail)
532  doHeartbeat();
533 
534  au8_txFifo2[u16_tmp] = u8_c; //write to buffer
535  u16_txFifo2Head = u16_tmp; //update head
536  _U2TXIE = 1; //enable interrupt
537 }
538 
539 void _ISR _U2TXInterrupt (void) {
540  if (u16_txFifo2Head == u16_txFifo2Tail) {
541  //empty TX buffer, disable the interrupt, do not clear the flag
542  _U2TXIE = 0;
543  } else {
544  //at least one free spot in the TX buffer!
545  u16_txFifo2Tail++; //increment tail pointer
546  if (u16_txFifo2Tail == UART2_TX_FIFO_SIZE)
547  u16_txFifo2Tail = 0; //wrap if needed
548  _U2TXIF = 0; //clear the interrupt flag
549  //transfer character from software buffer to transmit buffer
550  U2TXREG = au8_txFifo2[u16_txFifo2Tail];
551  }
552 }
553 
554 
555 #else
556 /**
557 * Output \em u8_c to UART2 TX.
558 * \param u8_c Character to write
559 */
560 void outChar2(uint8_t u8_c) {
561  //wait for transmit buffer to be empty
562  while (IS_TRANSMIT_BUFFER_FULL_UART2())
563  doHeartbeat();
564  U2TXREG = u8_c;
565 }
566 #endif
567 
568 #ifdef UART2_RX_INTERRUPT
569 //Interrupt driven RX
570 #ifndef UART2_RX_FIFO_SIZE
571 #define UART2_RX_FIFO_SIZE 32 //choose a size
572 #endif
573 
574 #ifndef UART2_RX_INTERRUPT_PRIORITY
575 #define UART2_RX_INTERRUPT_PRIORITY 1
576 #endif
577 
578 volatile uint8_t au8_rxFifo2[UART2_RX_FIFO_SIZE];
579 volatile uint16_t u16_rxFifo2Head = 0;
580 volatile uint16_t u16_rxFifo2Tail = 0;
581 
582 /**
583 * Return true if character is ready to be read
584 */
585 uint8_t isCharReady2(void) {
586  return(u16_rxFifo2Head != u16_rxFifo2Tail);
587 }
588 
589 /**
590 * Wait for a byte to be available from UART2 RX.
591 * \return Character read from UART2 RX.
592 */
593 uint8_t inChar2(void) {
594  while (u16_rxFifo2Head == u16_rxFifo2Tail)
595  doHeartbeat();
596  u16_rxFifo2Tail++;
597  if (u16_rxFifo2Tail == UART2_RX_FIFO_SIZE) u16_rxFifo2Tail=0; //wrap
598  return au8_rxFifo2[u16_rxFifo2Tail]; //return the character
599 }
600 
601 void _ISR _U2RXInterrupt (void) {
602  int8_t u8_c;
603 
604  _U2RXIF = 0; //clear the UART RX interrupt bit
605  checkRxErrorUART2();
606  u8_c = U2RXREG; //read character
607  u16_rxFifo2Head++; //increment head pointer
608  if (u16_rxFifo2Head == UART2_RX_FIFO_SIZE)
609  u16_rxFifo2Head = 0; //wrap if needed
610  if (u16_rxFifo2Head == u16_rxFifo2Tail) {
611  //FIFO overrun!, report error
612  reportError("UART2 RX Interrupt FIFO overrun!");
613  }
614  au8_rxFifo2[u16_rxFifo2Head] = u8_c; //place in buffer
615 }
616 
617 #else
618 /**
619 * Return true if character is ready to be read
620 */
621 uint8_t isCharReady2(void) {
622  return(IS_CHAR_READY_UART2());
623 }
624 
625 /**
626 * Wait for a byte to be available from UART2 RX.
627 * \return Character read from UART2 RX.
628 */
629 uint8_t inChar2(void) {
630  //do heartbeat while waiting for character.
631  // Use a do-while to insure error checks
632  // are always run.
633  while (!IS_CHAR_READY_UART2())
634  doHeartbeat();
635  checkRxErrorUART2();
636  return U2RXREG; //read the receive register
637 }
638 #endif
639 
640 
641 
642 /** Chose a default BRGH for UART2, used by
643  * \ref configUART2 to set up UART2.
644  */
645 #ifndef DEFAULT_BRGH2
646 #define DEFAULT_BRGH2 DEFAULT_BRGH
647 #endif
648 
649 #if (DEFAULT_BRGH2 != 0) && (DEFAULT_BRGH2 != 1)
650 #error Invalid value specified for DEFAULT_BRGH2
651 #endif
652 
653 
654 /** Configure the UART. Settings chosen:
655  * - TX is on RP11
656  * - RX is on RP10
657  * - Format is 8 data bits, no parity, 1 stop bit
658  * - CTS, RTS, and BCLK not used
659  *
660  * \param u32_baudRate The baud rate to use.
661  */
662 void configUART2(uint32_t u32_baudRate) {
663 #ifdef _NOFLOAT
664  uint32_t u32_brg;
665 #else
666  float f_brg;
667 #endif
668 
669  /************************* UART config ********************/
670  // See comments in the #warning statements below for
671  // instructions on how to modify this configuration.
672  // More information on each of these board is given
673  // in the HARDWARE_PLATFORM section of pic24_libconfig.h.
674 #if (HARDWARE_PLATFORM == EXPLORER16_100P)
675  // There's nothing to do, since pins on these boards are
676  // mapped to fixed ports.
677 #elif (2 == 1)
678  // The following pin mappings will apply only to UART 1.
679  // Change them as necessary for your device.
680  #if (HARDWARE_PLATFORM == DANGEROUS_WEB)
681  CONFIG_RP14_AS_DIG_PIN(); // RX RP pin must be digital
682  CONFIG_U1RX_TO_RP(14); // U1RX <- RP14
683  CONFIG_RP15_AS_DIG_PIN(); // TX RP pin must be digital
684  CONFIG_U1TX_TO_RP(15); // U1TX -> RP15
685  CONFIG_RP10_AS_DIG_PIN(); // RX RP pin must be digital
686  // turn off any analog functionality on these pins
687  // (may be needed if pin is hardmapped and RPx does
688  // not exist)
689  DISABLE_U1TX_ANALOG();
690  DISABLE_U1RX_ANALOG();
691  #elif (HARDWARE_PLATFORM == STARTER_BOARD_28P)
692  CONFIG_RP9_AS_DIG_PIN(); // RX RP pin must be digital
693  CONFIG_U1RX_TO_RP(9); // U1RX <- RP9
694  CONFIG_RP8_AS_DIG_PIN(); // TX RP pin must be digital
695  CONFIG_U1TX_TO_RP(8); // U1TX -> RP8
696  // turn off any analog functionality on these pins
697  // (may be needed if pin is hardmapped and RPx does
698  // not exist)
699  DISABLE_U1TX_ANALOG();
700  DISABLE_U1RX_ANALOG();
701  #elif (HARDWARE_PLATFORM == DEFAULT_DESIGN)
702  #if ( defined(__PIC24E__) || defined(__dsPIC33E__))
703  CONFIG_U2RX_TO_RP(42); //U2RX <- RP42
704  CONFIG_RP43_AS_DIG_PIN(); //TX RP pin must be digital
705  CONFIG_U2TX_TO_RP(43); //U2TX -> RP43
706  #else
707  CONFIG_U2RX_TO_RP(10); //U2RX <- RP10
708  CONFIG_RP11_AS_DIG_PIN(); //TX RP pin must be digital
709  CONFIG_U2TX_TO_RP(11); //U2TX -> RP11
710  #endif
711  // turn off any analog functionality on these pins
712  // (may be needed if pin is hardmapped and RPx does
713  // not exist)
714  DISABLE_U1TX_ANALOG();
715  DISABLE_U1RX_ANALOG();
716  #else
717  #error Unknown hardware platform.
718  #endif
719 #else
720  #warning UART2 pin mappings not defined. See comments below for more info.
721  // If your device has more than one UART, ****** CHANGE THE MAPPING ******
722  // since multiple UARTs can not share the same pins. In particular:
723  // 1. Change the statement #if (2 == 1) to #if 1
724  // 2. Change the pin numbers above
725  // to something valid for your device.
726  // If your device does not have remappable I/O,
727  // (typical for >44 pin packages), skip this step --
728  // the UART I/O pins are already assigned to something
729  // valid.
730 #endif
731 
732  // First, disable the UART, clearing all errors, terminating
733  // any in-progress transmissions/receptions, etc.
734  // In particular, this clears UTXEN.
735  U2MODE = (0u << 15); // UARTEN = 0 to disable.
736 
737  /* Configure UART baud rate, based on \ref FCY.
738  * NOTE: Be careful about using BRGH=1 - this uses only four clock
739  * periods to sample each bit and can be very intolerant of
740  * baud rate % error - you may see framing errors. BRGH is selected
741  * via the DEFAULT_BRGH1 define above.
742  */
743 #ifdef _NOFLOAT
744  u32_brg = FCY/u32_baudRate;
745 #if (DEFAULT_BRGH2 == 0)
746  if ((u32_brg & 0x0FL) >= 8) u32_brg = u32_brg/16;
747  else u32_brg = u32_brg/16 - 1;
748 #else
749  if ((brg & 0x03L) >= 2) u32_brg = u32_brg/4;
750  else u32_brg = u32_brg/4 - 1;
751 #endif
752  ASSERT(u32_brg < 65536);
753  U2BRG = u32_brg;
754 #else
755 #if (DEFAULT_BRGH2 == 0)
756  f_brg = (((float) FCY)/((float) u32_baudRate)/16.0) - 1.0;
757 #else
758  f_brg = (((float) FCY)/((float) u32_baudRate)/4.0) - 1.0;
759 #endif
760  ASSERT(f_brg < 65535.5);
761  U2BRG = roundFloatToUint16(f_brg);
762 #endif
763 
764  // Set up the UART mode register
765  U2MODE =
766  (1u << 15) | // UARTEN = 1 (enable the UART)
767  (0u << 13) | // USIDL = 0 (continue operation in idle mode)
768  (0u << 12) | // IREN = 0 (IrDA encoder and decoder disabled)
769  (0u << 11) | // RTSMD = 0 (UxRTS# in flow control mode. Given
770  // the UEN setting below, this doesn't matter.)
771  (0b00 << 8) | // UEN = 00 (UxTX and UxRx pins are enabled and used;
772  // used; UxCTS, UxRTS, and BCLKx pins are
773  // controlled by port latches)
774  (0u << 7) | // WAKE = 0 (Wake-up on start bit detect during
775  // sleep mode disabled)
776  (0u << 6) | // LPBACK = 0 (UARTx loopback mode is disabled)
777  (0u << 5) | // ABAUD = 0 (Auto-baud disabled)
778  (0u << 4) | // URXINV = 0 (Receve polarity inversion bit:
779  // UxRX idle state is 1)
780  (DEFAULT_BRGH2 << 3) | // BRGH (High/low baud rate select bit:
781  // 1 = high speed, 0 = low speed)
782  (0b00 << 1) | // PDSEL = 00 (8-bit data, no parity)
783  (0u << 0); // STSEL = 0 (1 stop bit)
784 
785  // Set up the UART status and control register
786  U2STA =
787  (0u << 15) | // UTXISEL1 = 0 (See bit 13 below for explanation)
788  (0u << 14) | // UTXINV = 0 (UxTX idle state is 1 (though docs
789  // say 0))
790  (0u << 13) | // UTXISEL0 = 0 (With bit 15 above, UTXISEL = 00:
791  // Interrupt generated when any character
792  // is transferred to the Transmit Shift Register).
793  (0u << 11) | // UTXBRK = 0 (Sync break transmission disabled)
794  (1u << 10) | // UTXEN = 0 (UARTx transmitter enabled. NOTE: per
795  // the data sheet, this must be set *AFTER* UARTEN
796  // is set to 1 (see UxMODE assignment above).
797  (0b00 << 6) | // URXISEL = 00 (Interrupt flag bit is set when a
798  // character is received)
799  (0u << 5) | // ADDEN = 0 (Address detect mode disabled)
800  (0u << 1); // OERR = 0 (Clear any overrun errors)
801 
802  // Delay 1 ms (at least one bit time) before beginning transmission,
803  // since the UxTX pin is initially configured as an input on device
804  // reset. It needs to be high for at least one bit time before
805  // a character is sent in order for the start bit to be recognized.
806  // See 24H FRM Sec. 17.5 for more details.
807  ASSERT(u32_baudRate >= 1000L);
808  // Note: If the baud rate is less than 1000, this delay
809  // isn't long encough. The alternative is to use floating-point
810  // math to compute the correct delay, which seems worse than the
811  // problem.
812  DELAY_MS(1);
813 
814  // Clear any errors
815  U2STAbits.OERR = 0;
816  while (U2STAbits.PERR || U2STAbits.FERR) {
817  U2RXREG; //clear errors by reading RXREG
818  }
819 
820  // Set up interrupts if requested
821 #ifdef UART2_RX_INTERRUPT
822  _U2RXIF = 0; //clear the flag
823  _U2RXIP = UART2_RX_INTERRUPT_PRIORITY; //choose a priority
824  _U2RXIE = 1; //enable the interrupt
825 #endif
826 #ifdef UART2_TX_INTERRUPT
827  //do not clear the U2TXIF flag!
828  _U2TXIP = UART2_TX_INTERRUPT_PRIORITY; //choose a priority
829  //do not enable the interrupt until we try to write to the UART
830 #endif
831 
832 }
833 
834 #endif // #if (NUM_UARTS >= 2)
835 
836 
837 
838 
839 /*
840  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
841  * All rights reserved.
842  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
843  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
844  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
845  *
846  * Permission to use, copy, modify, and distribute this software and its
847  * documentation for any purpose, without fee, and without written agreement is
848  * hereby granted, provided that the above copyright notice, the following
849  * two paragraphs and the authors appear in all copies of this software.
850  *
851  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
852  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
853  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
854  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
855  *
856  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
857  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
858  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
859  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
860  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
861  *
862  * Please maintain this header in its entirety when copying/modifying
863  * these files.
864  *
865  *
866  */
867 
868 
869 
870 
871 #include "pic24_clockfreq.h"
872 #include "pic24_uart.h"
873 #include "pic24_ports.h"
874 #include "pic24_unittest.h"
875 #include "pic24_delay.h"
876 
877 // Only include if this UART exists.
878 #if (NUM_UART_MODS >= 3)
879 
880 
881 // Documentation for this file. If the \file tag is not present,
882 // this file will not be documented.
883 // Note: place this comment below the #if NUM_UART_MODS so Doxygen
884 // will only see it once.
885 /** \file
886 * UART support functions.
887 * \par Interrupt-driven TX/RX
888 * By default, the UART functions use polling for both RX and TX.
889 * Define the macro UARTx_TX_INTERRUPT (i.e., UART1_TX_INTERRUPT) in your project file if you want interrupt-driven TX for the UARTx (i.e., UART1) module.
890 * For interrupt-driven TX, macro UARTx_TX_FIFO_SIZE sets the TX software FIFO size (default 32), and UARTx_TX_INTERRUPT_PRIORITY sets the priority (default 1).
891 * \par
892 * Define the macro UARTx_RX_INTERRUPT (i.e., UART1_RX_INTERRUPT) in your project file if you want interrupt-driven RX for the UARTx (i.e., UART1) module.
893 * For interrupt-driven RX, macro UARTx_RX_FIFO_SIZE sets the RX software FIFO size (default 32), and UARTx_RX_INTERRUPT_PRIORITY sets the priority (default 1).
894 */
895 
896 
897 /*********************************************************
898  * Public functions intended to be called by other files *
899  *********************************************************/
900 /**
901 * Check UART3 RX for error, call \em reportError() if error found.
902 *
903 */
904 void checkRxErrorUART3(void) {
905  uint8_t u8_c;
906  //check for errors, reset if detected.
907  if (U3STAbits.PERR) {
908  u8_c = U3RXREG; //clear error
909  reportError("UART3 parity error\n");
910  }
911  if (U3STAbits.FERR) {
912  u8_c = U3RXREG; //clear error
913  reportError("UART3 framing error\n");
914  }
915  if (U3STAbits.OERR) {
916  U3STAbits.OERR = 0; //clear error
917  reportError("UART3 overrun error\n");
918  }
919 }
920 
921 
922 
923 
924 #ifdef UART3_TX_INTERRUPT
925 /**
926 
927 */
928 #ifndef UART3_TX_FIFO_SIZE
929 #define UART3_TX_FIFO_SIZE 32 //choose a size
930 #endif
931 
932 #ifndef UART3_TX_INTERRUPT_PRIORITY
933 #define UART3_TX_INTERRUPT_PRIORITY 1
934 #endif
935 
936 volatile uint8_t au8_txFifo3[UART3_TX_FIFO_SIZE];
937 volatile uint16_t u16_txFifo3Head = 0;
938 volatile uint16_t u16_txFifo3Tail = 0;
939 
940 /**
941 * Output \em u8_c to UART3 TX.
942 * \param u8_c Character to write
943 */
944 void outChar3(uint8_t u8_c) {
945  uint16_t u16_tmp;
946 
947  u16_tmp = u16_txFifo3Head;
948  u16_tmp++;
949  if (u16_tmp == UART3_TX_FIFO_SIZE) u16_tmp = 0; //wrap if needed
950  while (u16_tmp == u16_txFifo3Tail)
951  doHeartbeat();
952 
953  au8_txFifo3[u16_tmp] = u8_c; //write to buffer
954  u16_txFifo3Head = u16_tmp; //update head
955  _U3TXIE = 1; //enable interrupt
956 }
957 
958 void _ISR _U3TXInterrupt (void) {
959  if (u16_txFifo3Head == u16_txFifo3Tail) {
960  //empty TX buffer, disable the interrupt, do not clear the flag
961  _U3TXIE = 0;
962  } else {
963  //at least one free spot in the TX buffer!
964  u16_txFifo3Tail++; //increment tail pointer
965  if (u16_txFifo3Tail == UART3_TX_FIFO_SIZE)
966  u16_txFifo3Tail = 0; //wrap if needed
967  _U3TXIF = 0; //clear the interrupt flag
968  //transfer character from software buffer to transmit buffer
969  U3TXREG = au8_txFifo3[u16_txFifo3Tail];
970  }
971 }
972 
973 
974 #else
975 /**
976 * Output \em u8_c to UART3 TX.
977 * \param u8_c Character to write
978 */
979 void outChar3(uint8_t u8_c) {
980  //wait for transmit buffer to be empty
981  while (IS_TRANSMIT_BUFFER_FULL_UART3())
982  doHeartbeat();
983  U3TXREG = u8_c;
984 }
985 #endif
986 
987 #ifdef UART3_RX_INTERRUPT
988 //Interrupt driven RX
989 #ifndef UART3_RX_FIFO_SIZE
990 #define UART3_RX_FIFO_SIZE 32 //choose a size
991 #endif
992 
993 #ifndef UART3_RX_INTERRUPT_PRIORITY
994 #define UART3_RX_INTERRUPT_PRIORITY 1
995 #endif
996 
997 volatile uint8_t au8_rxFifo3[UART3_RX_FIFO_SIZE];
998 volatile uint16_t u16_rxFifo3Head = 0;
999 volatile uint16_t u16_rxFifo3Tail = 0;
1000 
1001 /**
1002 * Return true if character is ready to be read
1003 */
1004 uint8_t isCharReady3(void) {
1005  return(u16_rxFifo3Head != u16_rxFifo3Tail);
1006 }
1007 
1008 /**
1009 * Wait for a byte to be available from UART3 RX.
1010 * \return Character read from UART3 RX.
1011 */
1012 uint8_t inChar3(void) {
1013  while (u16_rxFifo3Head == u16_rxFifo3Tail)
1014  doHeartbeat();
1015  u16_rxFifo3Tail++;
1016  if (u16_rxFifo3Tail == UART3_RX_FIFO_SIZE) u16_rxFifo3Tail=0; //wrap
1017  return au8_rxFifo3[u16_rxFifo3Tail]; //return the character
1018 }
1019 
1020 void _ISR _U3RXInterrupt (void) {
1021  int8_t u8_c;
1022 
1023  _U3RXIF = 0; //clear the UART RX interrupt bit
1024  checkRxErrorUART3();
1025  u8_c = U3RXREG; //read character
1026  u16_rxFifo3Head++; //increment head pointer
1027  if (u16_rxFifo3Head == UART3_RX_FIFO_SIZE)
1028  u16_rxFifo3Head = 0; //wrap if needed
1029  if (u16_rxFifo3Head == u16_rxFifo3Tail) {
1030  //FIFO overrun!, report error
1031  reportError("UART3 RX Interrupt FIFO overrun!");
1032  }
1033  au8_rxFifo3[u16_rxFifo3Head] = u8_c; //place in buffer
1034 }
1035 
1036 #else
1037 /**
1038 * Return true if character is ready to be read
1039 */
1040 uint8_t isCharReady3(void) {
1041  return(IS_CHAR_READY_UART3());
1042 }
1043 
1044 /**
1045 * Wait for a byte to be available from UART3 RX.
1046 * \return Character read from UART3 RX.
1047 */
1048 uint8_t inChar3(void) {
1049  //do heartbeat while waiting for character.
1050  // Use a do-while to insure error checks
1051  // are always run.
1052  while (!IS_CHAR_READY_UART3())
1053  doHeartbeat();
1054  checkRxErrorUART3();
1055  return U3RXREG; //read the receive register
1056 }
1057 #endif
1058 
1059 
1060 
1061 /** Chose a default BRGH for UART3, used by
1062  * \ref configUART3 to set up UART3.
1063  */
1064 #ifndef DEFAULT_BRGH3
1065 #define DEFAULT_BRGH3 DEFAULT_BRGH
1066 #endif
1067 
1068 #if (DEFAULT_BRGH3 != 0) && (DEFAULT_BRGH3 != 1)
1069 #error Invalid value specified for DEFAULT_BRGH3
1070 #endif
1071 
1072 
1073 /** Configure the UART. Settings chosen:
1074  * - TX is on RP11
1075  * - RX is on RP10
1076  * - Format is 8 data bits, no parity, 1 stop bit
1077  * - CTS, RTS, and BCLK not used
1078  *
1079  * \param u32_baudRate The baud rate to use.
1080  */
1081 void configUART3(uint32_t u32_baudRate) {
1082 #ifdef _NOFLOAT
1083  uint32_t u32_brg;
1084 #else
1085  float f_brg;
1086 #endif
1087 
1088  /************************* UART config ********************/
1089  // See comments in the #warning statements below for
1090  // instructions on how to modify this configuration.
1091  // More information on each of these board is given
1092  // in the HARDWARE_PLATFORM section of pic24_libconfig.h.
1093 #if (HARDWARE_PLATFORM == EXPLORER16_100P)
1094  // There's nothing to do, since pins on these boards are
1095  // mapped to fixed ports.
1096 #elif (3 == 1)
1097  // The following pin mappings will apply only to UART 1.
1098  // Change them as necessary for your device.
1099  #if (HARDWARE_PLATFORM == DANGEROUS_WEB)
1100  CONFIG_RP14_AS_DIG_PIN(); // RX RP pin must be digital
1101  CONFIG_U1RX_TO_RP(14); // U1RX <- RP14
1102  CONFIG_RP15_AS_DIG_PIN(); // TX RP pin must be digital
1103  CONFIG_U1TX_TO_RP(15); // U1TX -> RP15
1104  CONFIG_RP10_AS_DIG_PIN(); // RX RP pin must be digital
1105  // turn off any analog functionality on these pins
1106  // (may be needed if pin is hardmapped and RPx does
1107  // not exist)
1108  DISABLE_U1TX_ANALOG();
1109  DISABLE_U1RX_ANALOG();
1110  #elif (HARDWARE_PLATFORM == STARTER_BOARD_28P)
1111  CONFIG_RP9_AS_DIG_PIN(); // RX RP pin must be digital
1112  CONFIG_U1RX_TO_RP(9); // U1RX <- RP9
1113  CONFIG_RP8_AS_DIG_PIN(); // TX RP pin must be digital
1114  CONFIG_U1TX_TO_RP(8); // U1TX -> RP8
1115  // turn off any analog functionality on these pins
1116  // (may be needed if pin is hardmapped and RPx does
1117  // not exist)
1118  DISABLE_U1TX_ANALOG();
1119  DISABLE_U1RX_ANALOG();
1120  #elif (HARDWARE_PLATFORM == DEFAULT_DESIGN)
1121  #if ( defined(__PIC24E__) || defined(__dsPIC33E__))
1122  CONFIG_U3RX_TO_RP(42); //U3RX <- RP42
1123  CONFIG_RP43_AS_DIG_PIN(); //TX RP pin must be digital
1124  CONFIG_U3TX_TO_RP(43); //U3TX -> RP43
1125  #else
1126  CONFIG_U3RX_TO_RP(10); //U3RX <- RP10
1127  CONFIG_RP11_AS_DIG_PIN(); //TX RP pin must be digital
1128  CONFIG_U3TX_TO_RP(11); //U3TX -> RP11
1129  #endif
1130  // turn off any analog functionality on these pins
1131  // (may be needed if pin is hardmapped and RPx does
1132  // not exist)
1133  DISABLE_U1TX_ANALOG();
1134  DISABLE_U1RX_ANALOG();
1135  #else
1136  #error Unknown hardware platform.
1137  #endif
1138 #else
1139  #warning UART3 pin mappings not defined. See comments below for more info.
1140  // If your device has more than one UART, ****** CHANGE THE MAPPING ******
1141  // since multiple UARTs can not share the same pins. In particular:
1142  // 1. Change the statement #if (3 == 1) to #if 1
1143  // 2. Change the pin numbers above
1144  // to something valid for your device.
1145  // If your device does not have remappable I/O,
1146  // (typical for >44 pin packages), skip this step --
1147  // the UART I/O pins are already assigned to something
1148  // valid.
1149 #endif
1150 
1151  // First, disable the UART, clearing all errors, terminating
1152  // any in-progress transmissions/receptions, etc.
1153  // In particular, this clears UTXEN.
1154  U3MODE = (0u << 15); // UARTEN = 0 to disable.
1155 
1156  /* Configure UART baud rate, based on \ref FCY.
1157  * NOTE: Be careful about using BRGH=1 - this uses only four clock
1158  * periods to sample each bit and can be very intolerant of
1159  * baud rate % error - you may see framing errors. BRGH is selected
1160  * via the DEFAULT_BRGH1 define above.
1161  */
1162 #ifdef _NOFLOAT
1163  u32_brg = FCY/u32_baudRate;
1164 #if (DEFAULT_BRGH3 == 0)
1165  if ((u32_brg & 0x0FL) >= 8) u32_brg = u32_brg/16;
1166  else u32_brg = u32_brg/16 - 1;
1167 #else
1168  if ((brg & 0x03L) >= 2) u32_brg = u32_brg/4;
1169  else u32_brg = u32_brg/4 - 1;
1170 #endif
1171  ASSERT(u32_brg < 65536);
1172  U3BRG = u32_brg;
1173 #else
1174 #if (DEFAULT_BRGH3 == 0)
1175  f_brg = (((float) FCY)/((float) u32_baudRate)/16.0) - 1.0;
1176 #else
1177  f_brg = (((float) FCY)/((float) u32_baudRate)/4.0) - 1.0;
1178 #endif
1179  ASSERT(f_brg < 65535.5);
1180  U3BRG = roundFloatToUint16(f_brg);
1181 #endif
1182 
1183  // Set up the UART mode register
1184  U3MODE =
1185  (1u << 15) | // UARTEN = 1 (enable the UART)
1186  (0u << 13) | // USIDL = 0 (continue operation in idle mode)
1187  (0u << 12) | // IREN = 0 (IrDA encoder and decoder disabled)
1188  (0u << 11) | // RTSMD = 0 (UxRTS# in flow control mode. Given
1189  // the UEN setting below, this doesn't matter.)
1190  (0b00 << 8) | // UEN = 00 (UxTX and UxRx pins are enabled and used;
1191  // used; UxCTS, UxRTS, and BCLKx pins are
1192  // controlled by port latches)
1193  (0u << 7) | // WAKE = 0 (Wake-up on start bit detect during
1194  // sleep mode disabled)
1195  (0u << 6) | // LPBACK = 0 (UARTx loopback mode is disabled)
1196  (0u << 5) | // ABAUD = 0 (Auto-baud disabled)
1197  (0u << 4) | // URXINV = 0 (Receve polarity inversion bit:
1198  // UxRX idle state is 1)
1199  (DEFAULT_BRGH3 << 3) | // BRGH (High/low baud rate select bit:
1200  // 1 = high speed, 0 = low speed)
1201  (0b00 << 1) | // PDSEL = 00 (8-bit data, no parity)
1202  (0u << 0); // STSEL = 0 (1 stop bit)
1203 
1204  // Set up the UART status and control register
1205  U3STA =
1206  (0u << 15) | // UTXISEL1 = 0 (See bit 13 below for explanation)
1207  (0u << 14) | // UTXINV = 0 (UxTX idle state is 1 (though docs
1208  // say 0))
1209  (0u << 13) | // UTXISEL0 = 0 (With bit 15 above, UTXISEL = 00:
1210  // Interrupt generated when any character
1211  // is transferred to the Transmit Shift Register).
1212  (0u << 11) | // UTXBRK = 0 (Sync break transmission disabled)
1213  (1u << 10) | // UTXEN = 0 (UARTx transmitter enabled. NOTE: per
1214  // the data sheet, this must be set *AFTER* UARTEN
1215  // is set to 1 (see UxMODE assignment above).
1216  (0b00 << 6) | // URXISEL = 00 (Interrupt flag bit is set when a
1217  // character is received)
1218  (0u << 5) | // ADDEN = 0 (Address detect mode disabled)
1219  (0u << 1); // OERR = 0 (Clear any overrun errors)
1220 
1221  // Delay 1 ms (at least one bit time) before beginning transmission,
1222  // since the UxTX pin is initially configured as an input on device
1223  // reset. It needs to be high for at least one bit time before
1224  // a character is sent in order for the start bit to be recognized.
1225  // See 24H FRM Sec. 17.5 for more details.
1226  ASSERT(u32_baudRate >= 1000L);
1227  // Note: If the baud rate is less than 1000, this delay
1228  // isn't long encough. The alternative is to use floating-point
1229  // math to compute the correct delay, which seems worse than the
1230  // problem.
1231  DELAY_MS(1);
1232 
1233  // Clear any errors
1234  U3STAbits.OERR = 0;
1235  while (U3STAbits.PERR || U3STAbits.FERR) {
1236  U3RXREG; //clear errors by reading RXREG
1237  }
1238 
1239  // Set up interrupts if requested
1240 #ifdef UART3_RX_INTERRUPT
1241  _U3RXIF = 0; //clear the flag
1242  _U3RXIP = UART3_RX_INTERRUPT_PRIORITY; //choose a priority
1243  _U3RXIE = 1; //enable the interrupt
1244 #endif
1245 #ifdef UART3_TX_INTERRUPT
1246  //do not clear the U3TXIF flag!
1247  _U3TXIP = UART3_TX_INTERRUPT_PRIORITY; //choose a priority
1248  //do not enable the interrupt until we try to write to the UART
1249 #endif
1250 
1251 }
1252 
1253 #endif // #if (NUM_UARTS >= 3)
1254 
1255 
1256 
1257 
1258 /*
1259  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
1260  * All rights reserved.
1261  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
1262  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
1263  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
1264  *
1265  * Permission to use, copy, modify, and distribute this software and its
1266  * documentation for any purpose, without fee, and without written agreement is
1267  * hereby granted, provided that the above copyright notice, the following
1268  * two paragraphs and the authors appear in all copies of this software.
1269  *
1270  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
1271  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
1272  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
1273  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1274  *
1275  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
1276  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1277  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
1278  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
1279  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
1280  *
1281  * Please maintain this header in its entirety when copying/modifying
1282  * these files.
1283  *
1284  *
1285  */
1286 
1287 
1288 
1289 
1290 #include "pic24_clockfreq.h"
1291 #include "pic24_uart.h"
1292 #include "pic24_ports.h"
1293 #include "pic24_unittest.h"
1294 #include "pic24_delay.h"
1295 
1296 // Only include if this UART exists.
1297 #if (NUM_UART_MODS >= 4)
1298 
1299 
1300 // Documentation for this file. If the \file tag is not present,
1301 // this file will not be documented.
1302 // Note: place this comment below the #if NUM_UART_MODS so Doxygen
1303 // will only see it once.
1304 /** \file
1305 * UART support functions.
1306 * \par Interrupt-driven TX/RX
1307 * By default, the UART functions use polling for both RX and TX.
1308 * Define the macro UARTx_TX_INTERRUPT (i.e., UART1_TX_INTERRUPT) in your project file if you want interrupt-driven TX for the UARTx (i.e., UART1) module.
1309 * For interrupt-driven TX, macro UARTx_TX_FIFO_SIZE sets the TX software FIFO size (default 32), and UARTx_TX_INTERRUPT_PRIORITY sets the priority (default 1).
1310 * \par
1311 * Define the macro UARTx_RX_INTERRUPT (i.e., UART1_RX_INTERRUPT) in your project file if you want interrupt-driven RX for the UARTx (i.e., UART1) module.
1312 * For interrupt-driven RX, macro UARTx_RX_FIFO_SIZE sets the RX software FIFO size (default 32), and UARTx_RX_INTERRUPT_PRIORITY sets the priority (default 1).
1313 */
1314 
1315 
1316 /*********************************************************
1317  * Public functions intended to be called by other files *
1318  *********************************************************/
1319 /**
1320 * Check UART4 RX for error, call \em reportError() if error found.
1321 *
1322 */
1323 void checkRxErrorUART4(void) {
1324  uint8_t u8_c;
1325  //check for errors, reset if detected.
1326  if (U4STAbits.PERR) {
1327  u8_c = U4RXREG; //clear error
1328  reportError("UART4 parity error\n");
1329  }
1330  if (U4STAbits.FERR) {
1331  u8_c = U4RXREG; //clear error
1332  reportError("UART4 framing error\n");
1333  }
1334  if (U4STAbits.OERR) {
1335  U4STAbits.OERR = 0; //clear error
1336  reportError("UART4 overrun error\n");
1337  }
1338 }
1339 
1340 
1341 
1342 
1343 #ifdef UART4_TX_INTERRUPT
1344 /**
1345 
1346 */
1347 #ifndef UART4_TX_FIFO_SIZE
1348 #define UART4_TX_FIFO_SIZE 32 //choose a size
1349 #endif
1350 
1351 #ifndef UART4_TX_INTERRUPT_PRIORITY
1352 #define UART4_TX_INTERRUPT_PRIORITY 1
1353 #endif
1354 
1355 volatile uint8_t au8_txFifo4[UART4_TX_FIFO_SIZE];
1356 volatile uint16_t u16_txFifo4Head = 0;
1357 volatile uint16_t u16_txFifo4Tail = 0;
1358 
1359 /**
1360 * Output \em u8_c to UART4 TX.
1361 * \param u8_c Character to write
1362 */
1363 void outChar4(uint8_t u8_c) {
1364  uint16_t u16_tmp;
1365 
1366  u16_tmp = u16_txFifo4Head;
1367  u16_tmp++;
1368  if (u16_tmp == UART4_TX_FIFO_SIZE) u16_tmp = 0; //wrap if needed
1369  while (u16_tmp == u16_txFifo4Tail)
1370  doHeartbeat();
1371 
1372  au8_txFifo4[u16_tmp] = u8_c; //write to buffer
1373  u16_txFifo4Head = u16_tmp; //update head
1374  _U4TXIE = 1; //enable interrupt
1375 }
1376 
1377 void _ISR _U4TXInterrupt (void) {
1378  if (u16_txFifo4Head == u16_txFifo4Tail) {
1379  //empty TX buffer, disable the interrupt, do not clear the flag
1380  _U4TXIE = 0;
1381  } else {
1382  //at least one free spot in the TX buffer!
1383  u16_txFifo4Tail++; //increment tail pointer
1384  if (u16_txFifo4Tail == UART4_TX_FIFO_SIZE)
1385  u16_txFifo4Tail = 0; //wrap if needed
1386  _U4TXIF = 0; //clear the interrupt flag
1387  //transfer character from software buffer to transmit buffer
1388  U4TXREG = au8_txFifo4[u16_txFifo4Tail];
1389  }
1390 }
1391 
1392 
1393 #else
1394 /**
1395 * Output \em u8_c to UART4 TX.
1396 * \param u8_c Character to write
1397 */
1398 void outChar4(uint8_t u8_c) {
1399  //wait for transmit buffer to be empty
1400  while (IS_TRANSMIT_BUFFER_FULL_UART4())
1401  doHeartbeat();
1402  U4TXREG = u8_c;
1403 }
1404 #endif
1405 
1406 #ifdef UART4_RX_INTERRUPT
1407 //Interrupt driven RX
1408 #ifndef UART4_RX_FIFO_SIZE
1409 #define UART4_RX_FIFO_SIZE 32 //choose a size
1410 #endif
1411 
1412 #ifndef UART4_RX_INTERRUPT_PRIORITY
1413 #define UART4_RX_INTERRUPT_PRIORITY 1
1414 #endif
1415 
1416 volatile uint8_t au8_rxFifo4[UART4_RX_FIFO_SIZE];
1417 volatile uint16_t u16_rxFifo4Head = 0;
1418 volatile uint16_t u16_rxFifo4Tail = 0;
1419 
1420 /**
1421 * Return true if character is ready to be read
1422 */
1423 uint8_t isCharReady4(void) {
1424  return(u16_rxFifo4Head != u16_rxFifo4Tail);
1425 }
1426 
1427 /**
1428 * Wait for a byte to be available from UART4 RX.
1429 * \return Character read from UART4 RX.
1430 */
1431 uint8_t inChar4(void) {
1432  while (u16_rxFifo4Head == u16_rxFifo4Tail)
1433  doHeartbeat();
1434  u16_rxFifo4Tail++;
1435  if (u16_rxFifo4Tail == UART4_RX_FIFO_SIZE) u16_rxFifo4Tail=0; //wrap
1436  return au8_rxFifo4[u16_rxFifo4Tail]; //return the character
1437 }
1438 
1439 void _ISR _U4RXInterrupt (void) {
1440  int8_t u8_c;
1441 
1442  _U4RXIF = 0; //clear the UART RX interrupt bit
1443  checkRxErrorUART4();
1444  u8_c = U4RXREG; //read character
1445  u16_rxFifo4Head++; //increment head pointer
1446  if (u16_rxFifo4Head == UART4_RX_FIFO_SIZE)
1447  u16_rxFifo4Head = 0; //wrap if needed
1448  if (u16_rxFifo4Head == u16_rxFifo4Tail) {
1449  //FIFO overrun!, report error
1450  reportError("UART4 RX Interrupt FIFO overrun!");
1451  }
1452  au8_rxFifo4[u16_rxFifo4Head] = u8_c; //place in buffer
1453 }
1454 
1455 #else
1456 /**
1457 * Return true if character is ready to be read
1458 */
1459 uint8_t isCharReady4(void) {
1460  return(IS_CHAR_READY_UART4());
1461 }
1462 
1463 /**
1464 * Wait for a byte to be available from UART4 RX.
1465 * \return Character read from UART4 RX.
1466 */
1467 uint8_t inChar4(void) {
1468  //do heartbeat while waiting for character.
1469  // Use a do-while to insure error checks
1470  // are always run.
1471  while (!IS_CHAR_READY_UART4())
1472  doHeartbeat();
1473  checkRxErrorUART4();
1474  return U4RXREG; //read the receive register
1475 }
1476 #endif
1477 
1478 
1479 
1480 /** Chose a default BRGH for UART4, used by
1481  * \ref configUART4 to set up UART4.
1482  */
1483 #ifndef DEFAULT_BRGH4
1484 #define DEFAULT_BRGH4 DEFAULT_BRGH
1485 #endif
1486 
1487 #if (DEFAULT_BRGH4 != 0) && (DEFAULT_BRGH4 != 1)
1488 #error Invalid value specified for DEFAULT_BRGH4
1489 #endif
1490 
1491 
1492 /** Configure the UART. Settings chosen:
1493  * - TX is on RP11
1494  * - RX is on RP10
1495  * - Format is 8 data bits, no parity, 1 stop bit
1496  * - CTS, RTS, and BCLK not used
1497  *
1498  * \param u32_baudRate The baud rate to use.
1499  */
1500 void configUART4(uint32_t u32_baudRate) {
1501 #ifdef _NOFLOAT
1502  uint32_t u32_brg;
1503 #else
1504  float f_brg;
1505 #endif
1506 
1507  /************************* UART config ********************/
1508  // See comments in the #warning statements below for
1509  // instructions on how to modify this configuration.
1510  // More information on each of these board is given
1511  // in the HARDWARE_PLATFORM section of pic24_libconfig.h.
1512 #if (HARDWARE_PLATFORM == EXPLORER16_100P)
1513  // There's nothing to do, since pins on these boards are
1514  // mapped to fixed ports.
1515 #elif (4 == 1)
1516  // The following pin mappings will apply only to UART 1.
1517  // Change them as necessary for your device.
1518  #if (HARDWARE_PLATFORM == DANGEROUS_WEB)
1519  CONFIG_RP14_AS_DIG_PIN(); // RX RP pin must be digital
1520  CONFIG_U1RX_TO_RP(14); // U1RX <- RP14
1521  CONFIG_RP15_AS_DIG_PIN(); // TX RP pin must be digital
1522  CONFIG_U1TX_TO_RP(15); // U1TX -> RP15
1523  CONFIG_RP10_AS_DIG_PIN(); // RX RP pin must be digital
1524  // turn off any analog functionality on these pins
1525  // (may be needed if pin is hardmapped and RPx does
1526  // not exist)
1527  DISABLE_U1TX_ANALOG();
1528  DISABLE_U1RX_ANALOG();
1529  #elif (HARDWARE_PLATFORM == STARTER_BOARD_28P)
1530  CONFIG_RP9_AS_DIG_PIN(); // RX RP pin must be digital
1531  CONFIG_U1RX_TO_RP(9); // U1RX <- RP9
1532  CONFIG_RP8_AS_DIG_PIN(); // TX RP pin must be digital
1533  CONFIG_U1TX_TO_RP(8); // U1TX -> RP8
1534  // turn off any analog functionality on these pins
1535  // (may be needed if pin is hardmapped and RPx does
1536  // not exist)
1537  DISABLE_U1TX_ANALOG();
1538  DISABLE_U1RX_ANALOG();
1539  #elif (HARDWARE_PLATFORM == DEFAULT_DESIGN)
1540  #if ( defined(__PIC24E__) || defined(__dsPIC33E__))
1541  CONFIG_U4RX_TO_RP(42); //U4RX <- RP42
1542  CONFIG_RP43_AS_DIG_PIN(); //TX RP pin must be digital
1543  CONFIG_U4TX_TO_RP(43); //U4TX -> RP43
1544  #else
1545  CONFIG_U4RX_TO_RP(10); //U4RX <- RP10
1546  CONFIG_RP11_AS_DIG_PIN(); //TX RP pin must be digital
1547  CONFIG_U4TX_TO_RP(11); //U4TX -> RP11
1548  #endif
1549  // turn off any analog functionality on these pins
1550  // (may be needed if pin is hardmapped and RPx does
1551  // not exist)
1552  DISABLE_U1TX_ANALOG();
1553  DISABLE_U1RX_ANALOG();
1554  #else
1555  #error Unknown hardware platform.
1556  #endif
1557 #else
1558  #warning UART4 pin mappings not defined. See comments below for more info.
1559  // If your device has more than one UART, ****** CHANGE THE MAPPING ******
1560  // since multiple UARTs can not share the same pins. In particular:
1561  // 1. Change the statement #if (4 == 1) to #if 1
1562  // 2. Change the pin numbers above
1563  // to something valid for your device.
1564  // If your device does not have remappable I/O,
1565  // (typical for >44 pin packages), skip this step --
1566  // the UART I/O pins are already assigned to something
1567  // valid.
1568 #endif
1569 
1570  // First, disable the UART, clearing all errors, terminating
1571  // any in-progress transmissions/receptions, etc.
1572  // In particular, this clears UTXEN.
1573  U4MODE = (0u << 15); // UARTEN = 0 to disable.
1574 
1575  /* Configure UART baud rate, based on \ref FCY.
1576  * NOTE: Be careful about using BRGH=1 - this uses only four clock
1577  * periods to sample each bit and can be very intolerant of
1578  * baud rate % error - you may see framing errors. BRGH is selected
1579  * via the DEFAULT_BRGH1 define above.
1580  */
1581 #ifdef _NOFLOAT
1582  u32_brg = FCY/u32_baudRate;
1583 #if (DEFAULT_BRGH4 == 0)
1584  if ((u32_brg & 0x0FL) >= 8) u32_brg = u32_brg/16;
1585  else u32_brg = u32_brg/16 - 1;
1586 #else
1587  if ((brg & 0x03L) >= 2) u32_brg = u32_brg/4;
1588  else u32_brg = u32_brg/4 - 1;
1589 #endif
1590  ASSERT(u32_brg < 65536);
1591  U4BRG = u32_brg;
1592 #else
1593 #if (DEFAULT_BRGH4 == 0)
1594  f_brg = (((float) FCY)/((float) u32_baudRate)/16.0) - 1.0;
1595 #else
1596  f_brg = (((float) FCY)/((float) u32_baudRate)/4.0) - 1.0;
1597 #endif
1598  ASSERT(f_brg < 65535.5);
1599  U4BRG = roundFloatToUint16(f_brg);
1600 #endif
1601 
1602  // Set up the UART mode register
1603  U4MODE =
1604  (1u << 15) | // UARTEN = 1 (enable the UART)
1605  (0u << 13) | // USIDL = 0 (continue operation in idle mode)
1606  (0u << 12) | // IREN = 0 (IrDA encoder and decoder disabled)
1607  (0u << 11) | // RTSMD = 0 (UxRTS# in flow control mode. Given
1608  // the UEN setting below, this doesn't matter.)
1609  (0b00 << 8) | // UEN = 00 (UxTX and UxRx pins are enabled and used;
1610  // used; UxCTS, UxRTS, and BCLKx pins are
1611  // controlled by port latches)
1612  (0u << 7) | // WAKE = 0 (Wake-up on start bit detect during
1613  // sleep mode disabled)
1614  (0u << 6) | // LPBACK = 0 (UARTx loopback mode is disabled)
1615  (0u << 5) | // ABAUD = 0 (Auto-baud disabled)
1616  (0u << 4) | // URXINV = 0 (Receve polarity inversion bit:
1617  // UxRX idle state is 1)
1618  (DEFAULT_BRGH4 << 3) | // BRGH (High/low baud rate select bit:
1619  // 1 = high speed, 0 = low speed)
1620  (0b00 << 1) | // PDSEL = 00 (8-bit data, no parity)
1621  (0u << 0); // STSEL = 0 (1 stop bit)
1622 
1623  // Set up the UART status and control register
1624  U4STA =
1625  (0u << 15) | // UTXISEL1 = 0 (See bit 13 below for explanation)
1626  (0u << 14) | // UTXINV = 0 (UxTX idle state is 1 (though docs
1627  // say 0))
1628  (0u << 13) | // UTXISEL0 = 0 (With bit 15 above, UTXISEL = 00:
1629  // Interrupt generated when any character
1630  // is transferred to the Transmit Shift Register).
1631  (0u << 11) | // UTXBRK = 0 (Sync break transmission disabled)
1632  (1u << 10) | // UTXEN = 0 (UARTx transmitter enabled. NOTE: per
1633  // the data sheet, this must be set *AFTER* UARTEN
1634  // is set to 1 (see UxMODE assignment above).
1635  (0b00 << 6) | // URXISEL = 00 (Interrupt flag bit is set when a
1636  // character is received)
1637  (0u << 5) | // ADDEN = 0 (Address detect mode disabled)
1638  (0u << 1); // OERR = 0 (Clear any overrun errors)
1639 
1640  // Delay 1 ms (at least one bit time) before beginning transmission,
1641  // since the UxTX pin is initially configured as an input on device
1642  // reset. It needs to be high for at least one bit time before
1643  // a character is sent in order for the start bit to be recognized.
1644  // See 24H FRM Sec. 17.5 for more details.
1645  ASSERT(u32_baudRate >= 1000L);
1646  // Note: If the baud rate is less than 1000, this delay
1647  // isn't long encough. The alternative is to use floating-point
1648  // math to compute the correct delay, which seems worse than the
1649  // problem.
1650  DELAY_MS(1);
1651 
1652  // Clear any errors
1653  U4STAbits.OERR = 0;
1654  while (U4STAbits.PERR || U4STAbits.FERR) {
1655  U4RXREG; //clear errors by reading RXREG
1656  }
1657 
1658  // Set up interrupts if requested
1659 #ifdef UART4_RX_INTERRUPT
1660  _U4RXIF = 0; //clear the flag
1661  _U4RXIP = UART4_RX_INTERRUPT_PRIORITY; //choose a priority
1662  _U4RXIE = 1; //enable the interrupt
1663 #endif
1664 #ifdef UART4_TX_INTERRUPT
1665  //do not clear the U4TXIF flag!
1666  _U4TXIP = UART4_TX_INTERRUPT_PRIORITY; //choose a priority
1667  //do not enable the interrupt until we try to write to the UART
1668 #endif
1669 
1670 }
1671 
1672 #endif // #if (NUM_UARTS >= 4)
1673 
1674 
1675 
1676