STM32F1 GPIO寄存器LED不闪烁,一直保持
Posted
技术标签:
【中文标题】STM32F1 GPIO寄存器LED不闪烁,一直保持【英文标题】:STM32F1 GPIO registers LED not blinking, just staying on whole time 【发布时间】:2021-11-13 18:21:08 【问题描述】:我从微控制器开始我的旅程,我正在使用 STM32F1(带有 STM32F103RB 的 Nucleo 板)开始我的旅程。我尝试使用寄存器学习写作,看起来我被第一个“任务”困住了 - 闪烁的 LED。我设法打开了led,但我不能让它闪烁。奇怪的是,当我去调试(我在 Keil uVision 上工作)并查看 GPIOA 外围设备时,端口 5(led 是 PA5)有这个滴答声,这意味着它应该在现实中闪烁。但不是。我尝试更改延迟,但没有任何反应。我被困住了。 我究竟做错了什么? 这是我的代码:
#include "stm32f10x.h"
void delay(unsigned int ms)
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 20000; j++);
int main(void)
RCC->APB2ENR |= (1<<2);
GPIOA->CRL |= ( (1<<21));
GPIOA->CRL &= ~( (1<<22) | (1<<23) | (1<<20) );
while(1)
GPIOA->BSRR |= (1<<5);
delay(200);
GPIOA->BSRR |= (1<<21);
delay(200);
谢谢
【问题讨论】:
嗨!你确定你的delay
函数会持续 200 毫秒吗?
还要注意BSRR
寄存器是只写的。因此按位 or 操作具有未定义的行为。只需使用GPIOA->BSRR = (1<<5)
。
您可以通过使用 Keil 单步执行代码来检查 GPIOA->BSRR 命令。这将消除其他人提到的延迟函数可能出现的错误行为。
【参考方案1】:
正如 dunajski 所说,您确定将函数延迟延迟 200 毫秒吗?或者更直接地说:永远不要使用 NOP 作为延迟。这可能在特定芯片/系统上的某些特定情况下有效,但您可以假设它不会延迟任何事情。 NOP 循环将根据编译器进行优化。即使不是,在不同的频率/架构上也会有不同的运行时间。
如果您只想延迟,请改用sleep()
或usleep()
。这将暂时“阻止”控制器,因此您在此期间不能做任何事情,但对于您的测试,这就足够了。如果您想要并发计时,请使用一些 systick 回调(或中断)。
【讨论】:
【参考方案2】:启用时钟后,您需要等待此操作通过总线传播。它可以通过使用屏障指令或从寄存器回读来归档。
不要使用幻数。使用来自 CMSIS 的定义。检查是否设置了正确的模式。
这是无效的:
GPIOA->BSRR |= (1<<5); // Set bit 5
delay(200); // delay some time
GPIOA->BSRR |= (1<<21); // Set bit 21 (not 5)
BSRR 只写,您不应该从中读取。
GPIOA->BSRR = (1<<5); // Set bit 5
delay(200); // delay some time
GPIOA->BSRR = (1<<21); // Set bit 21 (not 5)
如果您想使用循环来延迟,请采用不同的方式:
void delay(unsigned int ms)
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 20000; j++)
asm(":::memory");
https://godbolt.org/z/6c8dqKT8P
如果您启用优化,您的函数将被优化为单次返回。
https://godbolt.org/z/szfT7Tfv9
【讨论】:
以上是关于STM32F1 GPIO寄存器LED不闪烁,一直保持的主要内容,如果未能解决你的问题,请参考以下文章