打印

软件无累积误差的定时中断程序模板,供初学者学习和行家

[复制链接]
楼主: xwj
手机看帖
扫描二维码
随时随地手机跟帖
41
dengm| | 2007-7-28 09:40 | 只看该作者 回帖奖励 |倒序浏览

还是 asm 高效率 (12Mhz)

$MOD51
    STACK_BUF EQU 60H
    T0_CNT DATA 20H
    F_1SEC BIT T0_CNT.4 ; 12 MHz 
    F_SEC  BIT T0_CNT.7     

    ORG 0000H
      AJMP START
      NOP
    ORG 000BH  ; INT T0
      JBC F_1SEC, SUB_1SEC
         INC T0_CNT
         NOP
INT_RET: RETI
         NOP
;---------------------------------      
    ORG 0088H 
SUB_1SEC:
      ORL TL0, #0C0H  ; 0c0h 的 Bit 0 to 5 为 "0" 
      ORL TH0, #0BDH  ; 必要时可与下一语句交换位置
      ACALL INT_RET
      INC T0_CNT
;*****  1 SEC SERVICE
      ;.......
      SETB F_SEC
      ;.......
      RET
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      
START:
     MOV SP, #(STACK_BUF-1)
     MOV T0_CNT, #0 
     ; Configure Timer 0
;    - Mode                   = 1
;    - Interrupt              = ENABLED
;    - Clock Source           = INTERNAL
;    - Enable Gating Control  = DISABLED
      MOV   TMOD, #01h  ;
      ;setb IE.1
      MOV IE, #10000010B
      setb TR0   ;TCON.4 start timer
      NOP
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
MAINLOOP:
      SJMP MAINLOOP
;______________________________________
           END
;----------------------------
      

使用特权

评论回复
42
cbbs| | 2007-7-28 10:00 | 只看该作者

xwj的是完全可行的


所以,应该改为 TL0 += CONL; 这个CONL 是多少可以自己灵活设定,和晶振有关, 不过还要注意,别这个时候进入其他中断程序

===============》
当TL0 += CONL结果大于255发生进位了呢?



古版的程序用的是T2,具有硬件自动充填的功能?

使用特权

评论回复
43
农民讲习所| | 2007-7-28 10:03 | 只看该作者

使用TL0 += CONL;之类的,都是需要进农民讲习所学习的。

使用特权

评论回复
44
xwj|  楼主 | 2007-7-28 10:05 | 只看该作者

fsaok ,你自己才是空谈哦

可以肯定你从来就没仔细看过1楼的贴,却每次都是想当然的妄下结论

Keil汇编的代码就在后面,你竟然看不到?

TL0 += CONL,当CONL较大时必然溢出,而随机的晶振频率和定时间隔你不可能保证CONL的值为0,所以必须考虑进位;
而且,你以为TL0 += CONL就不用修正吗?就不会被打断吗??


加变量还是加常数的问题,这个实际上没有区别,因为我的定时器是复用的,要一变化的频率中断。而且重载常数代码已经包括在里面了,去看屏蔽的对应行吧


对于二字节加法,必然不是一个指令能完成的,也就不能排除计算时翻转、溢出的可能

你自己也知道:“还要注意,别这个时候进入其他中断程序”,那要是别的中断打断它呢???



再次强调:
    这是一个普遍适用的模板,考虑了各种极端情况和可能下的正确性。如果某种可能不存在,当然可以去掉对应的保护代码



空谈是没有用的,上机试一下吧,
fsaok ,拜托你每次发言前自己先看清楚别人的帖子,也“上机试一下吧”

使用特权

评论回复
45
xwj|  楼主 | 2007-7-28 10:14 | 只看该作者

不可否认,需要快的地方 用汇编确实能快很多

C编译器再怎么优化都会多出很多可以省略的参数传递
毕竟它考虑的更多的是子程序、宏的通用性和普适性,入口出口的统一性等

对于数组、指针等处理的汇编代码,有时看着真的很上火
--太笨了!
:-)

使用特权

评论回复
46
农民讲习所| | 2007-7-28 10:22 | 只看该作者

你们的眼光怎么都放在这种局部细节上?

很多人在这种局部细节上过分追求,反而在大的层面上做着相反的消耗资源的事情。

使用特权

评论回复
47
农民讲习所| | 2007-7-28 10:24 | 只看该作者

就XWJ的例子,明显缺乏大局观。

使用特权

评论回复
48
xwj|  楼主 | 2007-7-28 10:34 | 只看该作者

任何事情有一利就必有一弊,只看你是怎么取舍的

既然强调“软件零误差',而我又多余强调了个“普适性”,那么其他的自然是次位考虑的

教学模板,你却非要从里面强调出个“局部细节上过分追求”,“明显缺乏大局观”,那我也只能向你致以如滔滔江水般连绵不绝,又有如黄河泛滥一发不可收拾的无限景仰:
“你实在是太有才了!”

使用特权

评论回复
49
xwj|  楼主 | 2007-7-28 10:38 | 只看该作者

dengm 采用的是一秒重载一次初值的方法

还用了中断重入

但我个人认为:
      ORL TL0, #0C0H  ; 0c0h 的 Bit 0 to 5 为 "0" 
      ORL TH0, #0BDH  ; 必要时可与下一语句交换位置
应该分别改为ADD和ADDC更严谨些,
当然,如果T0是唯一的最高优先级那么另说了

使用特权

