STM32-UART串口应用

通信的基本概念

同步通信

一般情况下同步通信指的是通信双方根据同步信号进行通信的方式。比如通信双方有一个共同的时钟信号,大家根据时钟信号的变化进行通信,如SPI、I2C等。

     

异步通信

是指数据传输速度匹配依赖于通信双方有自己独立的系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步,例如UART。

串行通信

指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。优点:占用引脚资源少。缺点:传输速度相对较慢。

并行通信

指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行。优点:速度快。缺点:占用引脚资源多。

通信模式

单工:要么收,要么发,只能做接收设备或者发送设备。比如收音机
半双工:可以收,可以发,但是不能同时收发。比如对讲机
全双工:可以在同一时刻既接收,又发送。比如手机

 常见通信方式总结如下表所示:

通信标准

引脚说明

通信方式

通信方向

  UART

(通用异步收发器)

TXD:发送端

RXD:接收端

GND:公共地

异步通信

全双工

  单总线

1-wire)

DQ:发送/接收端

异步通信

半双工

SPI

SCK:同步时钟

MISO:主机输入,从机输出

MOSI:主机输出,从机输入

同步通信

全双工

I2C

SCL:同步时钟

SDA:数据输入/输出端

同步通信

半双工

USART基本概念

通用同步异步收发器(USART)灵活地与外部设备进行全双工数据通信,满足外部设备对工业标准NRZ异步串行数据格式的要求。USART通过小数波特率发生器提供了多种波特率。它支持同步单向通信和半双工单线通信;还支持LIN(局域互联网络),智能卡协议与IrDA(红外数据协会)SIR ENDEC规范,以及调制解调操作(CTS/RTS)。而且,它还支持多处理器通信。

USART持同步模式,因此USART 需要同步始终信号USART_CK(如STM32 单片机),通常情况同步信号很少使用,因此USART和一般单片机UART使用方式是一样的,都使用异步模式。

STM32F051串口

STM32F051芯片内置两个通用同步/异步收发器(USART1和USART2),通信速度可达6Mbit/s。其中USART1的发送和接收引脚分别为PA9、PA10,UART2的发送和接收引脚分别为PA14、PA15。

串口通信协议

UART串口通信协议有1个起始位、8-9位数据位、1位奇偶校验位(可选)及1-2位停止位。通信时低位先发送,一般情况下串口通信选择8N1,即8位数据位、无奇偶校验位、1位停止位。

波特率

在串行通信中,用“波特率”来描述数据的传输速率。所谓波特率,既每秒传送的二进制位数,其单位为bps(bits per second)。它是衡量串行数据速度快慢的重要指标。
国际上规定一个标准的波特率系列: 110、300、600、1200、1800、2400、4800、9600、115200、14.4Kbps、19.2Kbps、……
例如:115200bps、指每秒传送115200位。通信双方必须设置同样的同学速率才能正常通信。

USART寄存器及配置方法

控制寄存器(USART_CR1)

由于STM32F051的USART控制寄存器(USART_CR1)内容十分庞杂,所以这里仅介绍一些常用功能。

位12 M: 字长
        这个位决定串口字长。 由软件置1 和清零。
        0: 1 个起始位,8 位数据位
        1: 1 个起始位,9 个数据位
        这个位域只能在USART 未被使能的时候(UE=0)改写。

位 9 PS: 校验选择
        这个位选择在校验生成和检测功能被打开的时候(PCE=1)使用奇校验还是使用偶校验。 由软件置1 和清零。 校验方式会在当前字节结束后生效。
        0: 偶校验
        1: 奇校验
        这个位域只能在USART 未被使能的时候(UE=0)改写。

位 6 TCIE: 发送完毕中断使能
        由软件置1 和清零。
        0: 中断禁止
        1: 在USART_ISR 寄存器中的TC 位被置1 的时候会产生USART 中断

位 5 RXNEIE: 接收寄存器非空中断使能
        由软件置1 和清零。
        0: 中断禁止
        1: 在USART_ISR 寄存器中的ORE 或者RXNE 被置1 的时候会产生USART 中断。

位 0 UE: USART 使能
        当这个位被清零,USART 的预分频器和输出都立即停止,并且当前的操作也被取消。对USART 的设置都不会丢,但USART_ISR 中所有的状态标志都会被复位。由软件置1 和清零。
        0: USART 预分频器和输出关闭,低功耗模式
        1: USART 开启

控制寄存器(USART_CR2)

位 13:12 STOP[1:0]: 停止位
        这些位用来定制停止位的个数。
        00: 1 个停止位:
        01: 保留
        10: 2 个停止位:
        11: 1.5 个停止位
        这个位域只能在USART 未被使能的时候(UE=0)改写。

