单片机
返回首页

STM32 USART学习

2025-11-06 来源:bilibili

USART(同步异步串口通信)

在STM32的参考手册中,串口被描述成通用同步异步收发器(USART),它提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互联网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。还可以使用DMA方式,实现高速数据通信


STM32 中的USART框图

框图

1、引脚编号

  • TX:发送数据输出

  • RX:接收数据串行输入

  • SCLK(位于最右边):发送器时钟输出,仅同步通信时使用

  • nRTS:请求发送(Request To Send)

  • nCTS:允许发送(Clear To Send)

  • SW_RX:数据接收引脚,属于内部引脚。

2、数据寄存器

数据寄存器(USART_DR)只有低9位有效,实际上它包含一个发送数据寄存器USART_TDR和一个接收数据寄存器USART_RDR。TDR和RDR都是介于系统总线和移位寄存器之间。这里比较特别:一个地址对应了两个物理内存。

当进行发送操作时,往USART_DR写入数据会自动存储在 TDR内,然后把内容转移到发送移位寄存器,最后通过模块发送到TX引脚;

当进行读取操作时,信息从RX引脚进入,通过模块后存入接受移位寄存器,然后把内容转移到RDR内,最后USART_DR提取RDR数据。

3、控制器

USART有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等。

控制寄存器1(USART_CR1)的TE位负责使能发送器,发送器就会“叫醒”发送移位寄存器。

控制寄存器1(USART_CR1)的RX位负责使能接收器,接收器就会“叫醒”接收移位寄存器。

控制寄存器1的TXEIE或RXNEIE置1可以产生中断。

控制寄存器1其他位:TXE:发送移位寄存器为空,发送单个字节时使用。TC:发送完成,发送多个字节数据时候使用。TXIE:发送完成中断使能。

控制寄存器1的M位设置的是字长,该位定义了数据字的长度,由软件对其设置和清零。设置0:一个起始位,8个数据位;设置1:一个起始位,9个数据位。之前已经说过,数据寄存器(USART_DR)只有低9位有效,并且第9位数据是否有效要取决于控制寄存器1的M位设置。

控制寄存器2(USART_CR2)的STOP[1:0]位用于设置停止位,可选0.5个、1个、1.5个、2个停止位。默认使用1个停止位。2个停止位适用于正常USART模式、单线模式和调制解调器模式。0.5和1.5个停止位用于智能卡模式

4、波特率

通过波特率寄存器(USART_BRR)可设置波特率。由于计算出的分频因子有小数,因此寄存器分为两个部分:

DIV_Mantissa[11:0]:USARTDIV的整数部分,这12位定义了USART分频器除法因子(USARTDIV)的整数部分。

DIV_Fraction[3:0]:USARTDIV的小数部分,这4位定义了USART分频器除法因子(USARTDIV)的小数部分。

波特比率的计算公式为:

但开发中调用库函数只需调用库函数

USART.c

#include "USART.h"                  // Device header

#include "stdio.h"



 static void NVIC_Configuration(void)

 {

 NVIC_InitTypeDef NVIC_InitStructure;

 /* 嵌套向量中断控制器组选择 */

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


 /* 配置 USART 为中断源 */

 NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;

 /* 抢断优先级为 1 */

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

 /* 子优先级为 1 */

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

 /* 使能中断 */

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 /* 初始化配置 NVIC */

 NVIC_Init(&NVIC_InitStructure);

 }

 void USART_Config(void)

 {

 GPIO_InitTypeDef GPIO_InitStructure;

 USART_InitTypeDef USART_InitStructure;


 // 打开串口 GPIO 的时钟

 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);


 // 打开串口外设的时钟

 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);


 // 将 USART Tx 的 GPIO 配置为推挽复用模式

 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);


 // 将 USART Rx 的 GPIO 配置为浮空输入模式

 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

 GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);


 // 配置串口的工作参数

 // 配置波特率

 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;

 // 配置 针数据字长

 USART_InitStructure.USART_WordLength = USART_WordLength_8b;

 // 配置停止位

 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(DEBUG_USARTx, &USART_InitStructure);


 // 串口中断优先级配置

 NVIC_Configuration();


 // 使能串口接收中断

 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);


 // 使能串口

 USART_Cmd(DEBUG_USARTx, ENABLE);

 }


/***************** 发送一个字符 **********************/

 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)

 {

 /* 发送一个字节数据到 USART */

 USART_SendData(pUSARTx,ch);


 /* 等待发送数据寄存器为空 */

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

 }


 /***************** 发送字符串 **********************/

 void Usart_SendString( USART_TypeDef * pUSARTx, char *str)

 {

 unsigned int k=0;

 do {

 Usart_SendByte( pUSARTx, *(str + k) );

 k++;

 } while (*(str + k)!='');


 /* 等待发送完成 */

 while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {

 }

 }

 /*中断服务函数和串口初始化*/

 void USART_init(void ){

USART_Config();

NVIC_Configuration();

 }

  /*中断服务函数*/

//void DEBUG_USART_IRQHandler(void)

// {

//   uint8_t ucTemp=1;

// if (USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)

//   {

//     ucTemp = USART_ReceiveData( DEBUG_USARTx );

//     USART_SendData(USART1,ucTemp);

//

//   }

//

// }

USART.h


#include "stm32f10x.h"

#ifndef __USART_H_

#define __USART_H_


/**

 * 串口宏定义,不同的串口挂载的总线和 IO 不一样,移植时需要修改这几个宏

 */

 // 串口 1-USART1

 #define DEBUG_USARTx USART1

 #define DEBUG_USART_CLK RCC_APB2Periph_USART1

 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd

 #define DEBUG_USART_BAUDRATE 9600

 // USART GPIO 引脚宏定义

 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)

 #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd


 #define DEBUG_USART_TX_GPIO_PORT GPIOA

 #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9

 #define DEBUG_USART_RX_GPIO_PORT GPIOA

 #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10


 #define DEBUG_USART_IRQ USART1_IRQn

 #define DEBUG_USART_IRQHandler USART1_IRQHandler


/***************** 发送一个字符 **********************/

 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);

 /***************** 发送一个字符串 **********************/

 void Usart_SendString( USART_TypeDef * pUSARTx, char *str);


 void USART_init(void );

#endif

main.c


#include "stm32f10x.h"                  // Device header

#include "Delay.h"

#include "OLED.h"

#include "USART.h"                  // Device header



int main(void)

{

OLED_Init();



OLED_ShowString(1, 3, "USART_TEST");


USART_init();

Usart_SendByte(USART1 ,0x41);

Usart_SendByte(USART1 ,0x45);

while (1)

{

Usart_SendString(USART1,"abcdn");

Delay_ms(1000);


}



 }


void DEBUG_USART_IRQHandler(void)

 {

   uint16_t ucTemp;

 if (USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)

   {

     ucTemp = USART_ReceiveData( DEBUG_USARTx );

     USART_SendData(USART1,ucTemp);

  OLED_ShowString(2,6,"ok!");

  OLED_ShowString(3,1,"test successful");

   }


 }


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章