LPC17XX 串口接收发送中断(含RS485)最全面驱动程序
** 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); 180181/*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); 192193/*194****************************************************************************************************** 195**函数名称: void UART_Printf(char *fmt,...) ** 196**函数描述:UART0串口打印程序函数 ** 197**参 数: *fmt---格式 ** 198**返 回: 无 ** 199****************************************************************************************************** 200*/201//构造此函数必须包含#include
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 54if(COM == UART0){ UART_INFO = &UART[0]; } 55if(COM == UART1){ UART_INFO = &UART[1]; } 56if(COM == UART2){ UART_INFO = &UART[2]; } 57if(COM == UART3){ UART_INFO = &UART[3]; } 58 59return(UART_INFO); 60} 61 62/* 63****************************************************************************************************** 64**函数名称: UART_IO_INIT(uint8 COM) ** 65**函数描述:所有串口IO初始化---RTS根据自己的实际情况修改! ** 66**参 数: COM--------串口: 0,1,2,3 ** 67**返 回: 无 ** 68****************************************************************************************************** 69*/ 70void UART_IO_INIT(uint8 COM) 71{ 72if(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 81if(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 90if(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 } 99100if(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} 110111/*112****************************************************************************************************** 113**函数名称: void Set_Baudrate(uint32 BaudRate, uint16 *V_DL, uint8 *V_FDR) ** 114**函数描述:设置精准的波特率(带小数分频寄存器的设定) ** 115**参 数: 入参---BaudRate 出参指针---*V_DL、*V_FDR ** 116**返 回: 无 ** 117****************************************************************************************************** 118*/119void 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)123124 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; 127128 divisor = (Fpclk>>4)*100/BaudRate; //求出最精确的除数值(取小数点后2位,即放大100倍)!129 best_error = 0xFFFFFFFF; 130131//查找最佳的DL(DLL和DLM)、divADDVAL和MULVAL值---此3个数值结合运算,结果最接近divisor值(误差最小)的数为最佳组合!132for(m=1; m<=15; m++) 133 { 134for(d=0; dRX_OK = FALSE; // 串口接收完成标志清零.174 UART_INFO->TX_OK = TRUE; // 串口发送完成标志置位.175176if(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接收中断,禁止发送中断.186187 NVIC_EnableIRQ(UART1_IRQn); // 使能LPC_UART1串口总中断,中断优先级默认!188 } 189else190 { 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接收中断,禁止发送中断. 199200201if(COM == UART0) // 使能LPC_UARTx串口总中断,中断优先级默认!202 {NVIC_EnableIRQ(UART0_IRQn);} 203if(COM == UART2) 204 {NVIC_EnableIRQ(UART2_IRQn);} 205if(COM == UART3) 206 {NVIC_EnableIRQ(UART3_IRQn);} 207 } 208} 209210/*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*/220void RS485_EN(uint8 COM, BitFlag Bit, State USE_RS485) 221{ 222if(USE_RS485) 223 { 224if(COM == UART0){ RTS_0(Bit); } 225if(COM == UART1){ RTS_1(Bit); } 226if(COM == UART2){ RTS_2(Bit); } 227if(COM == UART3){ RTS_3(Bit); } 228 } 229} 230231/*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*/241void UART_IRQ_CFG(uint8 COM, IRQ_TYPE IRQ, State NewState) 242{ 243 uint32 temp=0; 244245//先判断中断类型.246switch(IRQ) 247 { 248case IRQ_RBR: 249 temp = IER_RBR; 250break; 251252case IRQ_THRE: 253 temp = IER_THRE; 254break; 255 } 256257//再判断使能状况.258if (NewState == ENABLE) 259 { 260if(COM==UART1) 261 { 262 LPC_UART1->IER |= temp; 263 } 264else265 { 266 LPC_UART(COM)->IER |= temp; 267 } 268 } 269else270 { 271if(COM==UART1) 272 { 273 LPC_UART1->IER &= (~temp) & IER1_BITMASK; 274 } 275else276 { 277 LPC_UART(COM)->IER &= (~temp) & IER_BITMASK; 278 } 279 } 280} 281282/*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*/291BitFlag UART_CHK_LSR(uint8 COM, uint8 Bit) 292{ 293uint8 REG_LSR; 294295//找出对应串口的LSR值.296if(COM==UART1) { REG_LSR = LPC_UART1->LSR; } 297else { REG_LSR = LPC_UART(COM)->LSR; } 298299//判断LSR中的该位是为0还是为1.300if (REG_LSR & Bit){ return SET; } 301else { return RESET; } 302} 303304/*305****************************************************************************************************** 306**函数名称: uint32 UART_GET_IIR(uint8 COM) ** 307**函数描述:读取串口IIR寄存器的值 ** 308**参 数: COM--------串口: 0,1,2,3 ** 309**返 回: 寄存器的值 ** 310****************************************************************************************************** 311*/312uint32 UART_GET_IIR(uint8 COM) 313{ 314if(COM==UART1) 315 { 316return (LPC_UART1->IIR & IIR_BITMASK); 317 } 318else319 { 320return (LPC_UART(COM)->IIR & IIR_BITMASK); 321 } 322323} 324325/*326****************************************************************************************************** 327**函数名称: void UART_Send(uint8 COM, uint8 Data) ** 328**函数描述:串口UART发送一个字节 ** 329**参 数: COM--------串口: 0,1,2,3 ** 330** Data---待发送字节 ** 331**返 回: 无 ** 332****************************************************************************************************** 333*/334void UART_Send(uint8 COM, uint8 Data) 335{ 336337if(COM==UART1) 338 { 339 LPC_UART1->THR = Data; 340 } 341else342 { 343 LPC_UART(COM)->THR = Data; 344 } 345} 346347/*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; 361362 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据.363364while(len--) 365 { 366 UART_Send(COM, (*txbuf++)); 367while(UART_CHK_LSR(COM,LSR_TEMT)==RESET); //等待THR和TSR为空,即发送数据完成.368 bSent++; 369 } 370371 RS485_EN(COM, RESET, USE_RS485); //RS485收发使能信号---RST_x为低---接收数据.372373return(bSent); 374} 375376/*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; 389390 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据.391392while(*txbuf != ) 393 { 394 UART_Send(COM, (*txbuf++)); 395while(UART_CHK_LSR(COM,LSR_TEMT)==RESET); //等待THR和TSR为空,即发送数据完成.396 bSent++; 397 } 398399 RS485_EN(COM, RESET, USE_RS485); //RS485收发使能信号---RST_x为低---接收数据.400401return(bSent); 402} 403404/*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*/413void UART_IRQ_Send(uint8 COM, State USE_RS485) 414{ 415uint8 FIFO_CNT; 416 uart_info *UART_INFO; 417418 RS485_EN(COM, SET, USE_RS485); //RS485收发使能信号---RST_x为高---发送数据.419 UART_IRQ_CFG(COM, IRQ_THRE, DISABLE); //关闭串口THRE发送中断.420421while(UART_CHK_LSR(COM,LSR_THRE) == RESET); //等待THR为空. 422 UART_INFO = BUF_SELECT(COM); //选择对应的串口信息结构. 423424 FIFO_CNT = TX_FIFO_SIZE; 425while(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--; LPC17XX串口接收发送中断RS48 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