波特率寄存器(USART_BRR)

位31:16 保留,必须保持复位时的值。
位 15:4 DIV_Mantissa[11:0]: USARTDIV 的整数部分
        这12 位定义USART 分频器除法因子的整数部分
位 3:0 DIV_Fraction[3:0]: USARTDIV 的小数部分
        这4 位定义USART 分频器除法因子的小数部分,当OVER8=1时,DIV_Fraction3 位是没有用的,并且必须保持为0。

中断和状态寄存器(USART_ISR)

位 7 TXE: 发送数据寄存器空
        当USART_TDR 寄存器中的值被取到移位寄存器的同时,这个位被硬件置1。 再向USART_TDR 寄存器写数据就会同时清掉这个位。TXE 标志还可以用其它方式清除,例如向USART_RQR 寄存器的TXFRQ 位写1,为了丢弃数据(仅于智能卡模式T=0,传送失败的情形)。如果USART_CR1 寄存器中的TXEIE 位被置起时,则会产生中断。
        0: 没有数据被传到移位寄存器
        1: 有数据被传到移位寄存器,发送数据寄存器为空。

位 5 RXNE: 接收数据寄存器非空
        当接收移位寄存器的内容被传递到USART_RDR 寄存器中时,这个位被硬件置1。读取USART_TDR 寄存器的数据就会同时清掉这个位。 RXNE 标志也可以通过对USART_RQR 寄存器中的RXFRQ 位写1 来清除。如果USART_CR1 寄存器中的RXNEIE 位是1,就会产生中断请求。
        0: 没收到数据
        1: 收到的数据已经可读。

数据发送寄存器(USART_TDR) 

位31:9 保留,必须保持复位时的值。
位 8:0 TDR[8:0]: 发送数据的值
        用于写入要发送的数据字节。TDR 寄存器提供发送移位寄存器和内部总线间的并行接口(见图226)。当发送的时候设置了校验功能(USART_CR1 中的PCE=1),向最高位(位7 还是
位8 取决于设置的字长)写入的信息是无效的,因为它总是要被校验位代替了之后再去发送的。
        注: 这个寄存器只能在TXE=1 的时候才能做写操作。

数据接收寄存器(USART_RDR)

位31:9 保留,必须保持复位时的值。
位 8:0 RDR[8:0]: 接收数据的值
        包含所收到的字节。
        RDR 寄存器提供输入移位寄存器和内部总线间的并行接口(见图226)。
        当接收数据时打开了校验位,读这个寄存器得到的最高位是校验位。

STM32实现串口数据的收发

直接操作寄存器进行数据收发

 根据硬件原理图,在CubeMX上配置好串口UART1为异步模式,并将波特率设置为115200。

 生成工程后,通过直接操作寄存器控制UART进行数据收发的代码如下:

void Uart_Putchar(uint8_t ch) // 接收1个字节的数据
{
    while(!(USART1->ISR&(1<<7))); // 等待TXE置位
    USART1->TDR = ch;
}
uint8_t Uart_Getchar(void) // 发送1个字节的数据
{
    while(!(USART1->ISR&(1<<5))); // 等待RXNE置位
    return USART1->RDR;
}

应用HAL库函数进行数据收发

在ST公司提供的HAL库代码中,已经集成了UART串口收发的库函数,我们可以直接调用相应的函数操作串口,代码如下:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); // 串口发送数据
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); // 串口接收数据

其中huart是代表当前需要收发数据的串口的结构体指针,pData为即将接收/发送的数据首地址,Size为发送/接收的字节数,Timeout为最大阻塞时间(即阻塞Timeout毫秒后如果仍未响应则放弃本次操作,并继续执行后续代码)。代码示例如下:

uint8_t buf[32] = {0};
HAL_UART_Transmit(huart1, buf, sizeof(buf), 100); // 串口发送数据
HAL_UART_Receive(huart1, buf, sizeof(buf), 100); // 串口接收数据

应用C标准库的printf函数打印调试信息

printf函数调用的是c库中的fputc函数。因此我们如果重新写了fputc函数,就可以改变printf函数的功能,可以向串口打印输出。代码如下:

int fputc(int ch,FILE *f)
{
	while((USART1->ISR&(1<<7)) == 0);
	USART1->TDR=(uint8_t)ch;
	return ch;
} 

这样操作下来,就能通过printf函数向串口打印调试信息了。

注:本文仅由作者用于总结和记录学习ARM系列软件和Linux驱动开发的过程,未经允许请勿擅自转载,如有侵权请联系作者删除。

猜你喜欢

转载自blog.csdn.net/cotex_A9/article/details/125978490