STM32_USART_寄存器操作

文章目录

  • 一、UASRT寄存器
    • [   1、状态寄存器(USART_SR)](#   1、状态寄存器(USART_SR))
    • [   2、数据寄存器(USART_DR)](#   2、数据寄存器(USART_DR))
    • [   3、波特比率寄存器(USART_BRR)](#   3、波特比率寄存器(USART_BRR))
    • [   4、控制寄存器 1(USART_CR1)](#   4、控制寄存器 1(USART_CR1))
    • [   5、控制寄存器 2(USART_CR2)](#   5、控制寄存器 2(USART_CR2))
    • [   6、控制寄存器 3(USART_CR3)](#   6、控制寄存器 3(USART_CR3))
    • [   7、保护时间和预分频寄存器(USART_GTPR)](#   7、保护时间和预分频寄存器(USART_GTPR))
    • [   8、USART寄存器地址映象](#   8、USART寄存器地址映象)
  • 二、代码实例
    • [   串口寄存器编程代码(含中断 + 查询模式)](#   串口寄存器编程代码(含中断 + 查询模式))
  • 三、总结
    • [   1、关键寄存器](#   1、关键寄存器)
    • [   2、硬件接线:](#   2、硬件接线:)
    • [   3、串口寄存器编程核心流程:](#   3、串口寄存器编程核心流程:)

一、UASRT寄存器

1、状态寄存器(USART_SR)

地址偏移:0x00

复位值:0x00C0

2、数据寄存器(USART_DR)

地址偏移:0x04

复位值:不确定

3、波特比率寄存器(USART_BRR)

注意: 如果TE或RE被分别禁止,波特计数器停止计数

地址偏移:0x08

复位值:0x0000

4、控制寄存器 1(USART_CR1)

地址偏移:0x0C

复位值:0x0000

5、控制寄存器 2(USART_CR2)

地址偏移:0x10

复位值:0x0000

6、控制寄存器 3(USART_CR3)

地址偏移:0x14

复位值:0x0000

7、保护时间和预分频寄存器(USART_GTPR)

地址偏移:0x18

复位值:0x0000

8、USART寄存器地址映象

二、代码实例

串口寄存器编程代码(含中断 + 查询模式)

c 复制代码
	#include "stm32f10x.h"
	#include <string.h>
	
	// 全局接收缓冲区(中断接收用)
	#define USART1_RX_BUF_SIZE 128
	uint8_t USART1_Rx_Buf[USART1_RX_BUF_SIZE];
	uint16_t USART1_Rx_Len = 0;
	uint8_t USART1_Rx_Flag = 0; // 接收完成标志(0:未完成,1:完成)
	
	/**
	 * @brief  系统时钟初始化(72MHz,HSE=8MHz)
	 * 串口波特率计算依赖系统时钟,必须先初始化
	 */
	void SystemClock_Init(void)
	{
	    // 1. 开启HSE,等待稳定
	    RCC->CR |= RCC_CR_HSEON;
	    while(!(RCC->CR & RCC_CR_HSERDY));
	    
	    // 2. 配置FLASH延迟、总线分频
	    FLASH->ACR |= FLASH_ACR_LATENCY_2;
	    RCC->CFGR &= ~RCC_CFGR_HPRE;    // AHB不分频
	    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 2分频
	    RCC->CFGR &= ~RCC_CFGR_PPRE2;   // APB2不分频
	    
	    // 3. 配置PLL(8MHz×9=72MHz)
	    RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
	    RCC->CFGR |= RCC_CFGR_PLLMULL9;
	    
	    // 4. 开启PLL,等待稳定
	    RCC->CR |= RCC_CR_PLLON;
	    while(!(RCC->CR & RCC_CR_PLLRDY));
	    
	    // 5. 切换系统时钟到PLL
	    RCC->CFGR &= ~RCC_CFGR_SW;
	    RCC->CFGR |= RCC_CFGR_SW_PLL;
	    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
	}
	
	/**
	 * @brief  USART1初始化(9600波特率,8位数据位,1位停止位,无校验)
	 * @param  baudrate:波特率(如9600、115200)
	 */
	void USART1_Init(uint32_t baudrate)
	{
	    // 1. 开启GPIOA、USART1、AFIO时钟
	    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN;
	    
	    // 2. 配置GPIO引脚
	    // PA9(TX):复用推挽输出(10MHz)
	    GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
	    GPIOA->CRH |= GPIO_CRH_MODE9_0 | GPIO_CRH_CNF9_1;
	    // PA10(RX):浮空输入
	    GPIOA->CRH &= ~(GPIO_CRH_MODE10 | GPIO_CRH_CNF10);
	    GPIOA->CRH |= GPIO_CRH_CNF10_0;
	    
	    // 3. 配置串口核心参数
	    USART1->CR1 &= ~USART_CR1_UE; // 先关闭串口
	    
	    // 配置数据位:8位(M=0)、无校验(PCE=0)
	    USART1->CR1 &= ~(USART_CR1_M | USART_CR1_PCE);
	    // 配置停止位:1位(STOP[1:0]=00)
	    USART1->CR2 &= ~USART_CR2_STOP;
	    // 配置波特率(USART1时钟=72MHz)
	    USART1->BRR = 72000000 / baudrate;
	    
	    // 4. 开启发送、接收、接收非空中断
	    USART1->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
	    // 5. 开启串口
	    USART1->CR1 |= USART_CR1_UE;
	}
	
	/**
	 * @brief  USART1 NVIC配置(中断优先级)
	 */
	void USART1_NVIC_Init(void)
	{
	    // 配置优先级分组2:2位抢占+2位子优先级
	    SCB->AIRCR = 0x05FA0800;
	    // USART1对应37号中断通道
	    NVIC->IP[37] &= ~0xFF;         // 清空优先级
	    NVIC->IP[37] |= 0x10;          // 抢占优先级1,子优先级0
	    NVIC->ISER[1] |= (1 << 5);     // 37=32+5 → ISER1的bit5置1
	}
	
	/**
	 * @brief  USART1发送一个字节(查询模式)
	 * @param  data:要发送的字节
	 */
	void USART1_SendByte(uint8_t data)
	{
	    // 等待发送数据寄存器为空(TXE=1)
	    while(!(USART1->SR & USART_SR_TXE));
	    USART1->DR = data;
	    // 等待发送完成(TC=1)
	    while(!(USART1->SR & USART_SR_TC));
	}
	
	/**
	 * @brief  USART1发送字符串(查询模式)
	 * @param  str:要发送的字符串
	 */
	void USART1_SendString(char *str)
	{
	    while(*str != '\0')
	    {
	        USART1_SendByte(*str);
	        str++;
	    }
	}
	
	/**
	 * @brief  USART1中断服务函数(接收数据)
	 * 接收规则:接收到换行符'\n'表示接收完成
	 */
	void USART1_IRQHandler(void)
	{
	    uint8_t recv_data;
	    // 检查接收非空标志(RXNE=1)
	    if(USART1->SR & USART_SR_RXNE)
	    {
	        recv_data = USART1->DR; // 读取数据(自动清除RXNE标志)
	        
	        // 接收逻辑:未溢出且未完成
	        if(USART1_Rx_Len < USART1_RX_BUF_SIZE && !USART1_Rx_Flag)
	        {
	            if(recv_data == '\n') // 换行符表示接收完成
	            {
	                USART1_Rx_Buf[USART1_Rx_Len] = '\0'; // 字符串结束符
	                USART1_Rx_Flag = 1;                   // 置位完成标志
	                USART1_Rx_Len = 0;                    // 重置长度
	            }
	            else
	            {
	                USART1_Rx_Buf[USART1_Rx_Len++] = recv_data;
	            }
	        }
	        else // 溢出或已完成,重置
	        {
	            USART1_Rx_Len = 0;
	            USART1_Rx_Flag = 0;
	        }
	    }
	}
	
	// 主函数:测试串口收发(中断接收+查询发送)
	int main(void)
	{
	    // 1. 初始化系统时钟
	    SystemClock_Init();
	    // 2. 初始化USART1(9600波特率)
	    USART1_Init(9600);
	    // 3. 初始化NVIC
	    USART1_NVIC_Init();
	    
	    // 4. 发送测试字符串
	    USART1_SendString("STM32 USART1 Register Test\r\n");
	    USART1_SendString("Input String (end with '\\n'):\r\n");
	    
	    while(1)
	    {
	        // 检测到接收完成
	        if(USART1_Rx_Flag)
	        {
	            // 回显接收的字符串
	            USART1_SendString("Recv: ");
	            USART1_SendString((char*)USART1_Rx_Buf);
	            USART1_SendString("\r\n");
	            
	            // 清空接收标志
	            USART1_Rx_Flag = 0;
	        }
	    }
	}

三、总结

1、关键寄存器

2、硬件接线:

STM32 PA9(TX)→ USB 转 TTL 模块 RX

STM32 PA10(RX)→ USB 转 TTL 模块 TX

STM32 GND → USB 转 TTL 模块 GND

3、串口寄存器编程核心流程:

开时钟→配引脚→配波特率 / 帧格式→开收发 / 中断→配 NVIC→编写收发 / 中断函数;

相关推荐
沐欣工作室_lvyiyi2 小时前
基于单片机的多参数监护仪系统(论文+源码)
stm32·单片机·嵌入式硬件·多参数监护仪
熬夜有啥好3 小时前
51单片机(1)
单片机·嵌入式硬件·51单片机
DLGXY3 小时前
STM32(二十六)——WDG看门狗
stm32·单片机·嵌入式硬件
集芯微电科技有限公司3 小时前
AD536A高性能真有效值直流转换电路替代PC2909
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络
可乐鸡翅好好吃3 小时前
关于频率(HZ)与周期(ms)的转换
单片机·嵌入式硬件
进击的横打3 小时前
【车载开发系列】RH850常用的定时器
单片机·嵌入式硬件·rh850
2501_918126914 小时前
学习所有6502写游戏地图的语句
汇编·嵌入式硬件·学习·游戏·个人开发
szxinmai主板定制专家4 小时前
基于ZYNQ MPSOC船舶数据采集仪器设计(三)振动,流量,功耗,EMC,可靠性测试
arm开发·人工智能·嵌入式硬件·fpga开发
AI+程序员在路上4 小时前
Keil5 中安装 STM32各系列单片机开发包步骤
stm32·单片机·嵌入式硬件