Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字

这篇具有很好参考价值的文章主要介绍了Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、问题描述

在学习野火霸天虎F407寄存器点亮LED时,出现实验现象:LED灯不亮,野火霸天虎F407资料。
Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字,# STM32,arm开发,嵌入式开发,stm32,单片机

main.c代码如下:

#include "stm32f4xx.h"

void Delay(unsigned int count);

int main(void)
{   
#if 0
    /* 第一步:开启GPIO端口的时钟 */
    /* 打开GPIOF端口的时钟 */
    *(unsigned int *)(0x40023800+0x3f0) |= (1<<5);
    
    /* 第二步:控制GPIO的方向 */
    /* GPIOF 配置为输出 */
    *(unsigned int *)(0x40021400+0x00) &= ~((0x03) << (2*6));
    *(unsigned int *)(0x40021400+0x00) |= (1 << (2*6));
    
    /* 第三步:控制GPIO的数据输出寄存器 */
    /* PF6 输出高电平 */
    *(unsigned int *)(0x40021400+0x14) |= (1 << 6);
    /* PF6 输出低电平 */
    *(unsigned int *)(0x40021400+0x14) &= ~(1 << 6);
    
#elif 0
    /* 第一步:开启GPIO端口的时钟 */
    /* 打开GPIOF端口的时钟 */
    RCC_AHB1ENR |= (1<<5);
    
    /* 第二步:控制GPIO的方向 */
    /* GPIOF 配置为输出 */
    GPIO_MODER &= ~((0x03) << (2*6));
    GPIO_MODER |= (1 << (2*6));
    
    /* 第三步:控制GPIO的数据输出寄存器 */
    /* PF6 输出高电平 */
    GPIO_ODR |= (1 << 6);
    /* PF6 输出低电平 */
    GPIO_ODR &= ~(1 << 6);
#elif 0
    //任务1-把其他两个灯也点亮
    RCC_AHB1ENR |= (1<<5); //开启GPIO端口时钟
    
    //设置GPIOF6为推挽输出
    GPIO_MODER &= ~((0x03) << (2*6));  
    GPIO_MODER |= (1 << (2*6));
    GPIO_ODR |= (1 << 6);
    GPIO_ODR &= ~(1 << 6);
    //设置GPIOF7为推挽输出
    GPIO_MODER &= ~((0x03) << (2*7));  
    GPIO_MODER |= (1 << (2*7));
    GPIO_ODR |= (1 << 7);
    GPIO_ODR &= ~(1 << 7);
    //设置GPIOF8为推挽输出
    GPIO_MODER &= ~((0x03) << (2*8));  
    GPIO_MODER |= (1 << (2*8));
    GPIO_ODR |= (1 << 8);
    GPIO_ODR &= ~(1 << 8);

#elif 1
    //任务1-把其他两个灯也点亮
    RCC_AHB1ENR |= (1<<5); //开启GPIO端口时钟
    
    //设置GPIOF6为推挽输出
    GPIO_MODER &= ~((0x03) << (2*6));  
    GPIO_MODER |= (1 << (2*6));
    //设置GPIOF7为推挽输出
    GPIO_MODER &= ~((0x03) << (2*7));  
    GPIO_MODER |= (1 << (2*7));
    //设置GPIOF8为推挽输出
    GPIO_MODER &= ~((0x03) << (2*8));  
    GPIO_MODER |= (1 << (2*8));
    
    while(1)
    {
        GPIO_ODR &= ~(1 << 6);
        Delay(0xfffff);
        GPIO_ODR |= (1 << 6);
        Delay(0xfffff);
        
        GPIO_ODR &= ~(1 << 7);
        Delay(0xfffff);
        GPIO_ODR |= (1 << 7);
        Delay(0xfffff);
        
        GPIO_ODR &= ~(1 << 8);
        Delay(0xfffff);
        GPIO_ODR |= (1 << 8);
        Delay(0xfffff);
    }  
 #endif 
}


//延时函数
void Delay(unsigned int count)
{
    for(;count!=0;count--);
}

void SystemInit(void)
{
    /* 函数体为空,目的是为了骗过编译器不报错 */
}

/*
1-把其他两个灯也点亮
2-实现三个灯闪烁(时间的控制使用软件延时)
*/

二、问题分析

通过分析main.c代码,导致出现上述现象的间接原因是延时函数没有起作用。检查延时函数的实现代码,并没有错误。这不禁使我想起《程序员的自我修养——链接、装载、库》一书所提到的程序源代码经过预编译-》编译-》汇编-》链接,所以极大可能是编译器在编译过程中优化掉了我的延时函数,使得整个程序不能按照预定功能实现。

打开keil5的调试功能,查看对应main.c的反汇编文件:
经过优化的delay函数:
Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字,# STM32,arm开发,嵌入式开发,stm32,单片机
未经过优化的delay函数:
Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字,# STM32,arm开发,嵌入式开发,stm32,单片机
优化之后的 delay 函数没有for循环延时操作,因此失去延时的效果。

三、问题解决

3.1 降低ARM Compiler version

在Target设置界面下,Code Generation默认的是ARM Compiler version 6。
Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字,# STM32,arm开发,嵌入式开发,stm32,单片机
将ARM Compiler version 6改为ARM Compiler version 5即可。Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字,# STM32,arm开发,嵌入式开发,stm32,单片机