评论回复
50
dengm| | 2007-7-28 10:44 | 只看该作者

re: xwj

$MOD51
    STACK_BUF EQU 60H
    T0_CNT DATA 20H
    F_1SEC BIT T0_CNT.4 ; 12 MHz 
    F_SEC  BIT T0_CNT.7     

    ORG 0000H
      AJMP START
      NOP
    ORG 000BH  ; INT T0
      JBC F_1SEC, SUB_1SEC
         INC T0_CNT
         NOP
INT_RET: RETI
         NOP
;---------------------------------      
    ORG 0088H 
SUB_1SEC:
      MOV T0_CNT, A
      CLR EA      
      PUSH PSW
      CLR TR0
      MOV A, TL0
      ADD A, #LOW(0BDC0H + 6)
      MOV TL0, A
      MOV A, TH0
      ADDC A, #HIGH(0BDC0H+6)
      MOV TH0, A
      SETB TR0
      POP PSW
      SETB EA
      MOV A, #1
      XCH A, T0_CNT
      ACALL INT_RET
;*****  1 SEC SERVICE
      ;.......
      SETB F_SEC
      ;.......
      RET
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      
START:
     MOV SP, #(STACK_BUF-1)
     MOV T0_CNT, #0 
     ; Configure Timer 0
;    - Mode                   = 1
;    - Interrupt              = ENABLED
;    - Clock Source           = INTERNAL
;    - Enable Gating Control  = DISABLED
      MOV   TMOD, #01h  ;
      ;setb IE.1
      MOV IE, #10000010B
      setb TR0   ;TCON.4 start timer
      NOP
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
MAINLOOP:
      SJMP MAINLOOP
;______________________________________
           END
;----------------------------

使用特权

评论回复
51
农民讲习所| | 2007-7-28 10:46 | 只看该作者

从前面回帖的农民同志已经看到在误导优秀的农民同志走弯

别加“普适性”三个字,这三个字的份量还是蛮重的。

大家还是要到我这农民讲习所来进修,俺可以告诉你们好处:
学会了,大小程序通吃。俺这套教材可以做几百字节的程序,也可以做50万行代码的ARM程序。这就是学会理论的好处,是大局观,哪些芝麻大的技巧是少儿不宜。

使用特权

评论回复
52
农民讲习所| | 2007-7-28 10:56 | 只看该作者

设计程序的思维应该是这样的:

首先考虑:如果程序再大点,再大点,再大点,再大点,再大点.....,做的程序还能运行吗?不能就改。
能,再考虑:程序还能优化,优化,优化,优化......,不能优化了,好,这才是我们最后需要的程序。

那象你们一上来就想怎么优化,优化,优化,最后把自己思维全框死了,最后不停的改程序,改程序,改程序直到某天产品停产。然后新产品上重新开始这种无聊的简单重复劳动。

使用特权

评论回复
53
农民讲习所| | 2007-7-28 10:58 | 只看该作者

这里的水平,还真没几个能让俺正眼瞧瞧的。

使用特权

评论回复
54
pk.kong| | 2007-7-28 11:21 | 只看该作者

好帖。

但别吵架,大家讨论讨论,把道理说明白就好了。别攻击个人。

谢谢上面发言的朋友,受教育了。!

使用特权

评论回复
55
ayb_ice| | 2007-7-28 11:21 | 只看该作者

真正高手...

我见过的真正高手的喜欢用宏汇编,连标准浮点数程序都是自己写的,程序柜架早已固定,添加删除任务很容易,大量使用各种宏...

使用特权

评论回复
56
linfeng133| | 2007-7-28 12:39 | 只看该作者

农民讲习所似乎一味对别人评头论足

夸夸其谈,貌似并非就事论事,一般的浮躁!

使用特权

评论回复
57
fsaok| | 2007-7-28 13:19 | 只看该作者

unsigned int t0buf;

原来t0buf是个变量

我从来都不会这样书写变量,所以以为是常数呢,

看漏眼了,不好意思,

使用特权

评论回复
58
sz_kd| | 2007-7-28 13:41 | 只看该作者

老农太骄傲了

老农太骄傲了

使用特权

评论回复
59
hotpower| | 2007-7-28 19:58 | 只看该作者

说心里话:赞成所长的意见~~~不要招惹TL0~~~

//-------------------------------------------------------------------------
//T0中断
//处理弱实时任务,并产生20MS系统时间
//-------------------------------------------------------------------------
void Timer0(void) interrupt 1 using 1
{
    TH0 = sInSysTimer.mT0_PreLoad;        //重装T0高位初始值

    if( ++sInSysTimer.m20msCount > 3 ){
        sInSysTimer.m20msCount = 0;
        //20ms触发
        fInSys_20ms = 1;
        //调用20ms中断要处理的弱实时任务
        if( sInSysTimer.Weekness_20ms )(*sInSysTimer.Weekness_20ms)();
    }

    //调用5ms中断要处理的弱实时任务。
    if( sInSysTimer.Weekness_5ms )(*sInSysTimer.Weekness_5ms)();
}


所长这里:
TH0 = sInSysTimer.mT0_PreLoad;        //重装T0高位初始值
没下句TL0=xx

所以这样就形成了"自动"装载~~~

哪怕你在进入ISP前"睡觉",只要TL0"不翻山"即可~~~

使用特权

评论回复
60
dengm| | 2007-7-31 13:42 | 只看该作者

我的第2个代码停了中断 8 个周期,不应该使用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则