你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 串口详解

[复制链接]
STMCU小助手 发布时间:2022-4-17 21:05
01、USART的特点
USART是通用异步收发传输器(UniversalAsynchronousReceiver/Transmitter),通常称作UART,是一种异步收发传输器,是设备间进行异步通信的关键模块。UART负责处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式;通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用两根信号线(Rx和Tx)就可以完成通信过程,因此也称为异步串行通信。

全双工异步通信。

小数波特率发生器系统,提供精确的波特率。

可配置的16倍过采样或8倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能。

可编程的数据字长度(8位或者9位);

可配置的停止位(支持1或者2位停止位);

可配置的使用DMA多缓冲器通信。

单独的发送器和接收器使能位。

检测标志:① 接受缓冲器  ②发送缓冲器空 ③传输结束标志

多个带标志的中断源。触发中断。

其他:校验控制,四个错误检测标志。

通信结构

64da5001ea7f81a28083c1cd86bb944c.png

02、USART简介
2.1、数据传输模型

1977cd0bcc091b8c312ea4a33b863b5c.png

2.2、帧结构

串口异步通信需要定义的参数

① 起始位

② 数据位(8位或者9位)

③ 奇偶校验位(第9位)

④ 停止位(1,15,2位)

⑤ 波特率设置

带奇偶校验的数据为就是9位

eb6f9d3c3694e60fb484985396bd61dd.png

1.数据包

串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。

2.波特率

由于异步通信中没有时钟信号,所以接收双方要约定好波特率,即每秒传输的码元个数,以便对信号进行解码,常见的波特率有4800、9600、115200等。STM32中波特率的设置通过串口初始化结构体来实现。

3.起始和停止信号

数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。STM32中起始和停止信号的设置也是通过串口初始化结构体来实现。

4.有效数据

有效数据规定了主题数据的长度,一般为8或9位,其在STM32中也是通过串口初始化结构体来实现的。

5.数据校验

在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无(noparity)。这些也都可以在串口初始化结构体中实现的。

2.3、波特率


3e627d64bae5a7b44019ad5fdf9505e7.png

OVER8,用于配置过采样,通常情况下,OVER8设置为0。

7843ff80095b38cd6e63233c463f3a09.png

如果时钟时84M

USARTDIV = 84000000/(115200*16) = 45.572

那么得到:

DIV_Fraction = 16*0.572 = 0x09;

DIV_Mantissa = 45 = 0x2D;

03、STM32的USART
根据STM32F207数据手册,STM32F207一共6个串口

00d99484cbe8d677c01519eaf62e9e10.png

下文我们以USART1为例讲解

从STM32F207数据手册的Table10. Alternate functionmapping图中看到USART1的对应管脚,下文我们选择PA9和PA10作为USART1的管脚。

9d5255e81468bc957360deec15d92bd9.png

04、代码配置
配置中断优先级。

  1.   /* Enable the USARTx Interrupt */
  2.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  3.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;
  4.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  5.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  6.   NVIC_Init(&NVIC_InitStructure);
复制代码

打开串口与相应的GPIO引脚,配置好相应串口信息与GPIO引脚的工作模式。

  1.   /* Enable GPIO clock */
  2.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  3.   /* Enable UART1 clock */
  4.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  5.   /* Connect PXx to USARTx_Tx*/
  6.   GPIO_PinAFConfig(GPIOA, 9, GPIO_AF_USART1);

  7.   /* Connect PXx to USARTx_Rx*/
  8.   GPIO_PinAFConfig(GPIOA, 10, GPIO_AF_USART1);

  9.   /* Configure USART Tx as alternate function  */
  10.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  11.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  12.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.   GPIO_Init(GPIOA, &GPIO_InitStructure);

  16.   /* Configure USART Rx as alternate function  */
  17.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  18.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);
复制代码

