一、USART框图
![](https://i-blog.csdnimg.cn/blog_migrate/76413e1d3d971943abdc030cfc085939.png)
功能引脚
TX:发送引脚,Usart1一般对应PA9。
RX:接收引脚,Usart1一般对应PA10。
SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。.
SCLK:发送器时钟输出引脚,这个引脚仅适用于同步模式。
nRTS:请求以发送(Request To Send),n 表示低电平有效。如果使能 RTS 流控制,当 USART 接 收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send),n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下 一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
![](https://i-blog.csdnimg.cn/blog_migrate/4136d673ad8a866b00473b383b74081b.png)
2. 数据寄存器
![](https://i-blog.csdnimg.cn/blog_migrate/463f49f60644521268863b32ade5f885.png)
USART 数据寄存器(USART_DR)只有低 9 位有效,并且第 9 位数据是否有效要取决于 USART 控制寄存器 1(USART_CR1)的 M 位设置,当 M 位为 0 时表示 8 位数据字长,当 M 位为 1 表示 9 位数据字长,我们一般使用 8 位数据字长。
![](https://i-blog.csdnimg.cn/blog_migrate/5edc6b25f173c45019592af66210668c.png)
TDR 和 RDR 都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。 USART 支持 DMA 传输,可以实现高速数据传输。
3. 控制寄存器
![](https://i-blog.csdnimg.cn/blog_migrate/08e32de45dff62f30ec3d8fa6a7e42dc.png)
a)字符发送配置步骤
1.通过在USART_CR1寄存器上置位UE位来激活USART。
2. 编程USART_CR1的M位来定义字长。
3. 在USART_CR2中编程停止位的位数。
4. 如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中的描述配置DMA寄存器。
5. 利用USART_BRR寄存器选择要求的波特率。
6. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
7. 把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。
8. 在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的传输结束。当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。
如果此时USART正在发送数据,对USART_DR寄存器的写操作把数据存进TDR寄存器,并在当前传输结束时把该数据复制进移位寄存器。
如果此时USART没有在发送数据,处于空闲状态,对USART_DR寄存器的写操作直接把数据放进移位寄存器,数据传输开始,TXE位立即被置起。
当一帧发送完成时(停止位发送后)并且设置了TXE位,TC位被置起,如果USART_CR1寄存器中的TCIE位被置起时,则会产生中断。
在USART_DR寄存器中写入了最后一个数据字后,在关闭USART模块之前或设置微控制器进入低功耗模式之前,必须先等待TC=1。
b)字符接收配置步骤
1. 将USART_CR1寄存器的UE置1来激活USART。
2. 编程USART_CR1的M位定义字长。
3. 在USART_CR2中编写停止位的个数。
4. 如果需多缓冲器通信,选择USART_CR3中的DMA使能位(DMAR)。按多缓冲器通信所要求的配置DMA寄存器。
5. 利用波特率寄存器USART_BRR选择希望的波特率。
6. 设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。
RXNE位被置位。它表明移位寄存器的内容被转移到RDR。换句话说,数据已经被接收并且可以被读出(包括与之有关的错误标志)。
如果RXNEIE位被设置,产生中断。
在接收期间如果检测到帧错误,噪音或溢出错误,错误标志将被置起。
在多缓冲器通信时,RXNE在每个字节接收后被置起,并由DMA对数据寄存器的读操作而清零。
在单缓冲器模式里,由软件读USART_DR寄存器完成对RXNE位清除。RXNE标志也可以通过对它写0来清除。RXNE位必须在下一字符接收结束前被清零,以避免溢出错误。
c)溢出错误
如果RXNE还没有被复位,又接收到一个字符,则发生溢出错误。数据只有当RXNE位被清零后才能从移位寄存器转移到RDR寄存器。RXNE标记是接收到每个字节后被置位的。如果下一个数据已被收到或先前DMA请求还没被服务时,RXNE标志仍是置起的,溢出错误产生。
当溢出错误产生时:
ORE位被置位。
RDR内容将不会丢失。读USART_DR寄存器仍能得到先前的数据。
移位寄存器中以前的内容将被覆盖。随后接收到的数据都将丢失。
如果RXNEIE位被设置或EIE和DMAR位都被设置,中断产生。
顺序执行对USART_SR和USART_DR寄存器的读操作,可复位ORE位。
注意: 当ORE位置位时,表明至少有1个数据已经丢失。有两种可能性:
如果RXNE=1,上一个有效数据还在接收寄存器RDR上,可以被读出。
如果RXNE=0,这意味着上一个有效数据已经被读走,RDR已经没有东西可读。当上一个有效数据在RDR中被读取的同时又接收到新的(也就是丢失的)数据时,此种情况可能发生。在读序列期间(在USART_SR寄存器读访问和USART_DR读访问之间)接收到新的数据,此种情况也可能发生。
![](https://i-blog.csdnimg.cn/blog_migrate/9adcf55dd66e0c3f679323de031fb1a3.png)
4. 小数波特率生成
接收器和发送器的波特率在USARTDIV的整数和小数寄存器中的值应设置成相同。
这里的是给外设的时钟(PCLK1用于USART2、3、4、5,PCLK2用于USART1),USARTDIV是一个无符号的定点数。这12位的值设置在USART_BRR寄存器。
注: 在写入USART_BRR之后,波特率计数器会被波特率寄存器的新值替换。因此,不要在通信进行中改变波特率寄存器的数值。
5. 中断控制
![](https://i-blog.csdnimg.cn/blog_migrate/f5025100cc20a1ea6abc6bde397f11df.png)
USART的各种中断事件被连接到同一个中断向量(见下图),有以下各种中断事件:
发送期间:发送完成、清除发送、发送数据寄存器空。
接收期间:空闲总线检测、溢出错误、接收数据寄存器非空、校验错误、LIN断开符号检测、噪音标志(仅在多缓冲器通信)和帧错误(仅在多缓冲器通信)。
如果设置了对应的使能控制位,这些事件就可以产生各自的中断。
![](https://i-blog.csdnimg.cn/blog_migrate/28acd75f14a3e1fa3c1a073629f45d6f.png)
串口(USART)框图的讲解 - wenshinlee - 博客园 (cnblogs.com)
二、实现USART1接收和发送数据
STM32CubeMX设置
![](https://i-blog.csdnimg.cn/blog_migrate/f18a11da787ef4571f11b2bb17750d17.png)
主函数
uint8_t StaMessages[] = "Please enter 10 characters:\r\n";
uint8_t RxBuffer[20];
int main(void)
{
/*其余代码省略*/
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Transmit_IT(&huart1 ,(uint8_t*)StaMessages,sizeof(StaMessages));
HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuffer,10);
while(1){}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
HAL_UART_Transmit(&huart1,(uint8_t*)RxBuffer,10,0xFFFF);
HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuffer,10);
}
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/503bc4d566b288e201a5394a1001a776.png)