首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在STM32F103C8T6上做裸金属LED闪烁?

如何在STM32F103C8T6上做裸金属LED闪烁?
EN

Stack Overflow用户
提问于 2020-11-23 14:19:26
回答 2查看 967关注 0票数 2

我刚刚开始探索STM32 MCU。我想在BluePill(有STM32F103C8T6单片机)板上闪烁发光二极管。我怀疑我被什么东西误导了。根据“F1系列参考手册”,有三个主要步骤:

  • 启用端口时钟(此处为PORTC)
  • 配置CNF/模式寄存器
  • 根据需要配置ODR寄存器,即在引脚上配置高/低。

我已经按照手册用KEIL编写了代码,但是在加载代码之后,代码不运行,我按下重置按钮,然后打开,尽管我已经更改设置为重置并在中运行。

这是参考手册的代码和部分。

代码语言:javascript
复制
#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不会闪烁。在整个过程中,我找不到错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-11-23 16:52:23

当您编写虚拟延迟循环时,智能编译器通常会发现在这段代码中没有什么值得做的事情,并对整个过程进行优化。

如果您想知道已经发生了这种情况,最好的方法是查看生成的二进制文件的反汇编。

幸运的是,C提供了volatile关键字来解决这类问题。它显式地告诉编译器不要优化使用此限定符声明的变量的内存访问。

这里,您可以看到一些示例代码,这些代码显示了使用优秀的volatile工具生成的装配代码与不带volatile关键字的程序集代码之间的差异。如果没有易失性,for循环将被优化为零,并且不会发生i的增量或检查。

因此,循环应该编写为:

代码语言:javascript
复制
for(volatile int i = 0; i < 500000; i++); //dummy delay

在嵌入式系统上也可能遇到这种问题,例如当您从多个上下文/线程访问一个变量时。

票数 4
EN

Stack Overflow用户

发布于 2020-11-23 14:37:23

实际上,LED在while循环中切换,但只在调试模式下进行切换。

是的,因为这是唯一一次生成的机器代码包括那些延迟循环。在发布模式下,LED仍然没有切换,除非你需要一个示波器或逻辑分析器来观察输出引脚的状态,以确定它正在切换--你不会仅仅用眼睛看到它:)

在发布模式下,延迟循环将被删除,因为不能以这种方式实现延迟。理想情况下,您应该使用计时器,但作为一种快速攻击,这样做是可行的:

代码语言:javascript
复制
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指向易失性对象,编译器无法优化访问。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64970233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档