历史上的今天
今天是:2024年08月24日(星期六)
2021年08月24日 | 51单片机-隐形漏洞
2021-08-24 来源:eefocus
1.漏洞代码
假如就按上一讲说的书写方式,实现定时50ms间隔的流水灯。
#include #include void main() { LED_Init(); //初始化LED硬件模块 EA = 1; //闭合总中断开关 TMOD = 0x01; //设置定时器0为工作模式1 TH0=( 65536-( (50000*110592)/120000 ) )/256;//设置定时时间为50ms TL0=( 65536-( (50000*110592)/120000 ) )%256; ET0 = 1; //闭合定时器0中断的开关 TR0 = 1; //启动定时器0 while(1); } void TIM0_IRQHandler() interrupt 1 { static u8 i; TH0=( 65536-( (50000*110592)/120000 ) )/256;//重新设置定时时间为50ms TL0=( 65536-( (50000*110592)/120000 ) )%256; P0=~(0x01< i++; if(i>=8)i=0; } 下载进开发板发现根本不是间隔50ms! 进行仿真查看i每次间隔自加所花的时间居然是11ms左右。 2.解析漏洞 首先我们要知道,51单片机能存储最大的一个整型数的大小只有4个字节,也就是最多能记忆这个数到4294967296(2的32次方),而在 “( 65536-( (50000)*110592)/120000 )”中明显不能把“(50000*110592)”给临时存储,因为这个等式的得数已经大过2的32次方。所以我们的定时器才会无法实现准确的50ms定时。如果我们对编程没有一定的积累是很难察觉出这个隐形漏洞的。 解决办法就是,我们的定时最小单位只能是10微秒,也就是定时的时间必须是10微秒的整数倍。书写如下 TH0=( 65536-(5000*110592)/12000 ) )/256; 把之前的“50000”和“120000”都去掉一个零,这样就可以准确的定时50ms了,因为“(5000)*110592)”没有超过2的32次方,读者自行修改本讲提供的代码中的4处之后下载进开发板观察现象是不是又实现50ms的间隔流水了。 3.再次优化书写 上处的5000意为定时的是50ms,也就是5000*10微秒,但我们希望潜意识里假如要定时200微秒,如果写成20我们的思维还要绕个弯再把20默默乘以10才领悟出这是定时200微秒。 倒不如这样,我们看到关键的数字是多少那就是要定时多少微秒。 比如看到关键数字为50000时就知道定时的是50000微秒。 所以我们这样改写:TH0=( 65536-( (50000/10)*110592)/12000 )/256; 这样既保证了“(50000/10)*110592”没有超过2的32次方,也使“50000”更直观的让我们知道要定时的是50000微秒。 但是大家要记住,关键数字必须是10的整数倍,如果想定时个208微秒,“(208/10)”还是等于20,所以定时时间还是200微秒。 
上一篇:51单片机-定时器初始化新写法
下一篇:51单片机-代码参考
史海拾趣
|
做技术在慢慢培养自己的奴性,变得谨小慎微 刚毕业的时候啥也不懂,在公司自然夹着尾巴做人. 工作几年后,技术越来越纯熟了,可是也知道高手时时刻刻在自己的身边. 对自己带的新人,客客气气.对上司恭恭敬敬. ...… 查看全部问答> |
|
在天元买的j-link v8版,经过几天努力,终于可以通过sjflash 烧写nandflash了,经过试验,支持s3c2440烧写k9s1208 和 k9g1g08,s3c2410没有试验!!!!… 查看全部问答> |
|
前言: 近年,“云计算”的到来给人们的生活带来了方便、快捷以及前所未有的体验,然而“云计算”时代的到来也意味着“大数据”时代的到来,有资料表明,仅2011这一年就产生了大概4EB(2^60B)的数据量,而且在当前的数字化经济当中,每18个月数 ...… 查看全部问答> |
|
1引言 电导率作为重要的电化学分析参数。其测量已经广泛 应用于化工、冶金、生物、医学、粮食和水利等生产与科 研部门【I卅。随着生产和科研的不断深化,对电导率测量 的精度要求越来越高,对其测量方法的研究具有重要的实 际意义。 电导率的 ...… 查看全部问答> |