3.2 volatile关键字修饰

volatile关键字影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错。volatile关键字最通俗的解释是,告诉编译器这个变量我有其他用,不要给我随便优化掉。

原延时函数

//延时函数
void Delay(unsigned int count)
{
    for(;count!=0;count--);
}

添加volate关键字修饰

//延时函数
void Delay(volatile unsigned int count)
{
    for(;count!=0;count--);
}

推荐使用方法2,原因如下:

1.自定义延时函数中使用 volatile 去声明 val 变量可以解决编译器优化带来的延时失效问题;
2.编译器优化可以使代码更加精炼,执行效率更高。

参考资料

1. Keil AC5 和 AC6的一些区别
2. 编译器优化对自定义延时程序的影响(volatile详解实验一)
3. C语言丨深入理解volatile关键字文章来源地址https://www.toymoban.com/news/detail-518067.html

到了这里,关于Keil5中写的软件延时函数不起作用现象解析_ARM_Compiler_volatile关键字的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • keil5软件仿真stm32设置 和 调试技巧

    不想用板子的时候或没有板子的时候,软件仿真更方便调试快速验证; KEIL两大功能:1.编译器功能;2.调试器功能 1.选择 Use simulaor 代表要使用软件模拟仿真 2.“dialog DLL”的内容是 DARMSTM.DLL ,表示使用STM系列 3.把“dialog DLL”的内容换成 TARMSTM.DLL , 4.parameter”的内容是 -pSTM

    2024年02月13日
    浏览(51)
  • keil5.38 debug配置STlink调试,软件闪退

    keil5.38 debug配置STlink调试,软件闪退 因为新版的Keil加入了盗版下载器的校验机制 百度云盘 链接:旧版版本STLINK文件连接 提取码:7epc 解压下载文件后得到STlink文件夹,替换到新版本的keil的ARM目录即可

    2024年02月11日
    浏览(48)
  • Keil5,ARM编译器 软件优化注意事项

    循环是大多数程序中的常见结构。由于大量的执行时间通常花费在循环中,因此值得关注时间关键循环。 如果不谨慎地编写,环路终止条件可能会导致大量开销。在可能的情况下: 使用简单的终止条件。 写入倒计时到零循环。 使用  unsigned int  类型的计数器。 测试与零的

    2024年02月03日
    浏览(49)
  • keil5软件安装&开发环境搭建教程(mdk,c51通用)

    这是我在csdn上写的第一篇文章,心情激动兴奋。因为之前都是看别人写的博客,从来没想过自己去写一篇,在学长的鼓励下,尝试完成人生第一篇博客。仍有不足,希望大佬多多指正! 写这篇的目的是因为keil5的安装是许多人入门嵌入式的第一步,而且以后遇到许多不知名的

    2024年02月05日
    浏览(52)
  • Keil5软件安装方法(兼容stm32与c51方法)

    目录 一、下载软件包 二、安装软件 1、安装C51v960a.exe (1)右键以管理员权限运行程序  (2)开始安装软件  (3)勾选协议 (4)选择安装路径  (5)填写名字与邮箱  (6)等待安装 (7)安装完毕  (8)以管理员打开软件 (9)打开注册机 (10)破解成功 2、安装mdk528.exe

    2023年04月24日
    浏览(40)
  • STM32——01-开发软件Keil5及STM32CubeMX的安装

    1.1开发环境的安装  编程语言:C语言 需要安装的软件有两个:Keil5和STM32CubeMX 安装         安装包(不需要太新,以 MDK324 为例,最新的 MDK327 有问题)         安装过程一路下一步即可(建议不要安装在 C 盘)         安装路径一定不要有中文或空格!!(重要

    2024年02月08日
    浏览(46)
  • 小游戏:人生中写的第一个小游戏——贪吃蛇(C语言)

            小编开了一个关于游戏的专栏,主要是运用easyx图形库进行的。        第一章:人生中写的第一个小游戏——贪吃蛇(C语言)         这个游戏的代码我在gitee上发布了,大家如果不嫌弃,可以进入这个网址进行查看和复制:https://gitee.com/rising-sun-1。      

    2024年02月09日
    浏览(57)
  • keil5出现‘Target not created‘ keil5出现‘Target not created‘

    新建工程中写了main函数进行编译时出现错误的问题: 查找报错的关键提示: cannot open source input file \\\"core_cm3.h\\\": No such file or directory   #include \\\"core_cm3.h\\\" 这是因为你装的MDK版本太新了,比如MDK5.12/5.13,它们不会从MDK安装目录去查找头文件。 所以导致这个错误。 解决方法如下:

    2024年02月11日
    浏览(45)
  • XmlDocument.SelectNodes 不起作用

    今天采用Xpath读取Xml节点,怎么都读不出。 错误代码如下: 经排查 dotnet 文档,发现代码编写没有问题。文档描述如下: 文档示例如下: 示例代码: 示例XML: 自己程序采用Xml:

    2024年02月10日
    浏览(42)
  • Swagger传参不起作用

    本来是在swagger上面测试的,但是参数没有传进来,debug发现传的courseId为null 这个肯定就是传参的问题 拿去postman测试 发现结果正常   这时候就应该考虑是swagger的问题了 这个时候发现swagger上面的ParameterType是body类型的 那就好解决了,自己的请求地址是代码拼接类型的,也就

    2024年02月02日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包