最近在做一个关于串口的项目,于是把之前的串口程序又拿了出来,重新优化了一下!
1、头文件《uart.h》如下:
1 /* 2 ****************************************************************************************************** 3 ** Copright(c) 2007-2014,深圳固镭特电子 ** 4 ** All rights reserved. ** 5 ** http://www.greatele.com ** 6 ****************************************************************************************************** 7 **文件名称: uart.h ** 8 **文件标识: LPC17xx ** 9 **摘 要: 串口(UART0、UART1、UART2、UART3)通讯程序头文件 ** 10 **当前版本: V1.3 ** 11 **作 者: 江南神枪 ** 12 **完成日期: 2011.06.10---V1.0 ** 13 **修 改:2011.12.11---V1.1 : 对于IIR_RDA中断,接收RX_FIFO_SIZE-1个字节,对于刚好是RX_FIFO_SIZE ** 14 的整数倍个字节数据时,留一个字节于FIFO中,以产生CTI中断! ** 15 解决接收RX_FIFO_SIZE的整数倍个字节数据时无法创建接收完成标致(RX_OK)的问题! ** 16 ** 2014.01.01---V1.2 :增加中断发送数据功能. ** 17 ** 2014.10.18---V1.3 :修改部分bug,调整通过串口号选择串口而不通过结构选择串口! ** 18 ****************************************************************************************************** 19 */ 20 #ifdef UART_GLOBALS 21 #define UART_EXT 22 #else 23 #define UART_EXT extern 24 #endif 25 26 27 /* 28 ****************************************************************************************************** 29 ** 参数配置 ** 30 ****************************************************************************************************** 31 */ 32 #define RX_FIFO_SIZE (14) //设置RX FIFO触发深度4、8、14. 33 #define TX_FIFO_SIZE (16) //设置TX FIFO的使用长度. 34 #define BUFFER_SIZE (256) //设置串口收发数据缓冲区的长度. 35 36 /* 37 ****************************************************************************************************** 38 ** 全局变量定义 ** 39 ****************************************************************************************************** 40 */ 41 #define UART0 0x00 //串口号 42 #define UART1 0x01 43 #define UART2 0x02 44 #define UART3 0x03 45 46 UART_EXT uint32 BaudRate[4]; //波特率. 47 48 //对于RX FIFO触发深度为1的情况(和不使用FIFO差不多,意义不大),不作处理!默认触发深度为8字节! 49 #define FCR_VAL ((RX_FIFO_SIZE==4)?0x47:((RX_FIFO_SIZE==8)?0x87:((RX_FIFO_SIZE==14)?0xC7:0x87))) 50 51 //把UART1也转成和别的UART一样的结构,以便函数入参用!但程序中会对UART1的结构还原为正确的再使用! 52 #define LPC_UART(x) ((x==0)?(LPC_UART_TypeDef *)LPC_UART0_BASE: 53 ((x==1)?(LPC_UART_TypeDef *)LPC_UART1_BASE: 54 ((x==2)?(LPC_UART_TypeDef *)LPC_UART2_BASE: 55 (LPC_UART_TypeDef *)LPC_UART3_BASE))) 56 57 //串口收发线状态位控制(LSR寄存器). 58 #define LSR_RDR ((uint8)(1<<0)) 59 #define LSR_OE ((uint8)(1<<1)) 60 #define LSR_PE ((uint8)(1<<2)) 61 #define LSR_FE ((uint8)(1<<3)) 62 #define LSR_BI ((uint8)(1<<4)) 63 #define LSR_THRE ((uint8)(1<<5)) 64 #define LSR_TEMT ((uint8)(1<<6)) 65 #define LSR_RXFE ((uint8)(1<<7)) 66 #define LSR_BITMASK ((uint8)(0xFF)) 67 68 //串口中断标识位控制(IIR寄存器). 69 #define IIR_INTSTAT ((uint32)(1<<0)) 70 #define IIR_RLS ((uint32)(3<<1)) 71 #define IIR_RDA ((uint32)(2<<1)) 72 #define IIR_CTI ((uint32)(6<<1)) 73 #define IIR_THRE ((uint32)(1<<1)) 74 #define IIR_MASK ((uint32)(7<<1)) 75 #define IIR_BITMASK ((uint32)(0x3CF)) 76 77 //串口收发中断位控制(IER寄存器). 78 #define IER_RBR ((uint32)(1<<0)) //接收数据可用中断. 79 #define IER_THRE ((uint32)(1<<1)) //发送数据缓冲区为空. 80 #define IER_BITMASK ((uint32)(0x307)) 81 #define IER1_BITMASK ((uint32)(0x38F)) 82 83 //中断类型. 84 typedef enum 85 { 86 IRQ_RBR = 0, 87 IRQ_THRE = 1 88 }IRQ_TYPE; 89 90 //使能状况. 91 typedef enum 92 { 93 DISABLE = 0, 94 ENABLE = !DISABLE 95 }State; 96 97 //状态标志. 98 typedef enum 99 { 100 RESET = 0, //复位. 101 SET = !RESET //置位. 102 }BitFlag; 103 104 //串口相关标志及数据缓冲区结构. 105 typedef struct 106 { 107 uint8 RX_OK; //串口接收完成标志. 0:未接收完成 1:接收完成 108 uint8 TX_OK; //串口发送完成标志. 0:未发送完成 1:发送完成 109 uint16 RX_cnt; //收到字节计数器. 110 uint16 TX_cnt; //发送字节计数器. 111 uint16 RX_len; //已接收的字节长度. 112 uint16 TX_len; //待发送的字节长度. 113 uint8 RX_Buffer[BUFFER_SIZE]; //串口接收缓冲区. 114 uint8 TX_Buffer[BUFFER_SIZE]; //串口发送缓冲区. 115 116 }uart_info; 117 118 //结构实体定义 119 UART_EXT uart_info UART[4]; //4个结构对应4个串口. 120 121 122 /* 123 ****************************************************************************************************** 124 **函数名称: UART_IO_INIT(uint8 COM) ** 125 **函数描述:所有串口IO初始化---RTS根据自己的实际情况修改! ** 126 **参 数: COM--------串口: 0,1,2,3 ** 127 **返 回: 无 ** 128 ****************************************************************************************************** 129 */ 130 UART_EXT void UART_IO_INIT(uint8 COM); 131 132 /* 133 ****************************************************************************************************** 134 **函数名称: void UART_INIT(uint8 COM, uint32 BaudRate) ** 135 **函数描述:串口UART初始化 ** 136 **参 数: COM--------串口: 0,1,2,3 ** 137 ** BaudRate---波特率 ** 138 **返 回: 无 ** 139 ****************************************************************************************************** 140 */ 141 UART_EXT void UART_INIT(uint8 COM, uint32 BaudRate); 142 143 /* 144 ****************************************************************************************************** 145 **函数名称: uint16 UART_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) ** 146 **函数描述:串口UART发送多个字节(供外部文件调用) ** 147 **参 数: COM---------串口: 0,1,2,3 ** 148 ** txbuf-------数据指针,指向发送缓冲区 ** 149 ** len---------待发送字节数 ** 150 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 151 **返 回: bSent---成功发送字节数 ** 152 ****************************************************************************************************** 153 */ 154 UART_EXT uint16 UART_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485); 155 156 /* 157 ****************************************************************************************************** 158 **函数名称: uint16 UART_SendStrings(uint8 COM, char *txbuf, State USE_RS485) ** 159 **函数描述:串口UART发送字符串(供外部文件调用) ** 160 **参 数: COM---------串口: 0,1,2,3 ** 161 ** txbuf-------数据指针,指向发送缓冲区 ** 162 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 163 **返 回: bSent---成功发送字节数 ** 164 ****************************************************************************************************** 165 */ 166 UART_EXT uint16 UART_SendStrings(uint8 COM, char *txbuf, State USE_RS485); 167 168 /* 169 ****************************************************************************************************** 170 **函数名称: void UART_IRQ_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) ** 171 **函数描述:串口UART中断发送多个字节(供外部文件调用) ** 172 **参 数: COM---------串口: 0,1,2,3 ** 173 ** txbuf-------数据指针,指向发送缓冲区 ** 174 ** len---------待发送字节数 ** 175 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 176 **返 回: ERR---发送失败 OK---发送成功 ** 177 ****************************************************************************************************** 178 */ 179 UART_EXT void UART_IRQ_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485); 180 181 /* 182 ****************************************************************************************************** 183 **函数名称: void UART_IRQ_SendStrings(uint8 COM, char *txbuf, State USE_RS485) ** 184 **函数描述:串口UART中断发送字符串(供外部文件调用) ** 185 **参 数: COM---------串口: 0,1,2,3 ** 186 ** txbuf-------数据指针,指向发送缓冲区 ** 187 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 188 **返 回: ERR---发送失败 OK---发送成功 ** 189 ****************************************************************************************************** 190 */ 191 UART_EXT void UART_IRQ_SendStrings(uint8 COM, char *txbuf, State USE_RS485); 192 193 /* 194 ****************************************************************************************************** 195 **函数名称: void UART_Printf(char *fmt,...) ** 196 **函数描述:UART0串口打印程序函数 ** 197 **参 数: *fmt---格式 ** 198 **返 回: 无 ** 199 ****************************************************************************************************** 200 */ 201 //构造此函数必须包含#include <stdarg.h>和#include <stdio.h>这两个头文件! 202 203 UART_EXT void UART_Printf(char *fmt,...); 204 205 /* 206 ****************************************************************************************************** 207 ** End Of File ** 208 ****************************************************************************************************** 209 */
2、程序文件《uart.c》如下:
1 /* 2 ****************************************************************************************************** 3 ** Copright(c) 2007-2014,深圳固镭特电子 ** 4 ** All rights reserved. ** 5 ** http://www.greatele.com ** 6 ****************************************************************************************************** 7 **文件名称: uart.c ** 8 **文件标识: LPC17xx ** 9 **摘 要: 串口(UART0、UART1、UART2、UART3)通讯程序 ** 10 **当前版本: V1.3 ** 11 **作 者: 江南神枪 ** 12 **完成日期: 2011.06.10---V1.0 ** 13 **修 改:2011.12.11---V1.1 : 对于IIR_RDA中断,接收RX_FIFO_SIZE-1个字节,对于刚好是RX_FIFO_SIZE ** 14 的整数倍个字节数据时,留一个字节于FIFO中,以产生CTI中断! ** 15 解决接收RX_FIFO_SIZE的整数倍个字节数据时无法创建接收完成标致(RX_OK)的问题! ** 16 ** 2014.01.01---V1.2 :增加中断发送数据功能. ** 17 ** 2014.10.18---V1.3 :修改部分bug,调整通过串口号选择串口而不通过结构选择串口! ** 18 ****************************************************************************************************** 19 */ 20 #define UART_GLOBALS 21 #include "config.h" 22 23 /* 24 ****************************************************************************************************** 25 ** RS485使能信号定义 ** 26 ****************************************************************************************************** 27 */ 28 //本地使用的信号,无须在头文件中定义!------根据实际情况修改! 29 30 #define RTS0 (1<<18) //P1.18 31 #define RTS1 (1<<19) //P1.19 32 #define RTS2 (1<<20) //P1.20 33 #define RTS3 (1<<22) //P1.22 34 35 //bit=0 或 bit=1 36 #define RTS_0(bit) ( (bit==0)? (LPC_GPIO1->FIOCLR |=RTS0):(LPC_GPIO1->FIOSET |=RTS0) ) //UART0收发使能信号 37 #define RTS_1(bit) ( (bit==0)? (LPC_GPIO1->FIOCLR |=RTS1):(LPC_GPIO1->FIOSET |=RTS1) ) //UART1收发使能信号 38 #define RTS_2(bit) ( (bit==0)? (LPC_GPIO1->FIOCLR |=RTS2):(LPC_GPIO1->FIOSET |=RTS2) ) //UART2收发使能信号 39 #define RTS_3(bit) ( (bit==0)? (LPC_GPIO1->FIOCLR |=RTS3):(LPC_GPIO1->FIOSET |=RTS3) ) //UART3收发使能信号 40 41 42 /* 43 ****************************************************************************************************** 44 **函数名称: UART_info *BUF_SELECT(uint8 COM) ** 45 **函数描述:串口缓冲区结构的选择 ** 46 **参 数: COM---------串口号: 0,1,2,3 ** 47 **返 回: UART_INFO---串口信息结构 ** 48 ****************************************************************************************************** 49 */ 50 uart_info *BUF_SELECT(uint8 COM) 51 { 52 uart_info *UART_INFO=NULL; 53 54 if(COM == UART0){ UART_INFO = &UART[0]; } 55 if(COM == UART1){ UART_INFO = &UART[1]; } 56 if(COM == UART2){ UART_INFO = &UART[2]; } 57 if(COM == UART3){ UART_INFO = &UART[3]; } 58 59 return(UART_INFO); 60 } 61 62 /* 63 ****************************************************************************************************** 64 **函数名称: UART_IO_INIT(uint8 COM) ** 65 **函数描述:所有串口IO初始化---RTS根据自己的实际情况修改! ** 66 **参 数: COM--------串口: 0,1,2,3 ** 67 **返 回: 无 ** 68 ****************************************************************************************************** 69 */ 70 void UART_IO_INIT(uint8 COM) 71 { 72 if(COM == UART0) 73 { 74 LPC_PINCON->PINSEL0 |= (1 << 4); // 引脚配置:TXD0=P0.2 RXD0=P0.3 75 LPC_PINCON->PINSEL0 |= (1 << 6); 76 LPC_PINCON->PINSEL3 |= (0 << 4); // RST_0=P1.18 GPIO---方向为输出 77 LPC_GPIO1->FIODIR |= RTS0; 78 RTS_0(0); // 初始化为接收状态 79 } 80 81 if(COM == UART1) 82 { 83 LPC_PINCON->PINSEL4 |= (2 << 0); // 引脚配置:TXD1=P2.0 RXD1=P2.1 84 LPC_PINCON->PINSEL4 |= (2 << 2); 85 LPC_PINCON->PINSEL3 |= (0 << 6); // RST_1=P1.19 GPIO---方向为输出 86 LPC_GPIO1->FIODIR |= RTS1; 87 RTS_1(0); // 初始化为接收状态 88 } 89 90 if(COM == UART2) 91 { 92 LPC_SC->PCONP |= 0x01000000; // 使能UART2功率/时钟控制位---第24位,默认关闭 93 LPC_PINCON->PINSEL4 |= (2 << 16); // 引脚配置:TXD2=P2.08 RXD2=P2.09 94 LPC_PINCON->PINSEL4 |= (2 << 18); 95 LPC_PINCON->PINSEL3 |= (0 << 8); // RST_2=P1.20 GPIO---方向为输出 96 LPC_GPIO1->FIODIR |= RTS2; 97 RTS_2(0); // 初始化为接收状态 98 } 99 100 if(COM == UART3) 101 { 102 LPC_SC->PCONP |= 0x02000000; // 使能UART3功率/时钟控制位---第25位,默认关闭 103 LPC_PINCON->PINSEL9 |= (3 << 24); // 引脚配置:TXD3=P4.28 RXD3=P4.29 104 LPC_PINCON->PINSEL9 |= (3 << 26); 105 LPC_PINCON->PINSEL3 |= (0 << 12); // RST_3=P1.22 GPIO---方向为输出 106 LPC_GPIO1->FIODIR |= RTS3; 107 RTS_3(0); // 初始化为接收状态 108 } 109 } 110 111 /* 112 ****************************************************************************************************** 113 **函数名称: void Set_Baudrate(uint32 BaudRate, uint16 *V_DL, uint8 *V_FDR) ** 114 **函数描述:设置精准的波特率(带小数分频寄存器的设定) ** 115 **参 数: 入参---BaudRate 出参指针---*V_DL、*V_FDR ** 116 **返 回: 无 ** 117 ****************************************************************************************************** 118 */ 119 void Set_Baudrate(uint32 BaudRate, uint16 *V_DL, uint8 *V_FDR) 120 { 121 //BaudRate = Fpclk / ( 16 * DL * (1 + DIVADDVAL / MULVAL) ) 122 // = Fpclk * MULVAL / (DIVADDVAL + MULVAL) / (16 * DL) 123 124 uint8 d=0, m=0, bestd=0, bestm=0; 125 uint32 divisor=0, tmp_divisor=0, best_divisor=0; 126 uint32 current_error=0, best_error=0; 127 128 divisor = (Fpclk>>4)*100/BaudRate; //求出最精确的除数值(取小数点后2位,即放大100倍)! 129 best_error = 0xFFFFFFFF; 130 131 //查找最佳的DL(DLL和DLM)、DIVADDVAL和MULVAL值---此3个数值结合运算,结果最接近divisor值(误差最小)的数为最佳组合! 132 for(m=1; m<=15; m++) 133 { 134 for(d=0; d<m; d++) 135 { 136 tmp_divisor = divisor*m/(m+d); //根据不同的D值和M值确定DL值. 137 current_error = tmp_divisor%100; //缩小100倍后,整数部分即为DL的值。那么对100取余即为小数误差! 138 139 if(current_error < best_error) //误差最小的即为最佳给合! 140 { 141 best_error = current_error; 142 best_divisor = tmp_divisor/100; //最佳的DL、D、M值! 143 bestd = d; 144 bestm = m; 145 if(best_error == 0) break; //误差为0,即不需小数分频寄存器,仅DL就能确定精准的波特率! 146 } 147 } 148 if (best_error == 0) break; 149 } 150 151 *V_DL = best_divisor; 152 *V_FDR = (bestm<<4) | bestd; 153 } 154 155 /* 156 ****************************************************************************************************** 157 **函数名称: void UART_INIT(uint8 COM, uint32 BaudRate) ** 158 **函数描述:串口UART初始化 ** 159 **参 数: COM--------串口: 0,1,2,3 ** 160 ** BaudRate---波特率 ** 161 **返 回: 无 ** 162 ****************************************************************************************************** 163 */ 164 void UART_INIT(uint8 COM, uint32 BaudRate) 165 { 166 uint16 V_DL; 167 uint8 V_FDR; 168 uart_info *UART_INFO; 169 170 Set_Baudrate(BaudRate, &V_DL, &V_FDR); // 按期望的波特率,计算最佳的DLL、DLM和FDR值! 171 172 UART_INFO = BUF_SELECT(COM); // 选择对应的串口信息结构. 173 UART_INFO->RX_OK = FALSE; // 串口接收完成标志清零. 174 UART_INFO->TX_OK = TRUE; // 串口发送完成标志置位. 175 176 if(COM==UART1) 177 { 178 LPC_UART1->LCR = 0x83; // DLAB = 1, 使能访问除数锁存寄存器. 179 LPC_UART1->DLM = V_DL >> 8; // 除数高8位. 180 LPC_UART1->DLL = V_DL & 0xff; // 除数低8位. 181 LPC_UART1->FDR = V_FDR; // 小数分频寄存器赋值. 182 LPC_UART1->LCR &= 0x7f; // DLAB = 0, 禁止访问除数锁存寄存器. 183 LPC_UART1->LCR = 0x03; // 8位, 无校验, 1位停止位. 184 LPC_UART1->FCR = FCR_VAL; // 使能FIFO,并设置RX FIFO触发深度. 185 LPC_UART1->IER = 0x01; // 使能UART1接收中断,禁止发送中断. 186 187 NVIC_EnableIRQ(UART1_IRQn); // 使能LPC_UART1串口总中断,中断优先级默认! 188 } 189 else 190 { 191 LPC_UART(COM)->LCR = 0x83; // DLAB = 1, 使能访问除数锁存寄存器. 192 LPC_UART(COM)->DLM = V_DL >> 8; // 除数高8位. 193 LPC_UART(COM)->DLL = V_DL & 0xff; // 除数低8位. 194 LPC_UART(COM)->FDR = V_FDR; // 小数分频寄存器赋值. 195 LPC_UART(COM)->LCR &= 0x7f; // DLAB = 0, 禁止访问除数锁存寄存器. 196 LPC_UART(COM)->LCR = 0x03; // 8位, 无校验, 1位停止位. 197 LPC_UART(COM)->FCR = FCR_VAL; // 使能FIFO,并设置RX FIFO触发深度. 198 LPC_UART(COM)->IER = 0x01; // 使能UARTx接收中断,禁止发送中断. 199 200 201 if(COM == UART0) // 使能LPC_UARTx串口总中断,中断优先级默认! 202 {NVIC_EnableIRQ(UART0_IRQn);} 203 if(COM == UART2) 204 {NVIC_EnableIRQ(UART2_IRQn);} 205 if(COM == UART3) 206 {NVIC_EnableIRQ(UART3_IRQn);} 207 } 208 } 209 210 /* 211 ****************************************************************************************************** 212 **函数名称: RS485_EN(uint8 COM, BitFlag Bit, State USE_RS485) ** 213 **函数描述:串口RS485方向控制使能 ** 214 **参 数: COM--------串口: 0,1,2,3 ** 215 ** Bit---RESET:接收 SET:发送 ** 216 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 217 **返 回: 无 ** 218 ****************************************************************************************************** 219 */ 220 void RS485_EN(uint8 COM, BitFlag Bit, State USE_RS485) 221 { 222 if(USE_RS485) 223 { 224 if(COM == UART0){ RTS_0(Bit); } 225 if(COM == UART1){ RTS_1(Bit); } 226 if(COM == UART2){ RTS_2(Bit); } 227 if(COM == UART3){ RTS_3(Bit); } 228 } 229 } 230 231 /* 232 ****************************************************************************************************** 233 **函数名称: void UART_IRQ_CFG(uint8 COM, IRQ_TYPE IRQ, State NewState) ** 234 **函数描述:串口收发中断使能配置 ** 235 **参 数: COM--------串口: 0,1,2,3 ** 236 ** IRQ---中断类型 ** 237 ** NewState---DISABLE:不使能该中断 ENABLE:使能该中断 ** 238 **返 回: 无 ** 239 ****************************************************************************************************** 240 */ 241 void UART_IRQ_CFG(uint8 COM, IRQ_TYPE IRQ, State NewState) 242 { 243 uint32 temp=0; 244 245 //先判断中断类型. 246 switch(IRQ) 247 { 248 case IRQ_RBR: 249 temp = IER_RBR; 250 break; 251 252 case IRQ_THRE: 253 temp = IER_THRE; 254 break; 255 } 256 257 //再判断使能状况. 258 if (NewState == ENABLE) 259 { 260 if(COM==UART1) 261 { 262 LPC_UART1->IER |= temp; 263 } 264 else 265 { 266 LPC_UART(COM)->IER |= temp; 267 } 268 } 269 else 270 { 271 if(COM==UART1) 272 { 273 LPC_UART1->IER &= (~temp) & IER1_BITMASK; 274 } 275 else 276 { 277 LPC_UART(COM)->IER &= (~temp) & IER_BITMASK; 278 } 279 } 280 } 281 282 /* 283 ****************************************************************************************************** 284 **函数名称: BitFlag UART_CHK_LSR(uint8 COM, uint8 Bit) ** 285 **函数描述:检查LSR中的某位是为0还是为1 ** 286 **参 数: COM--------串口: 0,1,2,3 ** 287 ** Bit--------------LSR寄存器中的某位 ** 288 **返 回: RESET:该位为0 SET:该位为1 ** 289 ****************************************************************************************************** 290 */ 291 BitFlag UART_CHK_LSR(uint8 COM, uint8 Bit) 292 { 293 uint8 REG_LSR; 294 295 //找出对应串口的LSR值. 296 if(COM==UART1) { REG_LSR = LPC_UART1->LSR; } 297 else { REG_LSR = LPC_UART(COM)->LSR; } 298 299 //判断LSR中的该位是为0还是为1. 300 if (REG_LSR & Bit){ return SET; } 301 else { return RESET; } 302 } 303 304 /* 305 ****************************************************************************************************** 306 **函数名称: uint32 UART_GET_IIR(uint8 COM) ** 307 **函数描述:读取串口IIR寄存器的值 ** 308 **参 数: COM--------串口: 0,1,2,3 ** 309 **返 回: 寄存器的值 ** 310 ****************************************************************************************************** 311 */ 312 uint32 UART_GET_IIR(uint8 COM) 313 { 314 if(COM==UART1) 315 { 316 return (LPC_UART1->IIR & IIR_BITMASK); 317 } 318 else 319 { 320 return (LPC_UART(COM)->IIR & IIR_BITMASK); 321 } 322 323 } 324 325 /* 326 ****************************************************************************************************** 327 **函数名称: void UART_Send(uint8 COM, uint8 Data) ** 328 **函数描述:串口UART发送一个字节 ** 329 **参 数: COM--------串口: 0,1,2,3 ** 330 ** Data---待发送字节 ** 331 **返 回: 无 ** 332 ****************************************************************************************************** 333 */ 334 void UART_Send(uint8 COM, uint8 Data) 335 { 336 337 if(COM==UART1) 338 { 339 LPC_UART1->THR = Data; 340 } 341 else 342 { 343 LPC_UART(COM)->THR = Data; 344 } 345 } 346 347 /* 348 ****************************************************************************************************** 349 **函数名称: uint16 UART_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) ** 350 **函数描述:串口UART发送多个字节(供外部文件调用) ** 351 **参 数: COM---------串口: 0,1,2,3 ** 352 ** txbuf-------数据指针,指向发送缓冲区 ** 353 ** len---------待发送字节数 ** 354 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 355 **返 回: bSent---成功发送字节数 ** 356 ****************************************************************************************************** 357 */ 358 uint16 UART_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) 359 { 360 uint16 bSent=0; 361 362 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据. 363 364 while(len--) 365 { 366 UART_Send(COM, (*txbuf++)); 367 while(UART_CHK_LSR(COM,LSR_TEMT)==RESET); //等待THR和TSR为空,即发送数据完成. 368 bSent++; 369 } 370 371 RS485_EN(COM, RESET, USE_RS485); //RS485收发使能信号---RST_x为低---接收数据. 372 373 return(bSent); 374 } 375 376 /* 377 ****************************************************************************************************** 378 **函数名称: uint16 UART_SendStrings(uint8 COM, char *txbuf, State USE_RS485) ** 379 **函数描述:串口UART发送字符串(供外部文件调用) ** 380 **参 数: COM---------串口: 0,1,2,3 ** 381 ** txbuf-------数据指针,指向发送缓冲区 ** 382 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 383 **返 回: bSent---成功发送字节数 ** 384 ****************************************************************************************************** 385 */ 386 uint16 UART_SendStrings(uint8 COM, char *txbuf, State USE_RS485) 387 { 388 uint16 bSent=0; 389 390 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据. 391 392 while(*txbuf != ‘\0‘) 393 { 394 UART_Send(COM, (*txbuf++)); 395 while(UART_CHK_LSR(COM,LSR_TEMT)==RESET); //等待THR和TSR为空,即发送数据完成. 396 bSent++; 397 } 398 399 RS485_EN(COM, RESET, USE_RS485); //RS485收发使能信号---RST_x为低---接收数据. 400 401 return(bSent); 402 } 403 404 /* 405 ****************************************************************************************************** 406 **函数名称: void UART_IRQ_Send(uint8 COM, State USE_RS485) ** 407 **函数描述:串口UART中断发送多个字节(供中断服务程序调用) ** 408 **参 数: COM---------串口: 0,1,2,3 ** 409 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 410 **返 回: 无 ** 411 ****************************************************************************************************** 412 */ 413 void UART_IRQ_Send(uint8 COM, State USE_RS485) 414 { 415 uint8 FIFO_CNT; 416 uart_info *UART_INFO; 417 418 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据. 419 UART_IRQ_CFG(COM, IRQ_THRE, DISABLE); //关闭串口THRE发送中断. 420 421 while(UART_CHK_LSR(COM,LSR_THRE) == RESET); //等待THR为空. 422 UART_INFO = BUF_SELECT(COM); //选择对应的串口信息结构. 423 424 FIFO_CNT = TX_FIFO_SIZE; 425 while(UART_INFO->TX_len && FIFO_CNT) //最多可连续快速向TX_FIFO写入16个字节的数据! 426 { 427 UART_Send(COM, UART_INFO->TX_Buffer[UART_INFO->TX_cnt]); 428 UART_INFO->TX_cnt++; 429 UART_INFO->TX_len--; 430 FIFO_CNT--; 431 } 432 433 //如果还有数据未发送完,则使能串口中断。反之,则关闭串口中断. 434 if(UART_CHK_LSR(COM,LSR_THRE) == RESET) //THR不为空. 435 { 436 UART_IRQ_CFG(COM, IRQ_THRE, ENABLE); //使能串口发送中断. 437 UART_INFO->TX_OK = FALSE; 438 } 439 else 440 { 441 UART_IRQ_CFG(COM, IRQ_THRE, DISABLE); //关闭串口发送中断. 442 UART_INFO->TX_OK=TRUE; 443 UART_INFO->TX_cnt=0; 444 UART_INFO->TX_len=0; 445 446 while(UART_CHK_LSR(COM,LSR_TEMT)==RESET); //等待THR和TSR为空,即最后一个数据发送完成(已移出TSR). 447 RS485_EN(COM, RESET, USE_RS485); //RS485收发使能信号---RST_x为低---接收数据. 448 } 449 } 450 451 /* 452 ****************************************************************************************************** 453 **函数名称: void UART_IRQ_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) ** 454 **函数描述:串口UART中断发送多个字节(供外部文件调用) ** 455 **参 数: COM---------串口: 0,1,2,3 ** 456 ** txbuf-------数据指针,指向发送缓冲区 ** 457 ** len---------待发送字节数 ** 458 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 459 **返 回: ERR---发送失败 OK---发送成功 ** 460 ****************************************************************************************************** 461 */ 462 void UART_IRQ_SendBytes(uint8 COM, uint8 *txbuf, uint16 len, State USE_RS485) 463 { 464 uart_info *UART_INFO; 465 466 UART_INFO = BUF_SELECT(COM); //选择对应的串口信息结构. 467 while(!UART_INFO->TX_OK); //等待串口空闲. 468 469 memcpy(UART_INFO->TX_Buffer, txbuf, len); //复制等待发送的数据到发送缓冲区. 470 UART_INFO->TX_len=len; 471 UART_INFO->TX_cnt=0; 472 UART_INFO->TX_OK=FALSE; 473 474 UART_IRQ_Send(COM, USE_RS485); //将数据写到THR. 475 476 } 477 478 /* 479 ****************************************************************************************************** 480 **函数名称: void UART_IRQ_SendStrings(uint8 COM, char *txbuf, State USE_RS485) ** 481 **函数描述:串口UART中断发送字符串(供外部文件调用) ** 482 **参 数: COM---------串口: 0,1,2,3 ** 483 ** txbuf-------数据指针,指向发送缓冲区 ** 484 ** USE_RS485---DISABLE:不使能RS485_EN ENABLE:使能RS485_EN ** 485 **返 回: ERR---发送失败 OK---发送成功 ** 486 ****************************************************************************************************** 487 */ 488 void UART_IRQ_SendStrings(uint8 COM, char *txbuf, State USE_RS485) 489 { 490 uart_info *UART_INFO; 491 492 UART_INFO = BUF_SELECT(COM); //选择对应的串口信息结构. 493 while(!UART_INFO->TX_OK); //等待串口空闲. 494 495 strcpy((char *)(UART_INFO->TX_Buffer), txbuf); //复制等待发送的数据到发送缓冲区. 496 UART_INFO->TX_len=strlen(txbuf); 497 UART_INFO->TX_cnt=0; 498 UART_INFO->TX_OK=FALSE; 499 500 UART_IRQ_Send(COM, USE_RS485); //将数据写到THR. 501 502 } 503 504 /* 505 ****************************************************************************************************** 506 **函数名称: uint8 UART_Recv(uint8 COM) ** 507 **函数描述:串口UART接收一个字节 ** 508 **参 数: COM--------串口: 0,1,2,3 ** 509 **返 回: 接收到的数据 ** 510 ****************************************************************************************************** 511 */ 512 uint8 UART_Recv(uint8 COM) 513 { 514 515 if(COM==UART1) 516 { 517 return (LPC_UART1->RBR); 518 } 519 else 520 { 521 return (LPC_UART(COM)->RBR); 522 } 523 } 524 525 /* 526 ****************************************************************************************************** 527 **函数名称: void UART_IRQ_RecvBytes(uint8 COM, uint32 IIR_ID) ** 528 **函数描述:串口UART中断接收多个字节(供中断服务程序调用) ** 529 **参 数: COM--------串口: 0,1,2,3 ** 530 ** IIR_ID-----中断标识:IIR_RDA或IIR_CTI ** 531 **返 回: 无 ** 532 ****************************************************************************************************** 533 */ 534 void UART_IRQ_RecvBytes(uint8 COM, uint32 IIR_ID) 535 { 536 uint8 cnt; 537 uart_info *UART_INFO; 538 539 UART_IRQ_CFG(COM, IRQ_RBR, DISABLE); //关闭串口接收中断. 540 UART_INFO = BUF_SELECT(COM); //选择对应的串口信息结构. 541 542 switch(IIR_ID) 543 { 544 //接收数据可用中断---实际有RX_FIFO_SIZE个字节,但只读取RX_FIFO_SIZE-1个字节,对于刚好是RX_FIFO_SIZE的整数倍个数据时,留1字节产生CTI中断!否则无法创建RX_OK标致! 545 case IIR_RDA: 546 for (cnt=0; cnt<(RX_FIFO_SIZE-1); cnt++) 547 { 548 UART_INFO->RX_Buffer[UART_INFO->RX_cnt] = UART_Recv(COM); 549 UART_INFO->RX_cnt++; 550 } 551 break; 552 //字符超时中断. 553 case IIR_CTI: 554 while(UART_CHK_LSR(COM,LSR_RDR)==SET) //判断FIFO中是否还包仿有效数据,有则继续读取. 555 { 556 UART_INFO->RX_Buffer[UART_INFO->RX_cnt] = UART_Recv(COM); 557 UART_INFO->RX_cnt++; 558 } 559 UART_INFO->RX_len = UART_INFO->RX_cnt; 560 UART_INFO->RX_OK = TRUE; //串口接收完成标志置位. 561 break; 562 } 563 564 UART_IRQ_CFG(COM, IRQ_RBR, ENABLE); //使能串口接收中断. 565 } 566 567 /* 568 ****************************************************************************************************** 569 **函数名称: void UART_IRQ_SERVICE(uint8 COM) ** 570 **函数描述:串口中断服务程序回调函数 ** 571 **参 数: COM--------串口: 0,1,2,3 ** 572 **返 回: 无 ** 573 ****************************************************************************************************** 574 */ 575 void UART_IRQ_SERVICE(uint8 COM) 576 { 577 uint32 IIR_ID; 578 579 IIR_ID = UART_GET_IIR(COM) & IIR_MASK; 580 581 //接收线状态中断---本例不作处理,也没有使能该中断. 582 583 /****处理程序****/ 584 585 //接收数据中断 586 if((IIR_ID == IIR_RDA) || (IIR_ID == IIR_CTI)) 587 { 588 UART_IRQ_RecvBytes(COM, IIR_ID); 589 } 590 591 //发送数据中断 592 if(IIR_ID == IIR_THRE) 593 { 594 UART_IRQ_Send(COM, ENABLE); 595 } 596 } 597 598 /* 599 ****************************************************************************************************** 600 **函数名称: void UART0_IRQHandler(void) ** 601 **函数描述:UART0中断服务程序 ** 602 **参 数: 无 ** 603 **返 回: 无 ** 604 ****************************************************************************************************** 605 */ 606 void UART0_IRQHandler(void) 607 { 608 609 UART_IRQ_SERVICE(UART0); 610 611 } 612 613 /* 614 ****************************************************************************************************** 615 **函数名称: void UART1_IRQHandler(void) ** 616 **函数描述:UART1中断服务程序 ** 617 **参 数: 无 ** 618 **返 回: 无 ** 619 ****************************************************************************************************** 620 */ 621 void UART1_IRQHandler(void) 622 { 623 624 UART_IRQ_SERVICE(UART1); 625 626 } 627 628 /* 629 ****************************************************************************************************** 630 **函数名称: void UART2_IRQHandler(void) ** 631 **函数描述:UART2中断服务程序 ** 632 **参 数: 无 ** 633 **返 回: 无 ** 634 ****************************************************************************************************** 635 */ 636 void UART2_IRQHandler(void) 637 { 638 639 UART_IRQ_SERVICE(UART2); 640 641 } 642 643 /* 644 ****************************************************************************************************** 645 **函数名称: void UART3_IRQHandler(void) ** 646 **函数描述:UART3中断服务程序 ** 647 **参 数: 无 ** 648 **返 回: 无 ** 649 ****************************************************************************************************** 650 */ 651 void UART3_IRQHandler(void) 652 { 653 654 UART_IRQ_SERVICE(UART3); 655 656 } 657 658 659 660 /* 661 ****************************************************************************************************** 662 ** 另类printf函数构造方法 ** 663 ****************************************************************************************************** 664 */ 665 666 /* 667 ****************************************************************************************************** 668 **函数名称: void UART_Printf(char *fmt,...) ** 669 **函数描述:UART0串口打印程序函数 ** 670 **参 数: *fmt---格式 ** 671 **返 回: 无 ** 672 ****************************************************************************************************** 673 */ 674 //构造此函数必须包含#include <stdarg.h>和#include <stdio.h>这两个头文件! 675 676 void UART_Printf(char *fmt,...) 677 { 678 679 va_list ap; 680 char string[1024]; //此处切勿用字符串指针!!!---用指针很容易死机!!! 681 682 va_start(ap,fmt); 683 vsprintf(string,fmt,ap); 684 685 //中断方式发送 686 UART_IRQ_SendStrings(UART0,string,ENABLE); //串口UART0发送字符串函数---须自行构造! 687 688 //非中断方式发送 689 //UART_SendStrings(UART0,string,ENABLE); //串口UART0发送字符串函数---须自行构造! 690 691 va_end(ap); 692 } 693 694 /* 695 ****************************************************************************************************** 696 ** End Of File ** 697 ****************************************************************************************************** 698 */
时间: 2024-11-07 07:48:52