尽量用最少的文字描述清楚问题。

事情起因是这样的:

  要做遥控小车的平台迁移,STM32开发板无法方便地供电,因此又拿出了尘封的51(STC89C52RC),搭配上最小系统板就可以用排针加杜邦线供电了。

测试的时候出了点问题,51开发板上用作显示的数码管会闪动,而在逻辑正确的情况下是不会出现这个情况的(后来发现数码管的位选段选信号有点小问题)。在排查过程中,一步一步找到了中断处理程序。

51一共有5个中断源,其中有2个定时器中断T0 T1,2个外部中断,1个串口中断。52比51多一个定时器中断T2。

定时器有4种工作模式,T0和T1的M1M0均为01的时候,也即TMOD为0x11时,是工作模式1,为16位定时器。不自动重装初值,需要手动重装初值。

初学51的入门书是郭天祥老师的<新概念51单片机C语言教程>,在第3章第5节讲述定时器中断的时候,为了讲述方便和容易理解,中断服务程序中是这样写的:

void T0_time() interrupt
{
TH0 = (-)/;
TL0 = (-)%;
//...
//...
}

这是在11.0592MHz晶振下50ms来一次中断的重装初值的方法。关于这个的解释是这样的。

在晶振为12M的时候,由于机器周期是12个时钟周期,机器周期为(/12M)* =  (us)
也就是计一个数需要 1us
50ms需要 计50000个数
所要装入的总数是 -=
所要装入的初值是
TH0=(-)/;
TL0=(-)%; 在晶振为11.0592M的时候,机器周期为(/11.0592M)* = x /11.0592 =1.085 (us)
100us,需要计 /1.085 = 92.16个数,取整
所要装入的总数是 -
所要装入的初值是
TH0=(-)/;
TL0=(-)%;

  其实我想说的是,虽然这样可能比较容易看懂(配合注释),但是就把这个表达式放在这儿而不把结果计算出来,会使效率大打折扣!

  其实在50ms下还好,因为总时间比较长,每次计算(65536-45872)/256的时间虽然是固定的,但是百分比较小,相对影响较小。

  当设定中断为100us来一次的时候,会使得计算表达式的时间所占百分比大大提升。由于100us = 0.1ms = 50ms / 500,也就是说,假设65536-92和65536-45872的时间消耗同一个数量级的(100us的时候中断服务程序中重装的初值45872变成了92),计算

 (65536-92)/256 和(65536-92)%256

的时间消耗百分比提升了500倍左右。

举个栗子:

void T0_time() interrupt 1 {
TH0 = (-)/;
TL0 = (-)%;
}

void T0_time() interrupt  {
TH0 = (-)/;
TL0 = (-)%;
}

假设做

TH0 = (65536-45872)/256;
TL0 = (65536-45872)%256;

TH0 = (65536-92)/256;
TL0 = (65536-92)%256;

都需要1us的时间。

在总时间为50ms时,前者所占百分比为 1/50k = 0.002%

在总时间为100us时,后者所占百分比为 1/100 = 1.000%

尼玛差了500倍左右!能想象吗?

别看绝对数字,因为这1us是我编出来的,实际上51属于低速芯片,而且还有其他事要做。事实上上中断里面除了重装初值还要做其他事情,却让这么一个简单的但没有化简的重装初值的表达式给占用了太多资源和时间。。

我好像说了好多废话,那我就直接说结论吧:就只是把结果计算出来,也就是把

TH0 = (65536-92)/256;
TL0 = (65536-92)%256;

换成

TH0 = 255;
TL0 = 164;

其他啥都不改,然后把程序下载到芯片上,数码管的变化已经可以由人眼分辨我会乱说?

有的效率提升其实很简单。

PS1:我感觉51真的很慢。。或者应该说资源有限,需要尽量优化,或者不要轻易使用很小的定时器————>它忙不过来。

举个例子吧,还是刚才那个项目:

void T0_IRQHandler() interrupt
{
TH0=(-)/;
TL0=(-)%; pwmOutput();
}

也就是52 x 1.085 = 56.42 (us)来一次中断

当中断程序中不做其他事情,也就是没有pwmOutput()这个函数时,当然是能运行的。

而加入一个这样的pwmOutput()之后:

