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 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

NXP LPC17XX 串口接收发送中断(含RS485)最全面驱动程序的相关文章

stm32RS485串口通信——中断接收发送数据

功能:通过PC机的串口调试助手发送数据给串口A,串口B接收到串口A发送的数据,再由串口B将接收到的数据返回给PC机的串口调试助手. PC->串口A->串口B->PC. 实验平台:stm32f407 /********************************************************************* 本平台具有六个串口: com1  485 com2 com3  232 需一个管脚控制DTU com4 485 com5  调试串口  TTL com6

【转】搞定单片机多字节串口接收(串口多字节接收发送的高阶研究)

搞定单片机多字节串口接收(串口多字节接收发送的高阶研究) 原文地址:http://bbs.ednchina.com/BLOG_ARTICLE_3007162.HTM 工作了一年多,写了不少单片机串口程序.感觉串口多字节接收部分的逻辑相对于配置寄存器跟串口回复来说,是有点难度的——寄存器配置基本上都是死的,串口回复多字节跟回复一字节只是多了一个循环. 串口接收程序是基于串口中断的,单片机的串口每次接收到一字节数据产生一次中断,然后再读取某个寄存器就可以得到串口接收的数据了.然而在实际应用当中,基本

C#----串口数据接收发送

虚拟串口驱动工具,创建俩个虚拟串口,如图: 创建两个Console模拟串口的发送接收数据 C#串口数据接收发送,类空间: using System.IO.Ports; C# 串行端口 接收数据,代码如下: //遍历串行端口名称数组 foreach (string port in System.IO.Ports.SerialPort.GetPortNames()) { Console.WriteLine(port); } byte[] b = new byte[32]; SerialPort sp

stm32的串口接收字符串以十六进制数

#include "pbdata.h" uint8_t TxBuffer1[] = "USART Interrupt Example: This isUSART1 DEMO"; uint8_t RxBuffer1[],rec_f,tx_flag; volatile uint8_t TxCounter1 = 0x00; volatile uint8_t RxCounter1 = 0x00; uint32_t Rec_Len; int main(void) { u8 a

linux串口接收0x03等特殊字符的问题

近日在写一个linux的串口程序,发现大多数情况下数据接收没问题,但是有时却有问题.主要是接收的字符串中包含有0x03这个字符,会造成与它相邻的字符同时也接收不到,搞了好久才发现这个错误.查找资料后发现许多ARM板也存着这个问题,存在问题的字符串还包括0x13.0x0D等特殊含义的字符. 解决方法 方法比较简单,在接收数据前,对串口的文件描述符fd进行如下设置, <pre name="code" class="cpp">struct termios op

2018最新mfc作为上位机接收硬件端USB或串口数据显示成图片 解决串口接收数据丢字节丢包问题

本文用的是VS2013MFC写串口数据接收: 第一步:首先建立一个MFC工程,成功后会跳出一个对话框,直接在对话框上点击右键->点击插入ACTIVAE控件->选择MicrosoftCommunications Control, version 6.0 成功后会显示一个电话的图标在对话框上,运行起来不会显示的 不用担心这个美观问题.如果没有这个插件的话,可能是版本太低  可以自己下载一个补上 第二步:大概的窗体搞好:   那个显示图片的大框是PICTURE控件变量 然后就要项目->类向导中

STM32串口接收小结

STM32串口接收数据 稍微理一下思路,一个数据从电脑发送到STM32,然后在从STM32返回到电脑显示出来. 如上图所示,发送(1所示的路线)前,STM32的淳口需要初始化的设置.包括:波特率,字长,硬件流,停止位,奇偶校验位,模式(接收,发送,接收和发送),串口的基地址(Instance).在初始化串口的函数里面,需要调用到HAL_UART_MspInit(),这是一个虚函数(_weak),HAL_UART_MspInit()会调用到HAL_GPIO_Init(),把IO口进行配置.(模式,

AVR单片机教程——串口接收

上一讲中,我们实现了单片机开发板向电脑传输数据.在这一讲中,我们将通过电脑向单片机发送指令,让单片机根据指令控制LED.这一次,两端的TX与RX需要交叉连接,单片机TX连接串口工具RX也是需要的,因为程序会根据指令反馈信息. 为了简单起见,我们的程序只需要控制4个板载LED.指令包含两个字节:第一个字节为r.y.g.b中的一个,分别表示红.黄.绿.蓝灯:第二个字节为0或1,表示灯不亮或亮. 然而,a2这样的指令是没有意义的,却是可能出现的.即使用户已经熟悉了这8条指令,也可能会不小心打错.我们应

单片机多字节串口接收(转)

工作了一年多,写了不少单片机串口程序.感觉串口多字节接收部分的逻辑相对于配置寄存器跟串口回复来说,是有点难度的——寄存器配置基本上都是死的,串口回复多字节跟回复一字节只是多了一个循环. 串口接收程序是基于串口中断的,单片机的串口每次接收到一字节数据产生一次中断,然后再读取某个寄存器就可以得到串口接收的数据了.然而在实际应用当中,基本上不会有单字节接收的情况.一般都是基于一定串口通信协议的多字节通信.在422或者485通信中,还可能是一个主机(一般是计算机)带多个从机(相应的有单片机的板卡).这就