众所周知,相比于其他编程语言,c语言在编写嵌入式编程中有着绝对的优势。但它总也有缺点的:它的时序性比较差,不容易编写精准的延时。而在编写嵌入系统驱动程序时,常常需要比较精确的软件延时,这使得c语言的“劣势”暴露了出来,一般都只能通过嵌入汇编的方式实现。例如,在1mhz工作频率下需要延时10us,就需要嵌入10句“空操作”指令,显然在书写上比较难堪。本文提出一种简化书写的延时方案,使用带参数的宏构来造微小时间片,可以实现完全精确的软件延时,大大方便了驱动程序及软件模拟通信协议的编写。
说明:以下皆为icc avr平台下的讨论,对avr系列所有型号的单片机皆有效。至于其他平台,可据此方案自行修改和移值。
该方案的实现方法其实很简单:
首先定义n个宏,分别调用 1 ~ n 个汇编“空操作”指令,如:
#define nop_1 asm(“nop”) //延时一个时钟周期
#define nop_2 nop_1; asm(“nop”) //延时两个时钟周期
#define nop_3 nop_2; asm(“nop”) //延时三个时钟周期
#define nop_4 nop_3; asm(“nop”) //延时四个时钟周期
……
#define nop_40 nop_40; asm(“nop”) //延时40个时钟周期
然后利用“##”操作符,实现带参数宏的延时:
#define nop(n) nop_##n //延时 n个时钟周期
操作符的作用是把两个部分的内容连成一个内容。就是说,nop(3)展开后成为nop_3,nop(4)展开后成为nop_4,等等。因此,定义上述宏之后,就可通过调用nop(n)语句实现精确软件延时。例如:
nop(4); //延时4个时钟周期
上述语句展开过程如下:
nop_3 ; asm(“nop”);
nop_2; asm(“nop”); asm(“nop”);
nop_1; asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
正好延时4个时钟周期
不过,上面的宏还不够完善,如果试图使用下面的语句,程序将会出现漏洞。
if(表达式)
nop(3);
else
nop(4);
这是因为nop(n)宏展开之后,不是一个语句,而是变成n个语句。故必须用花括号括起来,程序才能运行正确。即应该改为:
if(表达式)
{
nop(3);
}
else
{
nop(4);
}
如果把nop(n)宏的定义改为:
#define nop(n) do{ nop_##n ; }while(0)
则nop(n)宏展开之后只形成一个语句,将不会出现上面的问题。
但是要注意,“##”操作符只能按照原样把两边的内容连在一起。故nop(n)的参数必须是具体的常量,即只能是数字,并且,与该数字相对应的宏nop_n已必须已经定义。
例如:
“nop(3+4);”语句展开之后,将将变成“nop_3+4;”,出现语法错误;
又如:
“nop(a);”语句展开之后,将将变成“nop_a;”,而“nop_a;”未定义。
只有这样的语句才是正确的调用:
nop(20); //延时20个时钟周期
将上述方案整理成一个头文件,以后就可以任意调用了。下面是整理好的头文件:
注意:该文件不宜作长时间的延时。长时间的延时将会调用大量的“空操作”指令,占用大量的程序指令空间。这个问题将在v2.0版本中解决。
ATX电源的光电耦合器检测好坏
华为云桌面--引领移动办公新潮流
太阳能电池发电原理介绍
我国云服务步入发展快车道,云计算为数字经济按下了“快进键”
传江淮汽车拟45亿元转让蔚来工厂资产?蔚来回应
C语言里如何编写精确的微量延时
企业CIO将如何采用人工智能技术?以及将来如何开发他们的业务用例?
NP4407SR - j30v p通道增强模式MOSFET
75%的物联网项目以失败告终的原因是什么?
2019智能制造大会”即将于2019年9月16日在上海闵行隆重举办
小米超级性价比!百元神器红米4A、千元神器红米Note4、小米5sPlus
WiFi5和6标准有何区别?5G的发展对WiFi意味重大
凸轮轴传感器的原理及作用
区块链游戏Dapp未来的发展要创新更要合规
小米6什么时候发布?小米6最新消息:小米6价格一泄露,MIUI就出招,要开始搞事情了!
强大的以太网物理层解决方案,适用于恶劣工业环境中的时间关键型通信
河道治理多参数控制器监测系统PH一体式平台有哪些
罗德与施瓦专注5G广播,展示可持续和互联的未来技术
高亮度LED的结构特点和应用
出资600万成立合资公司,恒太照明在下一盘什么棋?