STM32开发入门之串口详解

发布时间:2022-12-26  

  一、通信接口

  处理器与外部设备通信的两种方式:

  并行通信:

  -传输原理:数据各个位同时传输。

  -优点:速度快

  -缺点:占用引脚资源多

  串行通信:

  -传输原理:数据按位顺序传输。

  -优点:占用引脚资源少

  -缺点:速度相对较慢


  串行通信,按照数据传送方向,分为:

  单工:

  数据传输只支持数据在一个方向上传输

  半双工:

  允许数据在两个方向上传输,但是,在某一时刻,只允许数

  据在一个方向上传输,它实际上是一种切换方向的单工通信;


  全双工:

  允许数据同时在两个方向上传输,因此,全双工通信是两个

  单工通信方式的结合,它要求发送设备和接收设备都有独立

  的接收和发送能力。

  串行通信的通信方式:

  **同步通信:**带时钟同步信号传输。

  如:SPI,IIC通信接口

  **异步通信:**不带时钟同步信号。

  如:UART(通用异步收发器),单总线

  常见的串行通信接口:


  二、STM32的串口通信接口

  UART:通用异步收发器(universal asynchronous receiver and transmitter)

  USART:通用同步异步收发器(universal synchronous asynchronous receiver and transmitter)

  其中:

  通用同步异步收发器(USART)

  小容量产品:是指闪存存储器容量在16K至32K字节之间的STM32F101xx、 STM32F102xx和STM32F103xx微控制器。

  中容量产品:是指闪存存储器容量在64K至128K字节之间的STM32F101xx、 STM32F102xx和STM32F103xx微控制器。

  大容量产品:是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

  互联型产品:是指STM32F105xx和STM32F107xx微控制器。

  除非特别说明,本章描述的模块适用于整个STM32F10xxx微控制器系列。

  我使用的是 STM32F105xx,所以是互联型产品,包含3个USART和2个UART。(USART1/USART2/USART3/UART4/UART5)

  三、UART异步通信方式引脚连接方法

  -RXD:数据输入引脚。数据接收。

  -TXD:数据发送引脚。数据发送。

  串口交叉线

  串口直通线

  四、UART异步通信方式特点

  ● 全双工的,异步通信

  ● NRZ标准格式

  ● 分数波特率发生器系统

  ─ 发送和接收共用的可编程波特率,最高达4.5Mbits/s

  ● 可编程数据字长度(8位或9位)

  ● 可配置的停止位-支持1或2个停止位

  ● LIN主发送同步断开符的能力以及LIN从检测断开符的能力

  ─ 当USART硬件配置成LIN时,生成13位断开符;检测10/11位断开符

  ● 发送方为同步传输提供时钟

  ● IRDA SIR 编码器解码器

  ─ 在正常模式下支持3/16位的持续时间

  ● 智能卡模拟功能

  ─ 智能卡接口支持ISO7816-3标准里定义的异步智能卡协议

  ─ 智能卡用到的0.5和1.5个停止位

  ● 单线半双工通信

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

  ─ 在SRAM里利用集中式DMA缓冲接收/发送字节

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

  ● 检测标志

  ─ 接收缓冲器满

  ─ 发送缓冲器空

  ─ 传输结束标志

  ● 校验控制

  ─ 发送校验位

  ─ 对接收数据进行校验

  ● 四个错误检测标志

  ─ 溢出错误

  ─ 噪音错误

  ─ 帧错误

  ─ 校验错误

  ● 10个带标志的中断源

  ─ CTS改变

  ─ LIN断开符检测

  ─ 发送数据寄存器空

  ─ 发送完成

  ─ 接收数据寄存器满

  ─ 检测到总线为空闲

  ─ 溢出错误

  ─ 帧错误

  ─ 噪音错误

  ─ 校验错误

  ● 多处理器通信 – 如果地址不匹配,则进入静默模式

  ● 从静默模式中唤醒(通过空闲总线检测或地址标志检测)

  ● 两种唤醒接收器的方式:地址位(MSB,第9位),总线空闲

  五、串口通信过程

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

  起始位

  数据位(8位或者9位)

  奇偶校验位(第9位)

  停止位(1,15,2位)

  波特率设置

  七、串口配置

  串口设置的一般步骤可以总结为如下几个步骤:

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

  2、串口复位

  3、GPIO端口模式设置

  4、串口参数初始化

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

  6、使能串口

  7、编写中断处理函数


  下面, 我们就简单介绍下这几个与串口基本配置直接相关的几个固件库函数。 这些函数和定义主要分布在 stm32f10x_usart.h 和stm32f10x_usart.c 文件中。

  1.串口时钟使能。 串口是挂载在 APB2 下面的外设,所以使能函数为:

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);


  2.串口复位。 当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。 复位的是在函数 USART_DeInit()中完成:

  void USART_DeInit(USART_TypeDef* USARTx);//串口复位


  比如我们要复位串口 1,方法为:

  USART_DeInit(USART1); //复位串口 1


  3.串口参数初始化。 串口初始化是通过 USART_Init()函数实现的,

  void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);


  这个函数的第一个入口参数是指定初始化的串口标号,这里选择 USART1。

  第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针, 这个结构体指针的成员变量用来设置串口的一些参数。 一般的实现格式为:


  USART_InitStructure.USART_BaudRate = bound; //波特率设置;

  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8  位数据格式

  USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

  USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

  USART_InitStructure.USART_HardwareFlowControl

  = USART_HardwareFlowControl_None; //无硬件数据流控制

  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口



  从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制,模式(收,发)。 我们可以根据需要设置这些参数。


  4.数据发送与接收。 STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。


  STM32 库函数操作 USART_DR 寄存器发送数据的函数是:


  void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

  通过该函数向串口寄存器 USART_DR 写入一个数据。


  STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:


  uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

  通过该函数可以读取串口接受到的数据。


  5.串口状态。 串口的状态可以通过状态寄存器 USART_SR 读取。 USART_SR 的各位描述如图 9.1.1 所示:

  这里我们关注一下两个位,第 5、 6 位 RXNE 和 TC。


  RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将该位清零,也可以向该位写 0,直接清除。


  TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式: 1)读 USART_SR,写USART_DR。 2)直接向该位写 0。


  状态寄存器的其他位我们这里就不做过多讲解,大家需要可以查看中文参考手册。


  在我们固件库函数里面,读取串口状态的函数是:


  FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t  USART_FLAG);

  这个函数的第二个入口参数非常关键, 它是标示我们要查看串口的哪种状态, 比如上面讲解的RXNE(读数据寄存器非空)以及 TC(发送完成)。例如我们要判断读寄存器是否非空(RXNE), 操作库函数的方法是:


  USART_GetFlagStatus(USART1, USART_FLAG_RXNE);

  我们要判断发送是否完成(TC),操作库函数的方法是:


  USART_GetFlagStatus(USART1, USART_FLAG_TC);

  这些标识号在 MDK 里面是通过宏定义定义的:


  #define USART_IT_PE ((uint16_t)0x0028)

  #define USART_IT_TXE ((uint16_t)0x0727)

  #define USART_IT_TC ((uint16_t)0x0626)

  #define USART_IT_RXNE ((uint16_t)0x0525)

  #define USART_IT_IDLE ((uint16_t)0x0424)

  #define USART_IT_LBD ((uint16_t)0x0846)

  #define USART_IT_CTS ((uint16_t)0x096A)

  #define USART_IT_ERR ((uint16_t)0x0060)

  #define USART_IT_ORE ((uint16_t)0x0360)

  #define USART_IT_NE ((uint16_t)0x0260)

  #define USART_IT_FE ((uint16_t)0x0160)

  6.串口使能。 串口使能是通过函数 USART_Cmd()来实现的,这个很容易理解,使用方法是:


  USART_Cmd(USART1, ENABLE); //使能串口

  7.开启串口响应中断。 有些时候当我们还需要开启串口中断,那么我们还需要使能串口中断,使能串口中断的函数是:


  void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,

  FunctionalState NewState)

  这个函数的第二个入口参数是标示使能串口的类型, 也就是使能哪种中断, 因为串口的中断类型有很多种。 比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是:


  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断

  我们在发送数据结束的时候(TC, 发送完成) 要产生中断,那么方法是:


  USART_ITConfig(USART1, USART_IT_TC, ENABLE);

  8.获取相应中断状态。 当我们使能了某个中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。 经常我们在中断处理函数中,要判断该中断是哪种中断,使用的函数是:


  ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)

  比如我们使能了串口发送完成中断,那么当中断发生了, 我们便可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是:


  USART_GetITStatus(USART1, USART_IT_TC)

  返回值是 SET,说明是串口发送完成中断发生。


  八、串口程序完整代码


  参看:USART串口通信配置


   #include "stm32f10x.h"


  u8 Uart1_Get_Flag = 0;


  // 串口初始化函数


  void My_USART1_Init(void)


  {


  GPIO_InitTypeDef GPIO_InitStrue;


  USART_InitTypeDef USART_InitStrue;


  NVIC_InitTypeDef NVIC_InitStrue;


  // 1,使能GPIOA,USART1时钟


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);


  // 2,设置PGIO工作模式-PA9 PA10复用为串口1


  GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出


  GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;//USART1_TX PA.9


  GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;


  GPIO_Init(GPIOA,&GPIO_InitStrue); //初始化 GPIOA.9


  GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入


  GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;//USART1_RX PA.10


  GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;


  GPIO_Init(GPIOA,&GPIO_InitStrue); //初始化 GPIOA.10


  // 3,串口1初始化配置


  USART_InitStrue.USART_BaudRate=115200;//波特率设置


  USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件数据流控制


  USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//收发模式


  USART_InitStrue.USART_Parity=USART_Parity_No; //无奇偶校验位


  USART_InitStrue.USART_StopBits=USART_StopBits_1; //一个停止位


  USART_InitStrue.USART_WordLength=USART_WordLength_8b;//字长为 8 位


  USART_Init(USART1,&USART_InitStrue);//初始化串口


  // 4,打开串口1


  USART_Cmd(USART1,ENABLE);//使能串口


  // 5,使能串口1中断-接收数据完成中断


  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断


  // 6,设置中断优先级-主函数中设置中断优先级分组


  NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;


  NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//IRQ 通道使能


  NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级 1


  NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子优先级 1


  NVIC_Init(&NVIC_InitStrue);//中断优先级初始化


  }


  void USART1_Puts(char * str)


  {


  while(*str)


  {


  USART_SendData(USART1, *str++);


  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);


  }


  }


  // 中断服务函数


  void USART1_IRQHandler(void)


  {


  u8 res;


  if(USART_GetITStatus(USART1,USART_IT_RXNE))// 接收到数据


  {


  USART_ClearITPendingBit(USART1,USART_IT_RXNE);


  res= USART_ReceiveData(USART1); // 获得串口1接收到的数据


  Uart1_Get_Flag=1;


  }


  }


  // 主函数


  int main(void)


  {


  // 设置中断优先级分组位2 - 2位抢占2位相应


  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


  // 调用函数 初始化USART1相关引脚配置


  My_USART1_Init();


  if (Uart1_Get_Flag){


  Uart1_Get_Flag = 0;


  USART1_Puts(res);


  }


  return 0;


  }


 }

  九、串口其他需要了解的


  串口相关寄存器


  上面串口部分其实基本上已经讲完了。


  但是我们用的库函数版本是3.5的。在串口配置中还要配置USART 时钟的。


  首先看下串口相关的寄存器:


  USART_SR 状态寄存器

  USART_DR 数据寄存器

  USART_BRR 波特率寄存器

  USART_CR1 控制寄存器

  具体的配置看STM32中文参考手册了解一下,直接用串口库函数就好了。


  十、串口操作相关库函数


  获取状态标志位函数-操作USART_SR寄存器


  // 获取状态标志位

  FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t  USART_FLAG);

  // 清除状态标志位

  void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);

  // 获取中断状态标志位

  ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);

  // 清除中断状态标志位

  void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

  接收发送数据函数-操作USART_DR寄存器


  // 发送数据到串口(通过写USART_DR寄存器发送数据)

  void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

  // 接收数据(从USART_DR寄存器读取接收到的数据)

  uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

  串口配置函数


  // 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能

  void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef*  USART_InitStruct);

  // 使能串口

  void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);

  // 使能相关中断

  void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,  FunctionalState NewState);

  我们用的库函数V3.5里面还有:

  串口复位


  void USART_DeInit(USART_TypeDef* USARTx)

  串口时钟的初始化:

  void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef*  USART_ClockInitStruct)

  串口通信DMA中断

  void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,  FunctionalState NewState)

  所以除了上述的串口配置,还可以添加如下的配置:


  USART_InitTypeDef USART_InitStrue;

  USART_ClockInitTypeDef USART_CLK_InitStrue;

  USART_InitStrue.USART_BaudRate = baud_rate;//波特率设置

  USART_InitStrue.USART_WordLength = USART_WordLength_8b;//字长为 8 位

  USART_InitStrue.USART_StopBits = USART_StopBits_1;//一个停止位

  USART_InitStrue.USART_Parity = USART_Parity_No ;//无奇偶校验位

  USART_InitStrue.USART_HardwareFlowControl =  USART_HardwareFlowControl_None;//无硬件数据流控制

  USART_InitStrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式

  USART_CLK_InitStrue.USART_Clock = USART_Clock_Disable;//USART 时钟失能

  USART_CLK_InitStrue.USART_CPOL = USART_CPOL_Low;//SCLK引脚上时钟输出的极性

  USART_CLK_InitStrue.USART_CPHA = USART_CPHA_2Edge;//SLCK引脚上时钟输出的相位

  USART_CLK_InitStrue.USART_LastBit = USART_LastBit_Disable;//是否在同步模式下

  USART_Init(USART1,&USART_InitStrue);//初始化串口

  USART_ClockInit(USART1, &USART_CLK_InitStrue);//初始化USART时

  PS:刚开始有点不太理解,为什么要用到串口时钟。


  回顾了一下上面讲到的:


  我使用的是 STM32F105xx,所以是互联型产品,包含3个USART和2个UART。(USART1/USART2/USART3/UART4/UART5)

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    没有蓝屏、只是黑屏闪烁/没有插卡迹象,可能是卡的格式有问题。 读卡器 用于向SD(TF)卡中拷贝待下载文件。 DGUS软件DGUS为迪文串口屏的开发配置软件,该软件为用户提供了工程管理、字库生成、图片转换、串口......
    of HAL_TIM_IRQHandler...:找到HAL_TIM_Period... 重定义定时器6的定时中断服务函数: Step4:编译运行,可以看到串口屏幕上每一秒输出一次“timer6......
    道这位同学在毕业答辩时,有没有被老师为难,当着这么多评委老师,来几盘扫雷,是不是很刺激。 系统的硬件:指南者开发板和4.2英寸的UATRT HMI串口屏组成,其实可以用最小的核心板,单片机外设也就用到了串口而已,但是要求使用开发......
    串口屏与stm32串口通信;串口屏与单片机的发送与接收一.串口向单片机发送(使用串口屏和上位机软件USART HMI)1.波特率初始化2.按钮控件 printh 01二.单片机接收串口屏数据与发送给串口屏......
    示屏在工作时只需占用2个GPIO口,所以该器件很有特色,图1是其显示效果。 图1OLED屏显示效果 在STM32F103开发板所配的光盘中,也有OLED屏显示例程但它是并口屏,并与OV7670摄像......
    工业一体全国产方案,米尔T113核心板79起; 入门级HMI屏作为嵌入式系统中重要组成部分,大部分都是串口屏;其功能简单、成本低等特点,使用历史悠久、应用广泛,而随着信息技术的快速发展,行业......
    数功能。本文将以TIM2实现发动机转速/相位发生器的设计,并通过串口屏幕显示。文章给出了具体的电路的硬件设计及软件设计流程,并给出设计说明。经实践证明,该发生器据有可靠、稳定、精确的特性。 发动......
    富的片上资源,能够支持使用固件库开发编程。该芯片接口多,可以连接许多外设,总共有8个串口,因此可以通过串口将不同的模块连接,实现多路的数据采集并集中处理。STM32F429IGT6主控芯片HMI串口屏......
    系统设计的难点所在。LoRa 控制器一方面通过 232 与串口屏通信,可查看报警时间、报警浓度、故障类型等,也可设置、修改、查阅系统参数 ;另一方面,LoRa 控制器中的 LoRa 网关......
    -TTL串口模块,这个是用来调试M5311模块的,可以不需要,因为mini开发板板载USB转TTL模块,你可以拔掉原有的短路帽来用。不过玩单片机的话,最好是有一个这个模块,超级方便! 中移的M5311......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>