void pwmOutput(){
/* left side */
if(directionLeft == ){
PWM_IN1_ON();
PWM_IN2_OFF();
}
else if(directionLeft == ){
PWM_IN2_ON();
PWM_IN1_OFF();
}
// else if(directionLeft == 0){
// PWM_IN1_OFF();
// PWM_IN2_OFF();
// }
//
// /*right side*/
if(directionRight == ){
//forward
PWM_IN3_ON();
PWM_IN4_OFF();
}
//else if(directionRight == 2){
// //backward
// PWM_IN4_ON();
// PWM_IN3_OFF();
// }else if(directionRight == 0){
// PWM_IN3_OFF();
// PWM_IN4_OFF();
// } }

我注释掉了一部分。剩下的就很接近它的极限了。也就是说这样是能运行的,如果去掉/*left side*/的第二个else if,那么,pwmOutput()的运行时间将超过56.42 us,还没等这个函数运行完,下一次中断又来了。。也就是卡在这里出不去了0.0

//注:
void PWM_IN1_ON(){
PWM_Ch1 = ~PWM_Ch1;
} void PWM_IN1_OFF(){
PWM_Ch1 = ;
} //直接把PWM_Ch1写上去会稍微强一点,因为不用跳转了

PS2:

好像。。不对,上面的分析好像错了。。。(PS1是对的),因为是设定完初值之后定时器才开始工作的,所以放表达式好像和之前所说的效率无关了。。因为反正计算的这段时间它是停着的,只有等到计算好了之后才会生效。这样来说,

TH0=(65536-92)/256;
TL0=(65536-92)%256;

TH0=255;
TL0=164;

的差别只在于计时的准确性上,比如前者一个计时周期是1us + 0.01us,后者一个计时周期是1us + 0.001us

积累多了会有一点准确性上的误差,在不要求那么那么精准的地方还是推荐用表意更好的方式,demo方便阅读。如果是封装好了的那就另说了,因为毕竟每次都要重新计算确实有点浪费,封装好了就默认能看懂里面的,所以可以采用省时间省资源的方式。

PS3:

但是刚才我分明是看到了修改之后有变化的。。绝对没有自行脑补。。

提升效率(时间准确性),减少时间和资源的消耗——由89C52/89C51的定时器中断引出的一些问题的更多相关文章

  1. mysql提升效率

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  2. Java日期时间API系列30-----Jdk8中java.time包中的新的日期时间API类,减少时间精度方法性能比较和使用。

    实际使用中,经常需要使用不同精确度的Date,比如保留到天 2020-04-23 00:00:00,保留到小时,保留到分钟,保留到秒等,常见的方法是通过格式化到指定精确度(比如:yyyy-MM-dd) ...

  3. Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力)

    系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...

  4. paip.提升效率--僵尸代码的迷思

    paip.提升效率--僵尸代码的迷思 僵尸代码是指你的代码库里被注释掉的那部分代码, 很少去使用它,就像僵尸一样, 看雷kill-the-zombies-in-your-code ========== ...

  5. 纯前端表格控件SpreadJS以专注业务、提升效率赢得用户与市场

    提起华为2012实验室,你可能有点陌生. 但你一定还对前段时间华为的那封<海思总裁致员工的一封信>记忆犹新,就在那篇饱含深情的信中,我们知道了华为为确保公司大部分产品的战略安全和连续供应, ...

  6. Android测试提升效率批处理脚本(三)

    前言: 前面放出过几次批处理,这次只放一个环境检查的被管理员给打回来了,不得不再找找几个有含金量的放出来,请看正文~~~ 目录 1.Android环境检查 2.Android内存监控 3.模拟蓝牙手柄 ...

  7. Android测试提升效率批处理脚本(二)

    前言: 前面放出过一次批处理,本次再放出一些比较有用的批处理(获得当前包名.查看APP签名信息等),好长时没来写博客了,简单化,请看正文,更多脚本尽请期待~~~(不定期) 目录 1.[手机录屏(安卓4 ...

  8. paip.提升效率---filter map reduce 的java 函数式编程实现

    #paip.提升效率---filter map reduce 的java 函数式编程实现 ======================================================= ...

  9. paip.提升效率--调试--日志系统日志参数含义---python

    paip.提升效率--调试--日志系统日志参数含义---python #同时向控制台和文件输出日志 #日志参数含义 import logging log_format = '%(filename)s ...

随机推荐

  1. Java继承中成员方法的overload(重载/过载)

    如果Java基础类有一个方法名被"过载"使用多次,在衍生类里对那个方法名的重新定义就不会隐藏任何基础类的版本.所以无论方法在这一级还是在一个基础类中定义,过载都会生效. publi ...

  2. GJM : Unity3D - UI - UI边缘流光特效小技巧 [转载]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  3. 初识Hibernate 缓存

    生活就像一杯咖啡,让你我慢慢的品尝,品尝它的苦涩和甘甜...... 一.什么是Hibernate缓存. 解析:白话来说就是缓存数据的容器 官方标准点缓存:是计算机领域的概念,它介于应用程序和永久性数据 ...

  4. JAVA多线程之间共享数据BlockingQueue介绍

    在JAVA的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利. ...

  5. js的一些属性

    js attribute(): setAttribute():element.setAttribute(name,balue) getAttribute():element.getAttribute( ...

  6. [deviceone开发]-毛玻璃效果示例

    一.简介 do_Bitmap组件可以把图片加载为内存里的Bitmap对象,能够对这个对象做各种图形化处理.目前只有3种处理,圆角,毛玻璃,灰度.以后会添加更多. 二.效果图 三.相关下载 https: ...

  7. iOS常用第三方库

    1.AFNetworking 轻量级的通讯类库,使用非常简单. 下载地址:https://github.com/AFNetworking/AFNetworking   2.FMDB fmdb是一个数据 ...

  8. ABAP语言常用的系统字段及函数

    常用的系统变量如下: 1. SY-PAGNO当前页号 2. SY-DATUM当前时间 3. SY-LINSZ当前报表宽度 4. SY-LINCT当前报表长度 5. SPACE空字符 6. SY-SUB ...

  9. ABAP可以提高效率的小语法

    ADD dobj1 TO dobj2. Effect This statement has the same effect as the statement COMPUTE dobj2 = dobj2 ...

  10. 对称密码-DES和3DES

    最近在看信息安全的知识,就总结了一下自己所学到知识. 先说一下什么是对称密码算法,什么是对称密码算法呢?对称密码算法是指有了加密密钥就可以推算出解密密钥,有了解密密钥就可以推算出加密密钥的的算法. 那 ...