首页 > 代码库 > 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)最全面驱动程序