资讯动态

STM32F103的流水灯点亮版本1(寄存器地址操作)

发布时间:2026/9/24 17:53:15 来源:尧图企业网站定制
一、STM32F103C8T6 最小系统核心板介绍STM32F103C8T6 是 ST 意法半导体推出的Cortex‑M3 内核 32 位高性能单片机LQFP‑48封装是学生嵌入式学习最常用的最小系统核心板。一核心参数1内核ARM Cortex-M3最高工作频率 72MHz2存储Flash 64KB存放程序代码SRAM 20KB程序运行临时变量3供电工作电压 2.0~3.6V一般外部使用 3.3V 供电支持 VBAT 纽扣电池给 RTC 实时时钟备份供电4外设资源GPIO 通用 IO 口、ADC、定时器、USART 串口、I2C、SPI、CAN、USB 等二最小系统板必备电路1电源电路外部 5V 输入AMS1117-3.3V 稳压芯片输出 3.3V 给主芯片供电2复位电路 NRSTRC 复位按键按下低电平芯片系统复位3高速外部晶振 HSE8MHz 无源晶振经 PLL 倍频得到 72MHz 系统时钟4低速外部晶振 LSE32.768KHz为 RTC 实时时钟提供时钟5BOOT 启动选择引脚BOOT00从Flash 启动正常下载程序模式日常使用BOOT01从系统存储器启动串口 ISP 下载6下载调试电路集成 SWD 调试接口PA13-SWDIO、PA14-SWCLK使用 ST-Link 下载调试7板载 LED核心板自带 LEDLED 阳极接 3.3V引脚输出低电平点亮 LED高电平熄灭二、相关概念的学习一GPIOx端口GPIO General‑Purpose Input Output通用输入输出端口。GPIOx中x 是端口标识符代表不同端口组在 STM32F103 芯片中可以是 A、B、C、D、E于是就有 GPIOA、GPIOB、GPIOC、GPIOD、GPIOE。而且每一个GPIOx端口固定拥有最多 16 个 IO 引脚Px0 ~ Px15。GPIOA、GPIOB、GPIOC 挂载在 APB2 外设总线上。所以必须操作RCC_APB2ENR寄存器把对应端口时钟打开时钟不开启GPIO 完全失效读写寄存器无效。bit2 置 1 → 开启GPIOA时钟bit4 置 1 → 开启GPIOC时钟。每组端口拥有自己独立的寄存器地址互不相同GPIOA 的寄存器只会控制 A 组引脚不能控制 GPIOC 引脚。二寄存器在 STM32 单片机里寄存器是 MCU 芯片内部、拥有固定物理地址的硬件存储单元是 CPU 和硬件外设GPIO、定时器、串口等沟通的唯一桥梁。普通 C 语言变量是放在 RAM 内存里只是软件临时数据寄存器是真实硬件电路对寄存器读写直接改变芯片硬件行为。核心特点a.每个寄存器都有唯一固定物理地址例如GPIOA_CRL 地址0x40010800GPIOA_ODR 地址0x4001080CCPU 通过访问这个地址读写寄存器里面的数据。b.寄存器由很多二进制位bit组成 STM32 的 GPIO 寄存器大多是 32 位也就是 32 个 0/1 开关。 每一个 bit 或者连续几个 bit专门控制硬件某一项功能。 比如GPIOA_CRL中每 4 个 bit 控制 1 个 PA 端口引脚用来设置引脚模式、输出速度。c.每组 GPIOx 端口都自带一套独立寄存器 GPIOA、GPIOB、GPIOC 各自拥有一套 CRL、CRH、ODR、IDR 寄存器。写 GPIOA 的寄存器只会修改 PA 引脚不会影响 PB、PC 引脚写 GPIOC 寄存器只修改 PC 引脚本实验 PC13 板载 LED 就在 GPIOC。1、地址查找每个 GPIO 端口都有一个基地址CRL寄存器的偏移 0x00真实物理地址 GPIO端口基地址 偏移0x002、端口配置低寄存器是GPIO 通用输入输出口总线APB2只控制该端口的 Px0 ~ Px7低 8 个 IO 引脚Px8‑Px15 由GPIOx_CRH端口配置高寄存器控制。x 代表端口A/B/C/D/E例如 GPIOA_CRL 控制 PA0‑PA7GPIOB_CRL控制 PB0‑PB7。修改单个引脚配置时先把该引脚对应的 4 位清零 ~(0x0F (4*n))再写入新配置不能直接给 CRL 整个寄存器赋值否则会覆盖其他引脚复用功能模式下ODR 寄存器不再控制引脚电平由片内外设定时器、串口、SPI控制引脚输出输入上拉 / 下拉CNF 只开启功能选择真正电阻开关由GPIOx_ODR输出寄存器对应位控制。3、GPIOx_CRH 端口配置高寄存器CRH 只管 Px8‑Px15Px0‑Px7 交给 CRL不要搞混寄存器修改单个高引脚应该先把该引脚对应的 4 位掩码0x0F移位清零再写配置禁止直接GPIOA-CRH xxx会覆盖 PA8‑PA15 全部引脚。上拉 / 下拉时CNF 只选择模式必须配合 ODR 寄存器对应位内部电阻才生效。复用功能输出时ODR 不再控制引脚电平由外设TIM/USART/SPI接管引脚。4、APB2ENR属于 RCC复位和时钟控制模块必须先开启 GPIO 时钟GPIO 寄存器才能正常工作。相对 RCC 基地址偏移地址是0x18RCC 基地址为0x40021000所以 RCC_APB2ENR 物理地址 0x40021000 0x18 0x40021018可读可写每一位控制一个 APB2 总线上外设的时钟开关写1时打开该外设时钟使能写0时关闭该外设时钟复位默认省电5、IDR、ODR对比项GPIOx_IDRGPIOx_ODR偏移0x080x0C读写属性只读写无效可读可写含义读外部引脚实际电平读写内部输出锁存值用途读取按键、外部输入信号设置输出电平输入模式控制上下拉电阻风险无只管读修改单 bit 存在中断干扰风险三、基于寄存器实现流水灯一实验目的理解 STM32 GPIO 外设工作原理学习直接操作寄存器地址方式控制 IO 口掌握 RCC 时钟使能懂得 STM32 外设必须开启时钟才可以工作读懂 CRL、CRH、ODR 寄存器功能掌握位操作 使用GPIOA、GPIOB、GPIOC这3种端口的任意引脚控制3个LED灯这里用到的是PA1,PA3,PA5结合最小系统板自带 PC13 板载 LED实现 4 个 LED 轮流流水闪烁间隔 1 秒二软硬件准备1.硬件STM32F103C8T6 开发板ST‑Link 下载调试器USB 数据线、杜邦线LED灯2.软件Keil MDK5 用写、编译、调试代码初学 STM32第一步就是搞定 Keil MDK5 开发环境。这块步骤繁琐截图多这里就不重复写长篇安装图文了网上成熟教程资源非常多要学会利用资源跟着一步步操作效率更高。STM32 入门教程‑2023 版 细致讲解 中文字幕‑哔哩哔哩3.程序设计与实现1代码思路A.寄存器地址宏定义:使用volatile uint32_t强制映射硬件寄存器真实物理地址。volatile告诉编译器该地址是硬件寄存器不要做缓存优化每次都要真实读写内存。把RCC_APB2ENR、GPIOA_CRL、GPIOA_ODR、GPIOC_CRH、GPIOC_ODR定义成宏后面代码直接写名字访问寄存器。B.delay_1s 软件延时函数:两层 for 空循环靠 CPU 循环消耗时间粗略实现 1 秒延时。循环变量加volatile防止 Keil 高优化等级直接把空循环删掉导致延时失效。C.LED_GPIO_Init () 初始化函数:操作RCC_APB2ENR置位 bit2 打开 GPIOA 时钟置位 bit4 打开 GPIOC 时钟。配置GPIOA_CRLPA1、PA3、PA5 属于 PA0‑PA7CRL 每 4 位控制 1 个引脚。先 ~掩码把对应引脚的 4 位全部清零再| 配置值写入0001设置为推挽输出速度 2MHz。配置GPIOC_CRHPC13 属于 PC8‑PC15在 CRH 寄存器同样先清 4 位再写 0001 推挽输出。配置初始电平操作 ODR所有 LED 初始熄灭。PA1/PA3/PA5 外接 LED输出低电平熄灭PC13 板载 LED输出高电平熄灭。D.main 主函数先调用LED_GPIO_Init()完成端口初始化。进入while(1)死循环循环是单片机程序主体永远不会退出。分 4 个步骤轮流点亮单个 LED其余全部熄灭修改GPIOA_ODR、GPIOC_ODR控制引脚高低电平每点亮一组调用delay_1s()停留 1 秒依次PA1 亮 → PA3 亮 → PA5 亮 → PC13 亮往复循环。2点亮3个LED灯#includestm32f10x.h// Device header#includeDelay.hintmain(void){GPIO_InitTypeDef GPIO_InitStructure;//开启GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// PA1 PA3 PA5 推挽输出 50MHzGPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_PinGPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_5;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);//初始全部熄灭输出高电平低电平点亮LEDGPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_5);while(1){//点亮PA1其余熄灭GPIO_ResetBits(GPIOA,GPIO_Pin_1);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_SetBits(GPIOA,GPIO_Pin_5);Delay_ms(1000);//点亮PA3其余熄灭GPIO_SetBits(GPIOA,GPIO_Pin_1);GPIO_ResetBits(GPIOA,GPIO_Pin_3);GPIO_SetBits(GPIOA,GPIO_Pin_5);Delay_ms(1000);//点亮PA5其余熄灭GPIO_SetBits(GPIOA,GPIO_Pin_1);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_ResetBits(GPIOA,GPIO_Pin_5);Delay_ms(1000);}}(3)用PC13验证自己烧录的代码是否正常运行#includestm32f10x.h// Device header#includeDelay.hintmain(void){GPIO_InitTypeDef GPIO_InitStructure;//开启GPIOA、GPIOC时钟PA1 PA3 PA5属于GPIOAPC14属于GPIOCRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);// PA1 PA3 PA5 推挽输出 50MHzGPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_PinGPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_5;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);// PC14 推挽输出 50MHzGPIO_InitStructure.GPIO_PinGPIO_Pin_14;GPIO_Init(GPIOC,GPIO_InitStructure);//初始全部熄灭输出高电平低电平点亮LEDGPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_5);GPIO_SetBits(GPIOC,GPIO_Pin_14);while(1){//点亮PA1其余熄灭GPIO_ResetBits(GPIOA,GPIO_Pin_1);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_SetBits(GPIOA,GPIO_Pin_5);GPIO_SetBits(GPIOC,GPIO_Pin_14);Delay_ms(1000);//点亮PA3其余熄灭GPIO_SetBits(GPIOA,GPIO_Pin_1);GPIO_ResetBits(GPIOA,GPIO_Pin_3);GPIO_SetBits(GPIOA,GPIO_Pin_5);GPIO_SetBits(GPIOC,GPIO_Pin_14);Delay_ms(1000);//点亮PA5其余熄灭GPIO_SetBits(GPIOA,GPIO_Pin_1);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_ResetBits(GPIOA,GPIO_Pin_5);GPIO_SetBits(GPIOC,GPIO_Pin_14);Delay_ms(1000);//点亮PC14其余熄灭GPIO_SetBits(GPIOA,GPIO_Pin_1);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_SetBits(GPIOA,GPIO_Pin_5);GPIO_ResetBits(GPIOC,GPIO_Pin_13);Delay_ms(1000);}}4.实验现象LED灯LED灯四、总结本次STM32裸寄存器流水灯实验可以掌握了GPIO相关寄存器的配置方法明白STM32外设上电后时钟默认关闭使用前必须开启对应时钟。实验中学会使用Keil调试功能单步运行观察寄存器数值变化直观验证代码效果。也认识到软件空循环延时精度较差仅适合实验演示。编写代码不能直接复制照搬要弄懂每一行代码对应的硬件操作。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价