8.隐形漏洞

发布日期:2020-12-26 09:10:06 来源:网络转载

1.漏洞代码

假如就按上一讲说的书写方式,实现定时50ms间隔的流水灯。

#include <reg52.h> 
#include <function.h>//详见第六章第8讲

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);
    i++;
    if(i>=8)i=0;
}

下载进开发板发现根本不是间隔50ms!

进行仿真查看i每次间隔自加所花的时间居然是11ms左右。

8.5.png


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微秒。

关键词 :
网站违法和不良信息举报邮箱:23139485@qq.com
CopyRight@2020-2030 www.haoapp8.cn All Rights Reserved.C语言学习网版权所有 粤ICP备15061369号
免责声明:本站内容来源于用户自行提供或网络收集,其真实性、准确性和合法性,www.haoapp8.cn不提供任何保证,亦不承担任何法律责任.而产生的法律关系及法律纠纷,由您自行协商解决。