STM32——串口通信

STM32——串口通信


宗旨:技术的学习是有限的,分享的精神的无限的。


一、异步串口通信协议

        STM32 的串口非常强大,它不仅支持最基本的通用串口同步、异步通信,还具有 LIN 总线功能(局域互联网)、IRDA 功能(红外通信)、SmartCard 功能。一般我们利用串口打印调试信息。

STM32——串口通信_第1张图片

 

二、串口工作过程分析

        我们只需要大概了解串口发送的过程即可。从下至上,我们看到串口外设主要由三个部分组成,分别是波特率控制、收发控制和数据存储转移。

1、 波特率

        波特率,即每秒传输的二进制位数,用 b/s (bps)表示,通过对时钟的控制可以改变波特率。在配置波特率时,我们向波特比率寄存器 USART_BRR 写入参数,修改了串口时钟 的分 频 值USARTDIV 。USART_BRR 寄存 器 包括 两 部分 , 分别 是 DIV_Mantissa(USARTDIV 的整数部分)和 DIV_Fraction(USARTDIV 的小数)部分,最终,计算公式为 USARTDIV=DIV_Mantissa+(DIV_Fraction/16)。

USARTDIV 是对串口外设的时钟源进行分频的,对于 USART1,由于它挂载在 APB2总线上,所以它的时钟源为 f PCLK2 ;而 USART2、3 挂载在 APB1 上,时钟源则为 fPCLK1,串口的时钟源经过 USARTDIV 分频后分别输出作为发送器时钟及接收器时钟,控制发送和接收的时序。

2、 收发控制

        寄存器 :CR1、CR2、CR3 和 SR,即USART 的三个控制寄存器(Control Register)及一个状态寄存器(Status Register)。通过向寄存器写入各种控制参数来控制发送和接收,如奇偶校验位、停止位等,还包括对USART 中断的控制;串口的状态在任何时候都可以从状态寄存器中查询得到。具体的控制和状态检查,我们都是使用库函数来实现的。

3、 数据存储转移

        收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。当我们需要发送数据时,内核或 DMA 外设(一种数据传输方式,在后面介绍)把数据从内存(变量)写入到发送数据寄存器 TDR 后,发送控制器将适时地自动把数据从 TDR 加载到发送移位寄存器,然后通过串口线 Tx,把数据一位一位地发送出去,当数据从 TDR转移到移位寄存器时,会产生发送寄存器 TDR 已空事件 TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件 TC,这些事件可以在状态寄存器中查询到。

而接收数据则是一个逆过程,数据从串口线 Rx 一位一位地输入到接收移位寄存器,然后自动地转移到接收数据寄存器 RDR,最后用内核指令或 DMA

 

三、UART

串口配置流程:

(1)      使能串口1的时钟

(2)      配置串口1的I/O

(3)      配置串口1的工作模式,具体为波特率为 115200 、8 个数据位、1 个停止位、无硬件流控制。即 115200 8-N-1。

void USART1_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure; // 串口IO结构体
  USART_InitTypeDef USART_InitStructure;

  /* 配置串口时钟 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

  /* TX --PA9 -- 通用推挽式输出 -- 50MHZ */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* RX --PA10 -- 输入*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* 串口初始化 -- 115200-8-1 */
  USART_InitStructure.USART_BaudRate = 115200; // 波特率115200
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
  USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位
  USART_InitStructure.USART_Parity = USART_Parity_No ; // 无奇偶校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowC ontrol_None; // 无硬件流
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 配置串口的模式。为了配置双线全双工通信,需要把 Rx 和 Tx 模式都开启。
  USART_Init(USART1, &USART_InitStructure); // 填充完结构体, 向寄存器写入配置参数
  USART_Cmd(USART1, ENABLE); // 使能 USART1 外设
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

        要想 printf() 函数工作的话,我们需要把 printf() 重新定向到串口中。为了实现重定向 printf() 函数,我们需要重写 fputc() 这个 C 标准库函数,因为 printf()在C 标准库函数中实质是一个宏,最终是调用了 fputc() 这个函数。

// 重定向到串口
int fputc(int ch, FILE *f)
{
  /* 发送一个字节数据到 串口 */
  USART_SendData(USART1, (uint8_t) ch);

  /* 等待发送完毕 */
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

  return (ch);
}

你可能感兴趣的:(异步,stm32,串口通信,stm32串口通信)