MM32 UART中断通信

judy的头像
judy 发布于:周一, 10/23/2017 - 15:53 ,关键词:

UART(Universal Asynchronous Receiver and Transmitter)通用异步收发器(异步串行通信口)是MCU的一个重要的数字接口,市面上很多的传感器、通信模块等外围器件都采用了UART接口,同时工程师在软件开发调试过程中UART打印输出作为一种最直观的输出方式可以检查程序的运行情况,所以UART在MCU中的作用不言而喻。

首先普及一下并行通信、串行通信(同步通信和异步通信)两种通信方式的特点:
并行通信:并行通信是指数据的各个位同时传送,可以字或字节为单位并行进行。
-传输原理:数据各个位同时传输。
-优点:速度快,位数多
-缺点:占用引脚资源多,线路复杂,成本高

串行通信:串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度,其只需要少数几条线就可以在系统间交换信息。
-传输原理:数据按位顺序传输。
-优点:占用引脚资源少,传输线少
-缺点:速度相对较慢,耗时长

串行通信的通信方式又分为:同步通信和异步通信两种方式
同步通信:带时钟同步信号传输,发送方和接收方时钟需要建立连接,使双方的时钟
到完全同步。比如:SPI,IIC通信接口等。
异步通信:接收器和发送器使用各自的时钟,不带时钟同步信号。每一个字符要用起始位和停止位作为字符开始和结束的标志,以字符为单位的一个个地发送和接收。比如:UART通信接口等。

MM32系列MCU的通用异步收发器(UART)提供了一种灵活的方法与使用工业标准 NRZ 异步串行数据格式的外部设备之间进行全双工数据交换。UART 利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,以及调制解调器(CTS/RTS)操作。

有很多工程师在使用UART时,在设计PCB的UART接口时,一直对UART采用两线、三线、四线的问题一直都是很模糊情况,在这里我简单讲一下这个问题。

有些客户采用两线主要是单工模式,两线分别是:GND, TX 或者 RX,相当于MCU是做发送或者接收功能,将接收设备和发送设备共地,是要把参考电压调节成一致,避免接收设备和发送设备双方对高低电平的判断不一致的情况。

采用两线主要是双工模式,三线分别是:GND,TX,RX,接收设备和发送设备都是双向通信设备,且都有各自的供电电源,只需要将双方的基准电压调节一致就可以实现双方的串口通信功能,客户在使用ISP下载程序时一般都采用这种方式,预留一个三线接口。

采用四线主要是通信双方有一方需要为另一方提供电源,供另一方芯片运行,所以四线分别为:GND,TX,RX,VDD。
GND:共地,提供基准电压。
RX:接收数据串行输入。通过过采样技术来区别数据和噪音,从而恢复数据。
TX:发送数据串行输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。
VDD:供电源。

一般的通信模块还会有另外两个引脚在硬件流控模式中需要使用:
nCTS:清除发送,若是高电平,在当前数据传输结束时阻断下一次的数据发送。
nRTS:发送请求,若是低电平,表明 UART 准备好接收数据。

两个UART间的通信接线方法

MM32 UART中断通信

两个UART间的硬件流控
MM32 UART中断通信

UART特征:

字长可以通过编程 UART_CCR 寄存器中的 CHAR 位,选择 5 ~ 8 位。在起始位期间, TX 脚处于低电平,在停止位期间处于高电平。

空闲符号被视为完全由‘1’组成的一个完整的数据帧,后面跟着包含了数据的下一帧的开始位(‘1’的位数也包括了停止位的位数)。

断开符号被视为在一个帧周期内全部收到‘0’(包括停止位期间,也是‘0’)。在断开帧结束时,发送器再插入 1 或 2 个停止位(‘1’)来应答起始位。

发送和接收由一个共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟。

UART时序

MM32 UART中断通信

串口设置的步骤可分为如下几个流程:

1) 串口复位,GPIO复位
2) 串口时钟使能, GPIO 时钟使能
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
6) 编写中断处理函数

1、串口复位,GPIO复位

在系统开始配置外设时,建议先执行复位相对应的外设,然后重新配置该外设,使其达到自己所期望的工作模式。

UART_DeInit(UART1);//复位串口1
GPIO_DeInit(GPIOA);//复位GPIOA

2、串口时钟使能, GPIO 时钟使能

串口1(UART1)是挂载在 APB2 下面的外设,GPIOA的时钟是挂载在AHB上,所以使能函数为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);//使能UART1
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能GPIOA的时钟

3、GPIO 端口模式设置

