1. 抛出问题
在学习C语言,或者面试C语言的时候,常常会遇到这样一个问题:
请解释一下volatile关键词的含义,以及它起到什么作用?
百度出来的答案往往是这样的
但是这个答案究竟在代码中起到什么作用?有什么意义?
2. 背景介绍
我们知道单片机代码中,一般有两种方式:带系统的和不带系统的。在稍微简单一些的项目,或者对时序要求很高的项目中,多采用不带系统的方式开发。在带有4G NBIOT 这些通信应用的项目中,由于往往会用到多个线程进行同步,采用带系统的居多。
不带系统的代码包含初始化部分和大循环部分。
在这个简单点灯代码中,初始化部分,完成了LED的初始化。大循环部分,不断调用LED(ON)和LED(OFF),中间加上SOFT_DELAY的延时,实现LED点亮和熄灭的效果。
SOFT_DELAY是通过Delay函数来定义的。
而Delay函数中,用到了__IO, 也就是volatile关键词修饰的变量。
下面问题来了:如果去掉这个volatile关键词修饰,LED闪烁频率会如何?
动画1:LED快速闪烁的效果
动画2:LED闪烁速度明显变慢
下面,具体的问题来了:
动画1和动画2中的代码,唯一的改变就是:其中一个注释掉了__IO,请问具体是哪一个注释掉了IO?快的那个,还是慢的那个?
3. 分析与解答
要回答这个问题,显然不能靠猜测。我们需要深入理解volatile关键词究竟起到什么作用才行。
当C编译器看到volatile关键词修饰的变量时,它就会知道,这个变量的值是常常会发生变化的(volatile英文含义为易变的)。因此,它就会试图从内存中,去操作和读取这个变量。而当这个词没有被修饰时,它会从寄存器中,直接操作这个变量。
由于寄存器的操作读取速度是大于内存操作读取速度的,因此当去掉关键词volatile之后,就会提高灯闪烁频率。
因此,闪灯慢的是volatile, 闪灯快的不带volatile。
4. 进一步探讨:编译优化
当我们在编译时,选择不同的优化选线,可能会导致LED闪烁频率变化。但是在实际测试中,肉眼并未发现具体的变化,估计可能需要用示波器才能够看出波形的变化。在这里就不展开了。可以从下面的链接进一步查看。
keil优化等级影响STM32 GPIO速度变化 - 知乎 (zhihu.com)
5. 题外话-学习嵌入式的正确姿势
很多人觉得,多敲代码就可以提高学习嵌入式的效率。如果多敲代码能够改善学习效率的话,那最好的程序员应该是打字员。
学习嵌入式或者其他编程技术的最佳方式是:
1. 多做实验,将不同的代码功能实际运行一下,看看效果;
2. 多做代码整理:实验好的结果,一定要有条不紊的整理好,特别是代码模块的接口尽量单独列出来;
3. 多做代码复用:好的工程师是敲代码快么?不是的。好的工程师是在大脑里,还有电脑里,建议了很多功能模块,遇到问题后,可以非常方便的拿出模块,解决问题。学习编程的路径,不仅仅是学习语言,或者学习驱动,而是不断积累功能模块,并把功能模块反复复用,解决问题。
关注我,手把手带你完成智能气象站的设计。
现在就动手,把对应工程编译下载试试看吧。
(24条消息) led点灯代码。代码简单,主要用来验证开发环境。开发环境采用vscode+keil,详见博文-嵌入式文档类资源-优快云文库
纸上得来终觉浅,绝知此事要躬行!
接下来会一步一步带你完成家庭气象站的开发工作,敬请收藏关注,以免下次找不到了。