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

【经验分享】STM32串口通信UART使用

[复制链接]
STMCU小助手 发布时间:2022-2-7 21:16
uart使用的过程为:
  • 1. 使能GPIO口和UART对应的总线时钟
  • 2. 配置GPIO口的输出模式
  • 3. 配置uart口相关的基本信息
  • 4. 使能uart口的相关的中断,如接收中断、空闲中断等
  • 5. 编写中断接收函数

配置对应的GPIO口
对于STM32F4_Discovery开发板而言共有五个,选择UART5作为实验串口,其对应的IO口为PC12、PD2。
  • UART5_TX: PC12
  • UART5_RX: PD2
首先需要将对应的GPIO口配置为复用功能,如下所示:
  1. GPIO_InitTypeDef gpioInitStructure;
  2.         //
  3.         // 使能对应的GPIO口时钟
  4.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
  5.         //
  6.         // UART5 TX:PC12  RX:PD2
  7.         //
  8.         GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
  9.         GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
  10.         //
  11.         // PC12       
  12.         gpioInitStructure.GPIO_Pin = GPIO_Pin_12;
  13.         gpioInitStructure.GPIO_Mode = GPIO_Mode_AF;
  14.         gpioInitStructure.GPIO_OType = GPIO_OType_PP;
  15.         gpioInitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  16.         gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz;       
  17.         GPIO_Init(GPIOC, &gpioInitStructure);       
  18.         // PD2
  19.         gpioInitStructure.GPIO_Pin = GPIO_Pin_2;
  20.         GPIO_Init(GPIOD, &gpioInitStructure);
复制代码

对于GPIO口的配置,实际上是对GPIO各个寄存器的配置。GPIO_PinAFConfig()函数作用是配置GPIOx_AFR寄存器,每个口的复用功能选择由四个位来配置(具体参考STM32F4XX参考手册),因此16个GPIO空需要两个32位寄存器,在STM32F4处理器中,分别是GPIOx_AFRL、GPIOx_AFRH。而在库函数中,将寄存器的地址对应到相应的结构体上,与这两个寄存器放在一个AFR[2]数组中,如下所示。
  1. typedef struct
  2. {
  3.   __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
  4.   __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
  5.   __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
  6.   __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
  7.   __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
  8.   __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
  9.   __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */
  10.   __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */
  11.   __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
  12.   __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
  13. } GPIO_TypeDef;
复制代码

GPIO_Init()函数作用是配置GPIO口的输出输入功能,将GPIO_TypeDef结构体中的寄存器依次配置为相应的模式。
GPIO口配置完成之后,需要配置UART口。

UART口配置
配置UART口的同时,需要配置对应的接收中断,对应代码如下:
  1. NVIC_InitTypeDef nvicInitStructure;
  2.         USART_InitTypeDef uartInitStructure;
  3.         //使能uart5时钟
  4.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5 , ENABLE);
  5.         //
  6.         // 配置UART5
  7.         uartInitStructure.USART_BaudRate = 9600;
  8.         uartInitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  9.         uartInitStructure.USART_WordLength = USART_WordLength_8b;
  10.         uartInitStructure.USART_StopBits = USART_StopBits_1;
  11.         uartInitStructure.USART_Parity = USART_Parity_No;
  12.         uartInitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  13.         USART_Init(UART5, &uartInitStructure);
  14.         //
  15.         // 配置外设接受中断
  16.         nvicInitStructure.NVIC_IRQChannel = UART5_IRQn;       
  17.         nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  18.         nvicInitStructure.NVIC_IRQChannelSubPriority = 0;
  19.         nvicInitStructure.NVIC_IRQChannelCmd = ENABLE;
  20.         NVIC_Init(&nvicInitStructure);
  21.         //
  22.         USART_Cmd(UART5, ENABLE);
复制代码

配置UART5的过程主要由USART_Init()函数实现,该函数完成对UART寄存器的配置。在库函数中,UART寄存器如下所示:
  1. typedef struct
  2. {
  3.   __IO uint16_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
  4.   uint16_t      RESERVED0;  /*!< Reserved, 0x02                                                */
  5.   __IO uint16_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
  6.   uint16_t      RESERVED1;  /*!< Reserved, 0x06                                                */
  7.   __IO uint16_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
  8.   uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                                */
  9.   __IO uint16_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
  10.   uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                                */
  11.   __IO uint16_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
  12.   uint16_t      RESERVED4;  /*!< Reserved, 0x12                                                */
  13.   __IO uint16_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
  14.   uint16_t      RESERVED5;  /*!< Reserved, 0x16                                                */
  15.   __IO uint16_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
  16.   uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                                */
  17. } USART_TypeDef;
复制代码

UART寄存器详细内容可以参考STM32F4中文手册,这里简单介绍下以下几个寄存器:
  • SR寄存器:状态寄存器,包含了一些标志位,如TXE(发送数据寄存器为空)、TC(发送完成)、RXNE(读取数据寄存器不为空)
  • DR寄存器: 数据寄存器,只用其低9位(DR[8:0])。当发送数据时,将数据写入该寄存器,该寄存器将数据发送到TDR或者移位寄存器发送,当数据写到移位寄存器时,TXE标志置1(数据写入时置0)。TXE为1时可以继续写入数据,否则新写入的数据会把原有数据覆盖。读取数据时,也是从该寄存器读取数据。
  • BRR波特率寄存器:波特率寄存器,用来设置波特率的值。
  • CR1寄存器:包含使能位UE、字长M、过采样倍率、奇偶校验、接收使能、发送使能等控制信息。
数据收发单字符发送       
  1. //发送一个字符,USART_SendData函数实际就是将字符写入USART_DR寄存器
  2.         USART_SendData(pUSARTx,ch);
  3.         //
  4.         //等待发送寄存器为空,只有当USART_FLAG_TXE == 1 时才可以继续想DR寄存器写入数据,否则会将上一个数据覆盖掉。
  5.         while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
复制代码


字符串发送
  1. /***************** 发送字符串 **********************/
  2. // 发送字符串是每个字符依次发送,相当于循环执行单字符发送函数。
  3. //
  4. void uart_send_str( USART_TypeDef * pUSARTx, char *str)
  5. {
  6.         unsigned int k=0;
  7.         //
  8.         do {
  9.                 uart_send_byte( pUSARTx, *(str + k) );
  10.                 k++;
  11.         } while (*(str + k)!='\0');
  12.         //
  13.         /* 等待发送完成 */
  14.         while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) ;
  15. }
  16. //
  17. // USART_FLAG_TC为1的条件是,DR寄存器为空并且以为寄存器也为空。相当于所有数据都发送完毕
复制代码
字符接收
  1. uint8_t ucTemp;       
  2.         if (USART_GetITStatus(UART5, USART_IT_RXNE)!=RESET){
  3.                         ucTemp = USART_ReceiveData( UART5 );
  4.                         // USART_SendData(UART5,ucTemp);
  5.                 }
  6.         // USART_ReceiveData()函数是将DR寄存器读取并返回
  7.         // USART_IT_RXNE不为0表示数据寄存器中有数据,需要将其读出。
  8.         // 每次收一个字符,USART_IT_RXNE会被设置为1,直至数据被读出,USART_IT_RXNE再次被设置为0.
  9.         // 同时,USART_IT_RXNE也被设置为中断的标志,即接收到数据时,进入中断。
复制代码



收藏 评论0 发布时间:2022-2-7 21:16

举报

0个回答

所属标签

相似分享

官网相关资源

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