在上一章节讲述了GPIO的使用,使用GPIO的UART功能需要配置端口复用功能,根据DS_MM32L073_Ver1.7手册表4.PA端口功能复用可知PA9和PA10的UART功能的复用配置AF1。
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
外设的GPIO配置:

MM32 UART中断通信

接下来的两段代码就是将 TX(PA9)设置为推挽复用输出模式,将 RX(PA10)设置为浮空输入模式:
GPIO_InitTypeDef GPIO_InitStructure;
//UART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIOA.9

//UART1_RX GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化 GPIOA.10

4、串口参数初始化

4.1、分数波特率发生器

接收器和发送器的波特率在 BRR 的整数寄存器和 FRA 的小数寄存器中的值应设置成相同。
Tx/Rx 波特率 = fCK /(16 *UARTDIV )

这里的 fCK 是给外设的时钟(PCLK1 用于 UART2, PCLK2 用于 UART1)。UARTDIV 是一个无符号的定点数。这 16 位的值设置在 UART_BRR 寄存器。

例:如果BaudRate=9600,PCLK2=72MHz
则UARTDIV= 468.75

4.2、字长配置

字长可以通过编程 UART_CCR 寄存器中的 CHAR 位,选择 5 ~ 8 位。

4.3、奇偶校验位

奇偶控制(发送时生成一个奇偶位,接收时进行奇偶校验)可以通过设置 UART_CCR 寄存器上的 PEN位而激活。如果奇偶校验出错,无效数据不会从移位寄存器传送到 UART_RDR 寄存器。

偶校验:校验位使得一帧中的数据以及校验位中‘1’的个数为偶数。

例如:数据 = 00110101,有 4 个‘1’,如果选择偶校验(在 UART_CCR 中的 PSEL = 0),校验位将是‘0’。

奇校验:此校验位使得一帧中的数据以及校验位中‘1’的个数为奇数。

例如:数据=00110101,有 4 个‘1’,如果选择奇校验(在 UART_CCR 中的 PSEL = 1),校验位将是‘1’。

传输模式:如果 UART_CCR 的 PEN 位被置位,写进数据寄存器的数据的 MSB 位被校验位替换后发送出去(如果选择偶校验偶数个‘1’,如果选择奇校验奇数个‘1’)。如果奇偶校验失败, UART_ISR 寄存器中的 RXPERR_INTF 标志被置‘1’,并且如果 RXPERREN 在被预先设置的话,中断产生。

4.4、硬件数据流流控

RTS 流控制

如果 RTS 流控制被使能,只要 UART 接收器准备好接收新的数据, nRTS 就变成有效(接低电平)。当接收寄存器内有数据到达时, nRTS 被释放,由此表明希望在当前帧结束时停止数据传输。下图是一个启用 RTS 流控制的通信的例子。

MM32 UART中断通信

CTS 流控制

如果 CTS 流控制被使能,发送器在发送下一帧前检查 nCTS 输入。如果 nCTS 有效(被拉成低电平),则下一个数据被发送(假设那个数据是准备发送的),否则下一帧数据不被发出去。若 nCTS 在传输期间被变成无效,当前的传输完成后停止发送。下图是一个 CTS 流控制被启用的通信的例子。

MM32 UART中断通信

UART_InitTypeDef UART_InitStructure;
UART_InitStructure.UART_BaudRate = 115200;//波特率设置
UART_InitStructure.UART_WordLength= UART_WordLength_8b;//字长为8
UART_InitStructure.UART_StopBits = UART_StopBits_1;//一个停止位
UART_InitStructure.UART_Parity = UART_Parity_No;//无奇偶校验位
UART_InitStructure.UART_HardwareFlowControl=UART_HardwareFlowControl_None;//无硬件数据流流控
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//开启收发模式
UART_Init(UART1, &UART_InitStructure); //初始化串口
UART_Cmd(UART1, ENABLE); //UART1使能

4.5、开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)

NVIC_InitTypeDef NVIC_InitStructure;
UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);//开启串口接收中断
NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

4.6、编写中断处理函数

void UART1_IRQHandler(void) //中断服务函数
{
u8 Res;
if(UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET) //接收中断产生
{
UART_ClearITPendingBit(UART1,UART_IT_RXIEN);//清中断标志
Res =UART_ReceiveData(UART1);
UART_SendData (Res);
}
}

按照上述配置完成后,在main函数中将上述函数调用,将程序下载到MiniBorad中,打开串口助手,在对话框中输入您需要输入的内容,MCU的UART将您发送的数据转发并且打印在串口助手对话框,可以在显示串口看到您输入的内容。打印结果如下图所示:

MM32 UART中断通信

转自: 灵动微电子

围观 672