Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
serial.c
00001 /*---------------------------------------------------------------------------- 00002 * Name: serial.c 00003 * Purpose: serial port handling for LPC17xx 00004 * Version: V1.20 00005 *---------------------------------------------------------------------------- 00006 * This software is supplied "AS IS" without any warranties, express, 00007 * implied or statutory, including but not limited to the implied 00008 * warranties of fitness for purpose, satisfactory quality and 00009 * noninfringement. Keil extends you a royalty-free right to reproduce 00010 * and distribute executable files created using this software for use 00011 * on NXP Semiconductors LPC microcontroller devices only. Nothing else 00012 * gives you the right to use this software. 00013 * 00014 * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. 00015 *---------------------------------------------------------------------------*/ 00016 #include "LPC17xx.h" // LPC17xx definitions 00017 //#include "LPC23xx.h" 00018 #include "type.h" 00019 #include "serial.h" 00020 00021 #include "compatible.h" 00022 00023 /*---------------------------------------------------------------------------- 00024 Defines for ring buffers 00025 *---------------------------------------------------------------------------*/ 00026 #define SER_BUF_SIZE (128) // serial buffer in bytes (power 2) 00027 #define SER_BUF_MASK (SER_BUF_SIZE-1ul) // buffer size mask 00028 00029 /* Buffer read / write macros */ 00030 #define SER_BUF_RESET(serBuf) (serBuf.rdIdx = serBuf.wrIdx = 0) 00031 #define SER_BUF_WR(serBuf, dataIn) (serBuf.data[SER_BUF_MASK & serBuf.wrIdx++] = (dataIn)) 00032 #define SER_BUF_RD(serBuf) (serBuf.data[SER_BUF_MASK & serBuf.rdIdx++]) 00033 #define SER_BUF_EMPTY(serBuf) (serBuf.rdIdx == serBuf.wrIdx) 00034 #define SER_BUF_FULL(serBuf) (serBuf.rdIdx == serBuf.wrIdx+1) 00035 #define SER_BUF_COUNT(serBuf) (SER_BUF_MASK & (serBuf.wrIdx - serBuf.rdIdx)) 00036 00037 // buffer type 00038 typedef struct __SER_BUF_T { 00039 unsigned char data[SER_BUF_SIZE]; 00040 unsigned int wrIdx; 00041 unsigned int rdIdx; 00042 } SER_BUF_T; 00043 00044 unsigned long ser_txRestart; // NZ if TX restart is required 00045 unsigned short ser_lineState; // ((msr << 8) | (lsr)) 00046 SER_BUF_T ser_out; // Serial data buffers 00047 SER_BUF_T ser_in; 00048 00049 /*---------------------------------------------------------------------------- 00050 open the serial port 00051 *---------------------------------------------------------------------------*/ 00052 void ser_OpenPort (char portNum) { 00053 00054 if ( portNum == 0 ) 00055 { 00056 /* Port 0 */ 00057 NVIC_DisableIRQ(UART0_IRQn); 00058 LPC_PINCON->PINSEL0 &= ~0x000000F0; 00059 LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 is P0.3 and TxD0 is P0.2 */ 00060 } 00061 else 00062 { 00063 /* Port 1 */ 00064 NVIC_DisableIRQ(UART1_IRQn); 00065 LPC_PINCON->PINSEL4 &= ~0x0000000F; 00066 LPC_PINCON->PINSEL4 |= 0x0000000A; /* Enable RxD1 P2.1, TxD1 P2.0 */ 00067 } 00068 return; 00069 } 00070 00071 /*---------------------------------------------------------------------------- 00072 close the serial port 00073 *---------------------------------------------------------------------------*/ 00074 void ser_ClosePort (char portNum ) { 00075 if ( portNum == 0 ) 00076 { 00077 /* POrt 0 */ 00078 LPC_PINCON->PINSEL0 &= ~0x000000F0; 00079 /* Disable the interrupt in the VIC and UART controllers */ 00080 LPC_UART0->IER = 0; 00081 NVIC_DisableIRQ(UART0_IRQn); 00082 } 00083 else 00084 { 00085 /* Port 1 */ 00086 LPC_PINCON->PINSEL4 &= ~0x0000000F; 00087 /* Disable the interrupt in the VIC and UART controllers */ 00088 LPC_UART1->IER = 0; 00089 NVIC_DisableIRQ(UART1_IRQn); 00090 } 00091 return; 00092 } 00093 00094 /*---------------------------------------------------------------------------- 00095 initialize the serial port 00096 *---------------------------------------------------------------------------*/ 00097 void ser_InitPort0 (unsigned long baudrate, unsigned int databits, 00098 unsigned int parity, unsigned int stopbits) { 00099 00100 unsigned char lcr_p, lcr_s, lcr_d; 00101 unsigned int dll; 00102 unsigned int pclkdiv, pclk; 00103 00104 switch (databits) { 00105 case 5: // 5 Data bits 00106 lcr_d = 0x00; 00107 break; 00108 case 6: // 6 Data bits 00109 lcr_d = 0x01; 00110 break; 00111 case 7: // 7 Data bits 00112 lcr_d = 0x02; 00113 break; 00114 case 8: // 8 Data bits 00115 default: 00116 lcr_d = 0x03; 00117 break; 00118 } 00119 00120 switch (stopbits) { 00121 case 1: // 1,5 Stop bits 00122 case 2: // 2 Stop bits 00123 lcr_s = 0x04; 00124 break; 00125 case 0: // 1 Stop bit 00126 default: 00127 lcr_s = 0x00; 00128 break; 00129 } 00130 00131 switch (parity) { 00132 case 1: // Parity Odd 00133 lcr_p = 0x08; 00134 break; 00135 case 2: // Parity Even 00136 lcr_p = 0x18; 00137 break; 00138 case 3: // Parity Mark 00139 lcr_p = 0x28; 00140 break; 00141 case 4: // Parity Space 00142 lcr_p = 0x38; 00143 break; 00144 case 0: // Parity None 00145 default: 00146 lcr_p = 0x00; 00147 break; 00148 } 00149 00150 SER_BUF_RESET(ser_out); // reset out buffer 00151 SER_BUF_RESET(ser_in); // reset in buffer 00152 00153 /* Bit 6~7 is for UART0 */ 00154 pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03; 00155 00156 switch ( pclkdiv ) 00157 { 00158 case 0x00: 00159 default: 00160 pclk = SystemFrequency/4; 00161 break; 00162 case 0x01: 00163 pclk = SystemFrequency; 00164 break; 00165 case 0x02: 00166 pclk = SystemFrequency/2; 00167 break; 00168 case 0x03: 00169 pclk = SystemFrequency/8; 00170 break; 00171 } 00172 00173 dll = (pclk/16)/baudrate ; /*baud rate */ 00174 LPC_UART0->FDR = 0; // Fractional divider not used 00175 LPC_UART0->LCR = 0x80 | lcr_d | lcr_p | lcr_s; // Data bits, Parity, Stop bit 00176 LPC_UART0->DLL = dll; // Baud Rate depending on PCLK 00177 LPC_UART0->DLM = (dll >> 8); // High divisor latch 00178 LPC_UART0->LCR = 0x00 | lcr_d | lcr_p | lcr_s; // DLAB = 0 00179 LPC_UART0->IER = 0x03; // Enable TX/RX interrupts 00180 00181 LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */ 00182 ser_txRestart = 1; // TX fifo is empty 00183 00184 /* Enable the UART Interrupt */ 00185 NVIC_EnableIRQ(UART0_IRQn); 00186 return; 00187 } 00188 00189 /*---------------------------------------------------------------------------- 00190 initialize the serial port 00191 *---------------------------------------------------------------------------*/ 00192 void ser_InitPort1 (unsigned long baudrate, unsigned int databits, 00193 unsigned int parity, unsigned int stopbits) { 00194 00195 unsigned char lcr_p, lcr_s, lcr_d; 00196 unsigned int dll; 00197 unsigned int pclkdiv, pclk; 00198 00199 switch (databits) { 00200 case 5: // 5 Data bits 00201 lcr_d = 0x00; 00202 break; 00203 case 6: // 6 Data bits 00204 lcr_d = 0x01; 00205 break; 00206 case 7: // 7 Data bits 00207 lcr_d = 0x02; 00208 break; 00209 case 8: // 8 Data bits 00210 default: 00211 lcr_d = 0x03; 00212 break; 00213 } 00214 00215 switch (stopbits) { 00216 case 1: // 1,5 Stop bits 00217 case 2: // 2 Stop bits 00218 lcr_s = 0x04; 00219 break; 00220 case 0: // 1 Stop bit 00221 default: 00222 lcr_s = 0x00; 00223 break; 00224 } 00225 00226 switch (parity) { 00227 case 1: // Parity Odd 00228 lcr_p = 0x08; 00229 break; 00230 case 2: // Parity Even 00231 lcr_p = 0x18; 00232 break; 00233 case 3: // Parity Mark 00234 lcr_p = 0x28; 00235 break; 00236 case 4: // Parity Space 00237 lcr_p = 0x38; 00238 break; 00239 case 0: // Parity None 00240 default: 00241 lcr_p = 0x00; 00242 break; 00243 } 00244 00245 SER_BUF_RESET(ser_out); // reset out buffer 00246 SER_BUF_RESET(ser_in); // reset in buffer 00247 00248 /* Bit 8,9 are for UART1 */ 00249 pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03; 00250 00251 switch ( pclkdiv ) 00252 { 00253 case 0x00: 00254 default: 00255 pclk = SystemFrequency/4; 00256 break; 00257 case 0x01: 00258 pclk = SystemFrequency; 00259 break; 00260 case 0x02: 00261 pclk = SystemFrequency/2; 00262 break; 00263 case 0x03: 00264 pclk = SystemFrequency/8; 00265 break; 00266 } 00267 00268 dll = (pclk/16)/baudrate ; /*baud rate */ 00269 LPC_UART1->FDR = 0; // Fractional divider not used 00270 LPC_UART1->LCR = 0x80 | lcr_d | lcr_p | lcr_s; // Data bits, Parity, Stop bit 00271 LPC_UART1->DLL = dll; // Baud Rate depending on PCLK 00272 LPC_UART1->DLM = (dll >> 8); // High divisor latch 00273 LPC_UART1->LCR = 0x00 | lcr_d | lcr_p | lcr_s; // DLAB = 0 00274 LPC_UART1->IER = 0x03; // Enable TX/RX interrupts 00275 00276 LPC_UART1->FCR = 0x07; /* Enable and reset TX and RX FIFO. */ 00277 ser_txRestart = 1; // TX fifo is empty 00278 00279 /* Enable the UART Interrupt */ 00280 NVIC_EnableIRQ(UART1_IRQn); 00281 return; 00282 } 00283 00284 /*---------------------------------------------------------------------------- 00285 read data from serial port 00286 *---------------------------------------------------------------------------*/ 00287 int ser_Read (char *buffer, const int *length) { 00288 int bytesToRead, bytesRead; 00289 00290 /* Read *length bytes, block if *bytes are not avaialable */ 00291 bytesToRead = *length; 00292 bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length); 00293 bytesRead = bytesToRead; 00294 00295 while (bytesToRead--) { 00296 while (SER_BUF_EMPTY(ser_in)); // Block until data is available if none 00297 *buffer++ = SER_BUF_RD(ser_in); 00298 } 00299 return (bytesRead); 00300 } 00301 00302 /*---------------------------------------------------------------------------- 00303 write data to the serial port 00304 *---------------------------------------------------------------------------*/ 00305 int ser_Write (char portNum, const char *buffer, int *length) { 00306 int bytesToWrite, bytesWritten; 00307 00308 // Write *length bytes 00309 bytesToWrite = *length; 00310 bytesWritten = bytesToWrite; 00311 00312 while (!SER_BUF_EMPTY(ser_out)); // Block until space is available if none 00313 while (bytesToWrite) { 00314 SER_BUF_WR(ser_out, *buffer++); // Read Rx FIFO to buffer 00315 bytesToWrite--; 00316 } 00317 00318 if (ser_txRestart) { 00319 ser_txRestart = 0; 00320 if ( portNum == 0 ) 00321 { 00322 LPC_UART0->THR = SER_BUF_RD(ser_out); // Write to the Tx Register 00323 } 00324 else 00325 { 00326 LPC_UART1->THR = SER_BUF_RD(ser_out); // Write to the Tx Register 00327 } 00328 } 00329 00330 return (bytesWritten); 00331 } 00332 00333 /*---------------------------------------------------------------------------- 00334 check if character(s) are available at the serial interface 00335 *---------------------------------------------------------------------------*/ 00336 void ser_AvailChar (int *availChar) { 00337 00338 *availChar = SER_BUF_COUNT(ser_in); 00339 00340 } 00341 00342 /*---------------------------------------------------------------------------- 00343 read the line state of the serial port 00344 *---------------------------------------------------------------------------*/ 00345 void ser_LineState (unsigned short *lineState) { 00346 00347 *lineState = ser_lineState; 00348 ser_lineState = 0; 00349 00350 } 00351 00352 /*---------------------------------------------------------------------------- 00353 serial port 0 interrupt 00354 *---------------------------------------------------------------------------*/ 00355 void UART0_IRQHandler(void) 00356 { 00357 volatile unsigned long iir; 00358 00359 iir = LPC_UART0->IIR; 00360 00361 if ((iir & 0x4) || (iir & 0xC)) { // RDA or CTI pending 00362 while (LPC_UART0->LSR & 0x01) { // Rx FIFO is not empty 00363 SER_BUF_WR(ser_in, LPC_UART0->RBR); // Read Rx FIFO to buffer 00364 } 00365 } 00366 if ((iir & 0x2)) { // TXMIS pending 00367 if (SER_BUF_COUNT(ser_out) != 0) { 00368 LPC_UART0->THR = SER_BUF_RD(ser_out); // Write to the Tx FIFO 00369 ser_txRestart = 0; 00370 } 00371 else { 00372 ser_txRestart = 1; 00373 } 00374 } 00375 ser_lineState = LPC_UART0->LSR & 0x1E; // update linestate 00376 return; 00377 } 00378 00379 /*---------------------------------------------------------------------------- 00380 serial port 1 interrupt 00381 *---------------------------------------------------------------------------*/ 00382 void UART1_IRQHandler(void) 00383 { 00384 volatile unsigned long iir; 00385 00386 iir = LPC_UART1->IIR; 00387 00388 if ((iir & 0x4) || (iir & 0xC)) { // RDA or CTI pending 00389 while (LPC_UART1->LSR & 0x01) { // Rx FIFO is not empty 00390 SER_BUF_WR(ser_in, LPC_UART1->RBR); // Read Rx FIFO to buffer 00391 } 00392 } 00393 if ((iir & 0x2)) { // TXMIS pending 00394 if (SER_BUF_COUNT(ser_out) != 0) { 00395 LPC_UART1->THR = SER_BUF_RD(ser_out); // Write to the Tx FIFO 00396 ser_txRestart = 0; 00397 } 00398 else { 00399 ser_txRestart = 1; 00400 } 00401 } 00402 ser_lineState = ((LPC_UART1->MSR<<8)|LPC_UART1->LSR) & 0xE01E; // update linestate 00403 return; 00404 } 00405 00406
Generated on Thu Jul 14 2022 04:45:41 by
1.7.2