首页 > 代码库 > NXP LPC17XX 串口接收发送中断(含RS485)最全面驱动程序
NXP LPC17XX 串口接收发送中断(含RS485)最全面驱动程序
最近在做一个关于串口的项目,于是把之前的串口程序又拿了出来,重新优化了一下!
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 struct106 {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 else190 {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 else265 {266 LPC_UART(COM)->IER |= temp;267 }268 }269 else270 {271 if(COM==UART1)272 {273 LPC_UART1->IER &= (~temp) & IER1_BITMASK;274 }275 else276 {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 else319 {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 else342 {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 else440 {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 else520 {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 */
NXP LPC17XX 串口接收发送中断(含RS485)最全面驱动程序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。