配置USART1。

  1.   USART_InitStructure.USART_BaudRate = 115200;//配置波特率
  2.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;//配置数据字长
  3.   USART_InitStructure.USART_StopBits = USART_StopBits_1;//配置停止位
  4.   USART_InitStructure.USART_Parity = USART_Parity_No;//配置校验位
  5.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//配置硬件流控制
  6.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//配置工作模式,收发一起

  7.   /* USART configuration */
  8.   USART_Init(USART1, &USART_InitStructure);// 完成串口的初始化配置
  9. 使能中断配置。

  10.   USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  11.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)
  12. 我们配置了发送传输完成中断和接收数据寄存器非空中断。我们可以配置很多类型中断,在ST提供的标准库函数中看到。

  13. /**
  14.   * @brief  Enables or disables the specified USART interrupts.
  15.   * @param  USARTx: where x can be 1, 2, 3, 4, 5 or 6 to select the USART or
  16.   *         UART peripheral.
  17.   * @param  USART_IT: specifies the USART interrupt sources to be enabled or disabled.
  18.   *          This parameter can be one of the following values:
  19.   *            @arg USART_IT_CTS:  CTS change interrupt
  20.   *            @arg USART_IT_LBD:  LIN Break detection interrupt
  21.   *            @arg USART_IT_TXE:  Transmit Data Register empty interrupt
  22.   *            @arg USART_IT_TC:   Transmission complete interrupt
  23.   *            @arg USART_IT_RXNE: Receive Data register not empty interrupt
  24.   *            @arg USART_IT_IDLE: Idle line detection interrupt
  25.   *            @arg USART_IT_PE:   Parity Error interrupt
  26.   *            @arg USART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)
  27.   * @param  NewState: new state of the specified USARTx interrupts.
  28.   *          This parameter can be: ENABLE or DISABLE.
  29.   * @retval None
  30.   */
复制代码

最后使能串口。
  1.   /* Enable USART */
  2.   USART_Cmd(USART1, ENABLE);
复制代码

main主函数,功能是LCD显示串口接收的10个字符(如果不是ascii码则不显示),串口倒序返回接收到的10个字节。

  1. int main(void)
  2. {
  3. /*省略初始化部分代码*/
  4.   while (1)
  5.   {
  6.     if(LCD_refresh_flg){
  7.       LCD_refresh_flg = 0;
  8.       LCD_ShowString(0,16,receive_data);
  9.       receive_num--;
  10.       USART_SendData(USART1, receive_data[receive_num--]);
  11.       send_flg = 1;
  12.     }
  13.   }
  14. }
复制代码

因为使能了中断,我们还需要编写中断函数。

  1. void USART1_IRQHandler(void)
  2. {
  3.   if(USART_GetFlagStatus(USART1, USART_FLAG_TC))
  4.   {
  5.     if(send_flg == 1){
  6.       if(receive_num==0){
  7.         USART_SendData(USART1, receive_data[receive_num]);
  8.         send_flg = 0;
  9.         receive_flg = 1;
  10.       }else{
  11.         USART_SendData(USART1, receive_data[receive_num--]);
  12.       }
  13.     }
  14.     USART_ClearFlag(USART1, USART_FLAG_TC);
  15.   }
  16.   if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
  17.   {
  18.     if((receive_flg)&&(send_flg == 0)){
  19.       receive_data[receive_num++] = USART_ReceiveData(USART1);
  20.       if(receive_num==10){
  21.         receive_flg = 0;
  22.         LCD_refresh_flg = 1;
  23.       }
  24.     }
  25.     USART_ClearFlag(USART1, USART_FLAG_RXNE);
  26.   }
  27. }
复制代码


下载验证

LCD显示屏可以显示接收的10个字符,且PC以100ms为间隔发送数据,发送977包收到977包回复,测试demo就够健壮,没有出现丢包。

dfae4faec397eb4df0fbe9e952cc35dc.png




收藏 评论0 发布时间:2022-4-17 21:05

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版