我刚刚开始探索STM32 MCU。我想在BluePill(有STM32F103C8T6单片机)板上闪烁发光二极管。我怀疑我被什么东西误导了。根据“F1系列参考手册”,有三个主要步骤:
我已经按照手册用KEIL编写了代码,但是在加载代码之后,代码不运行,我按下重置按钮,然后打开,尽管我已经更改设置为重置并在中运行。
这是参考手册的代码和部分。
#include<stm32f10x.h>
int main(){
RCC->APB2ENR |= 1<<4; //PORTC is on APB2 bus
GPIOC->CRH |= (1<<20);
while(1){
GPIOC->ODR |= 0x00002000;
for(int i = 0; i < 500000;i++); //dummy delay
GPIOC->ODR &= ~0x00002000;
for(int i = 0; i < 500000;i++); // dummy delay
}
}参考手册:



当我使用调试模式时,我注意到一件事,即在执行RCC->APB2ENR |= (1<<4)之后,没有为PORTC启用时钟。

LED不会闪烁。在整个过程中,我找不到错误。
发布于 2020-11-23 16:52:23
当您编写虚拟延迟循环时,智能编译器通常会发现在这段代码中没有什么值得做的事情,并对整个过程进行优化。
如果您想知道已经发生了这种情况,最好的方法是查看生成的二进制文件的反汇编。
幸运的是,C提供了volatile关键字来解决这类问题。它显式地告诉编译器不要优化使用此限定符声明的变量的内存访问。
这里,您可以看到一些示例代码,这些代码显示了使用优秀的volatile工具生成的装配代码与不带volatile关键字的程序集代码之间的差异。如果没有易失性,for循环将被优化为零,并且不会发生i的增量或检查。
因此,循环应该编写为:
for(volatile int i = 0; i < 500000; i++); //dummy delay在嵌入式系统上也可能遇到这种问题,例如当您从多个上下文/线程访问一个变量时。
发布于 2020-11-23 14:37:23
实际上,LED在while循环中切换,但只在调试模式下进行切换。
是的,因为这是唯一一次生成的机器代码包括那些延迟循环。在发布模式下,LED仍然没有切换,除非你需要一个示波器或逻辑分析器来观察输出引脚的状态,以确定它正在切换--你不会仅仅用眼睛看到它:)
在发布模式下,延迟循环将被删除,因为不能以这种方式实现延迟。理想情况下,您应该使用计时器,但作为一种快速攻击,这样做是可行的:
const int N = 500000;
while(1){
for(int i = 0; i < N;i++) GPIOC->ODR |= 0x00002000;
for(int i = 0; i < N;i++) GPIOC->ODR &= ~0x00002000;
}它可以工作,因为GPIOC指向易失性对象,编译器无法优化访问。
https://stackoverflow.com/questions/64970233
复制相似问题