前言:我自己装了MDK后,按照讲课老师讲解,编写了一个stm32通过寄存器控制LED灯闪烁的程序,结果发现led灯不闪烁,但是程序写的没问题啊,和视频中讲师的源码一模一样,但就是,运行不成功,led灯常亮,并没有闪烁。百思不得其解。后来发现是volatile的问题,和keil优化级别设置问题导致的。
我的keil工程优化级别的默认设置如下图:优化级别设置默认为-O1
解决stm32点亮LED不闪烁问题方法有两个:
方法一:更改优化级别为-O0
方法二:while循环中出现的变量,定义时加上关键字volatile
/*
所用芯片---STM32F047ZET6
LED0 --->PF9---->GPIOF组的第9个引脚
LED_ON ---0
LED_OFF ---1
寄存器设置套路,见参考手册
*/
#define RCC_BASEADDR (0x40023800)
#define RCC_AHB1ENR (*( unsigned int *)(RCC_BASEADDR+0x30))
#define GPIOF_BASEADDR (0x40021400)
#define GPIOF_MODER (*( unsigned int *)(GPIOF_BASEADDR+0x00)) //端口模式
#define GPIOF_OTYPE (*( unsigned int *)(GPIOF_BASEADDR+0x04)) //输出类型
#define GPIOF_OSPEEDR (*( unsigned int *)(GPIOF_BASEADDR+0x08)) //输出速度
#define GPIOF_PUPDR (*( unsigned int *)(GPIOF_BASEADDR+0x0C)) //上下拉
#define GPIOF_ODR (*(volatile unsigned int *)(GPIOF_BASEADDR+0x14))//输出控制,这里要加volatile,因为该变量出现在while循环中,有可能被编译器优化
static void delay(volatile unsigned int ns) //这里要加volatile ,该变量出现在while循环中,有可能被编译器优化
{
while(ns--);
}
int main(void)
{
//1.使能F组时钟,必须操作以下这一步:开启 GPIOF 组时钟!!!
RCC_AHB1ENR |= (unsigned int)(0x01<<5);
//debug:如果时钟不使能的话,所有寄存器的值都不会改变
//2.设置 PF9 引脚为输出模式
GPIOF_MODER &= ~(unsigned int)(0x03<<9*2);
GPIOF_MODER |= (unsigned int)(0x01<<9*2);
//3.配置 PF9 引脚的输出类型为:推挽输出
GPIOF_OTYPE &= ~(unsigned int)(0x1<<9);
//4.配置 PF9 引脚的输出速度为:25MHz ,这个影响不大可以忽略
GPIOF_OSPEEDR &= ~(unsigned int)(0x03<<9*2);
GPIOF_OSPEEDR |= (unsigned int)(0x01<<9*2);
//5.配置 PF9 引脚为上拉 ,这个影响不大可以忽略
GPIOF_PUPDR &= ~(unsigned int)(0x03<<9*2);
GPIOF_PUPDR |= (unsigned int)(0x01<<9*2);
//输出
//6、配置 PF9 引脚的输出数据寄存器的值,目的就是为了控制PF9引脚高低电平
while(1)
{
GPIOF_ODR &= ~(unsigned int)(0x01<<9);//置0亮
delay(0xFFFFF);
GPIOF_ODR |= (unsigned int)(0x01<<9);//置1灭
delay(0xFFFFF);
}
return 0;
}
debug:没有勾选reset and run。发现下载完程序后不运行。
总结:当程序出现反常现象,说明有自己不知道知识,或有自己没有观察到的信息。要冷静,相信事出反常必有妖,冷静的进行程序的调试,敏锐细心的观察不寻常之处。当然,通过调试解决问题也需要知识和经验,当自己不知如何调试时,可以向身边懂得人请教,或者去百度搜索问题,问题描述要尽可能的包括关键信息,如自己通过什么代码编辑器,调试的是什么样的程序,现象等等。不把问题当回事,耐心,冷静面对。