0 唉,这么简单的问题搞这么复杂来忽悠菜鸟…… - 第3页 - 单片机论坛,单片机技术交流论坛 - 21ic电子技术开发论坛
打印

唉,这么简单的问题搞这么复杂来忽悠菜鸟……

[复制链接]
楼主: 刘前辈
手机看帖
扫描二维码
随时随地手机跟帖
41
pdzyg| | 2011-8-27 11:21 | 只看该作者 回帖奖励 |倒序浏览
头晕。。。。。。。。。。。。。。

使用特权

评论回复
42
Cortex-M0| | 2011-8-27 11:29 | 只看该作者
看菜农的红杏出墙系列才真的头晕呢~~~~

使用特权

评论回复
43
刘前辈|  楼主 | 2011-8-27 12:41 | 只看该作者
本帖最后由 刘前辈 于 2011-8-27 13:31 编辑
#24楼
刘前辈确实是绝顶聪明的超宇宙级高手,俺菜鸟只有在后面跟班学习的份,试着改写了一段刘前辈最拿手的标准51程序,反汇编结果如下,请刘前辈指教。


M0版主真是认真的人,终于看出刘前辈的CY 不是中断ISR 里的CY 了——是自己用户程序里用来自测试的CY;值得庆贺一番,我请你吃饭,一天长进了3年!
    我还奇怪一点,如若我的CY 如你所想,是count 过0 进位时,ISR的行为,那前辈还一直充什么第一?HotPower等前辈早就指出来了,刘前辈经他们提示,照抄他们的思想?然后说自己是原创? 呵呵,前辈从不干那种事……若有一个人跟刘前辈想的一样,刘前辈必然会再想出一个与所有人不一样的方法来,……笑话所长如今只会骂粗口,昔日裸奔大腕,自诩“天下第一”,如今连一个与中断无关的裸奔方法也想不出来啦,昔日黄花,“要尊重老人……”

今天早上一小时已经理论上完成了 ||CY 的证明。不用花多少天,写出来谁都不高兴,提示一下:



CY应该永远等于0而不是 1 。因为count 按理不会小于250 ;所以正如你上面一框所说CY=0,跳转至“……”。Smartpower已经告诉大家“按道理一定(CY=0)执行这句话”。而CY=1属于非正常的随机偶然情况,——不应该出现的、导致程序出错的异常情况。 何时成了CY永远=1


见下面:

    67:  
    68:         if( count > 250)      //count = 251~260
C:0x0853    D3       SETB     C
C:0x0854    E509     MOV      A,0x09
C:0x0856    94FA     SUBB     A,#0xFA
C:0x0858    E508     MOV      A,count(0x08)
C:0x085A    9400     SUBB     A,#0x00
C:0x085C    4007     JC       C:0865        //异常情况,万分之 n 的概率。
    69:         {  //
    70:            delay(2);         //  按理一定执行这句话
C:0x085E    7F02     MOV      R7,#0x02
C:0x0860    1208CB   LCALL    delay(C:08CB)
    71:         }
    72:         else
C:0x0863    80B7     SJMP     C:081C
    73:         {
    74:             error++;           //但实际上有一定的机率会执行这句话
C:0x0865    AF11     MOV      R7,0x11
C:0x0867    AE10     MOV      R6,0x10
C:0x0869    AD0F     MOV      R5,0x0F
C:0x086B    AC0E     MOV      R4,error(0x0E)

既然   JC    &error     是由于中断ISR引起的不正常状况,而且SmartPower 已经写出了测试语句,想办法把它阻塞掉,当然用CY最简单:

    66:  
    67:  
    68:         if( count > 250||CY )      //count = 251~260
C:0x0853    D3       SETB     C
C:0x0854    E509     MOV      A,0x09
C:0x0856    94FA     SUBB     A,#0xFA
C:0x0858    E508     MOV      A,count(0x08)
C:0x085A    9400     SUBB     A,#0x00
C:0x085C    5003     JNC      C:0861     // 正常情况跳走了,下面语句是异常概率。不影响正常执行程序。
C:0x085E    30D707   JNB      CY(0xD0.7),C:0868      // 潜伏异常检测语句
    69:         {  //
    70:            delay(2);            //   按理一定执行这句话
C:0x0861    7F02     MOV      R7,#0x02
C:0x0863    1208CE   LCALL    delay(C:08CE)
    71:         }
    72:         else
C:0x0866    80B4     SJMP     C:081C
    73:         {
    74:             error++;        // 但实际上有一定的机率会执行这句话
C:0x0868    AF11     MOV      R7,0x11
C:0x086A    AE10     MOV      R6,0x10
C:0x086C    AD0F     MOV      R5,0x0F





、、

使用特权

评论回复
44
刘前辈|  楼主 | 2011-8-27 13:46 | 只看该作者
本帖最后由 刘前辈 于 2011-8-27 13:54 编辑

错误发生在 中断ISR 处理count = 260向 251 转换期间,这时,
count  低8开始为 = 4,使得下面:  4 - 250- 1< 0  ;  CY = 1;

    68:         if( count > 250)      //count = 251~260
C:0x0853    D3       SETB     C
C:0x0854    E509     MOV      A,0x09
C:0x0856    94FA     SUBB     A,#0xFA
      //   之后中断精确发生在这里。count 由0x104  转换为0x 00FB 。返回执行下面。

C:0x0858    E508     MOV      A,count(0x08)
C:0x085A    9400     SUBB     A,#0x00
C:0x085C    4007     JC       C:0865        //异常情况,万分之 n 的概率。


count 高8位=0 ;造成  0-0-1< 0 ; 错误概率出现。  



、、

使用特权

评论回复
45
刘前辈|  楼主 | 2011-8-27 14:04 | 只看该作者
玩一个不忽悠人的,不影响中断的、通用程序:

   DPTR=&count;  // DPL=(char *)&count+1;   DPH=&count;

    if( DPTR > 250 )         //count = 251~260
        {
            __delay_cycles(2);  //按理一定执行这句话
        }
        else
        {
            error++;            //但实际上有一定的机率会执行这句话
        }


//

使用特权

评论回复
46
Cortex-M0| | 2011-8-27 15:03 | 只看该作者
......

68:         if( count > 250||CY )      //count = 251~260
C:0x0853    D3       SETB     C
C:0x0854    E509     MOV      A,0x09
C:0x0856    94FA     SUBB     A,#0xFA
C:0x0858    E508     MOV      A,count(0x08)
C:0x085A    9400     SUBB     A,#0x00
C:0x085C    5003     JNC      C:0861     // 正常情况跳走了,下面语句是异常概率。不影响正常执行程序。
C:0x085E    30D707   JNB      CY(0xD0.7),C:0868      // 潜伏异常检测语句
    69:         {  //
    70:            delay(2);            //   按理一定执行这句话
C:0x0861    7F02     MOV      R7,#0x02
C:0x0863    1208CE   LCALL    delay(C:08CE)
    71:         }
    72:         else
C:0x0866    80B4     SJMP     C:081C
    73:         {
    74:             error++;        // 但实际上有一定的机率会执行这句话
C:0x0868    AF11     MOV      R7,0x11
C:0x086A    AE10     MOV      R6,0x10
C:0x086C    AD0F     MOV      R5,0x0F

......

刘前辈 发表于 2011-8-27 12:41


感谢刘前辈在百忙之中抽空指点俺菜鸟,刘前辈说的对,“要尊重老人……”,更要尊重前辈,菜鸟还是搞不明白,想请教刘前辈指点一二。

上面程序中,蓝色语句  JNB      CY(0xD0.7),C:0868   等价于   JNC           C:0868  ,

为将疑问述说的更清楚些,将上面程序改写成:

C:0x085C    5003     JNC      C:0861     // 正常情况跳走了,下面语句是异常概率。不影响正常执行程序。
C:0x085E    ******     JNC      C:0868      // 潜伏异常检测语句

由于 C=0时,按正常情况跳走了,只有当 C=1时,才执行下面语句。
但是,由于此时 C=1, 才会朝下走,因此,永远不会执行下一条 C=0 才跳转的指令。
      JNC      C:0868      // 潜伏异常检测语句,永远不会执行!因为执行到此的C标志永远等于1

真实高手啊,碰到出错就让他不执行,这方法多好啊~~~
俺怎么就想不到呢?





使用特权

评论回复
47
流行音乐| | 2011-8-27 15:13 | 只看该作者
我来帮忙总结一下。
到目前为止,大家给出的方法有以下两种,
方法1:关中断的方法。
方法2:smartpower 提出的在中断外循环读 count,当连续两次读的值相同才作为有效数据来处理。
大家还有没有更好的方法?

使用特权

评论回复
48
Cortex-M0| | 2011-8-27 15:21 | 只看该作者
玩一个不忽悠人的,不影响中断的、通用程序:

   DPTR=&count;  // DPL=(char *)&count+1;   DPH=&count;

    if( DPTR > 250 )         //count = 251~260
        {
            __delay_cycles(2);  //按理一定执行这句话
        }
        else
        {
            error++;            //但实际上有一定的机率会执行这句话
        }


// ...
刘前辈 发表于 2011-8-27 14:04



这个忽悠的更厉害,尽管DPTR加1 为16位运算,中断不能拆分,但 if( DPTR > 250 ) 判断语句照样是拆分成两个8位运算,不是一个完整的16位运算,在判断过程中,照样存在被中断打断的随机性~~~

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
highgear + 1
49
kaifengzhongyi| | 2011-8-27 15:48 | 只看该作者
:L

使用特权

评论回复
50
Cortex-M0| | 2011-8-27 17:04 | 只看该作者
本帖最后由 Cortex-M0 于 2011-8-27 17:06 编辑
我来帮忙总结一下。
到目前为止,大家给出的方法有以下两种,
方法1:关中断的方法。
方法2:smartpower 提出的在中断外循环读 count,当连续两次读的值相同才作为有效数据来处理。
大家还有没有更好的方法? ...
流行音乐 发表于 2011-8-27 15:13



LS总结的《方法1》 常用,《方法2》有点局限性,当count处于高速计数状态时,每次读出的值都不同,根本无法连续两次读到相同值,程序进入死循环。
因此,解决此问题的方法是,将int类型分成2个char型变量读,先读int类型高位8字节,再读低位8字节,然后要一次复读高位8字节,比较两次读入的高位8字节,如相同,则第一次读入的高、低8字节有效,否则,重复上述过程,再一次分时循环读入高、低8字节,直至有效。

因此,在一般情况下,计数频率慢的用关中断之法,程序简单方法。
计数频率快的用俺上面讲的高、低8字节依次读入,再比较8位高字节确认法。当计数频率很快时,用关中断之法,影响计数准确性。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
highgear + 1
51
icecut| | 2011-8-27 19:51 | 只看该作者
LS总结的《方法1》 常用,《方法2》有点局限性,当count处于高速计数状态时,每次读出的值都不同,根本无法连续两次读到相同值,程序进入死循环。
因此,解决此问题的方法是,将int类型分成2个char型变量读,先读 ...
Cortex-M0 发表于 2011-8-27 17:04

《方法2》有点局限性
这个方法是正确的,多线程同步的时候肯定是一种方法。。。中断的时候标志寄存器竟然不保存。。。。

下面引用8086的处理方法
中断时,为保证中断服务程序正确返回原来的程序,要把被中断程序的断点处逻辑地址CS : IP压入堆栈保存,还要保存反映现场状态的标志寄存器FLAGS。然后,将中断服务程序的入口地址送CS和IP寄存器转去执行中断服务程序。
我特别的搜索一些单片机汇编语言的中断处理程序,的确是写了保存psw的指令,如果keil不保存。那我没办法了。。。这个问题解决办法就是嵌入汇编,增加psw的保存。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
highgear + 1
52
Cortex-M0| | 2011-8-27 20:36 | 只看该作者
《方法2》有点局限性
这个方法是正确的,多线程同步的时候肯定是一种方法。。。中断的时候标志寄存器竟然不保存。。。。

下面引用8086的处理方法
中断时,为保证中断服务程序正确返回原来的程序,要把被中断程序的 ...
icecut 发表于 2011-8-27 19:51


icecut大师就别用您那超高挡的MCU来搅拌了,这里刘前辈用的是AVR, 51低挡8位机,连个int类型都要分两次读写~~~  :L

使用特权

评论回复
53
highgear| | 2011-8-27 20:42 | 只看该作者
刘公公前辈又一次被打脸。刘公公前辈你技术的深度和广度皆不足,就不必自取其辱了。"第一","填补空白”更是浅薄可笑。

流行音乐和123姐姐总结几种方法,还有一种就是把变量读写放入同一模块中,对外用标志,可避免此类错误。

使用特权

评论回复
54
aihe| | 2011-8-27 21:02 | 只看该作者
好好讨论技术,不要攻击人身
是好是坏,大家都看得懂

使用特权

评论回复
55
Cortex-M0| | 2011-8-28 04:43 | 只看该作者
highgear老师高见,补充的《方法3》也常用,即把变量读写放入同一模块中,对外用标志,可避免此类错误。
这种方法同样适合于计数速率不太高的场合。

使用特权

评论回复
56
icecut| | 2011-8-28 08:55 | 只看该作者
icecut大师就别用您那超高挡的MCU来搅拌了,这里刘前辈用的是AVR, 51低挡8位机,连个int类型都要分两次读写~~~  :L
Cortex-M0 发表于 2011-8-27 20:36


8086也是16bit总线,一个32bit的int也表示不出来啊。。。
拼int的时候中断不要紧,关键是保存psw就不会标记错误。不要把x86看得太神圣。
要走正统的路。不要曲线救数

使用特权

评论回复
57
Cortex-M0| | 2011-8-28 09:42 | 只看该作者
8086也是16bit总线,一个32bit的int也表示不出来啊。。。
拼int的时候中断不要紧,关键是保存psw就不会标记错误。不要把x86看得太神圣。
要走正统的路。不要曲线救数 ...
icecut 发表于 2011-8-28 08:55



icecut大师越搅拌离题越远,俺怀疑您刘前辈的题目都没看完整,任何中断都要保存psw标记,除非有些低挡的如PIC之类芯片,保存累加器、psw标记等内容需要人工干涉,没有自动保存功能,中断返回当然自动恢复原psw标记,这点根本不用关心,问题是,您分两次读一个类型的数据,中间被中断打断,并且改写了数据,改写数据不要紧,关键是这个数据高低位字节有进位,引起主程序分两次读入的数据出错,您说靠保存psw标记有啥用?

顺便说一下,俺玩8086肯定比您熟,几十年前就玩8086硬件和汇编,软硬件结构现在还依稀记得一点~~~

使用特权

评论回复
58
qin552011373| | 2011-8-28 09:49 | 只看该作者
路过看看

使用特权

评论回复
59
qin552011373| | 2011-8-28 09:49 | 只看该作者
这个帖子挺热闹

使用特权

评论回复
60
Cortex-M0| | 2011-8-28 09:59 | 只看该作者
说句公道话,刘前辈的"C” 其实玩的挺转的(不是指C++),汇编还行,因此,动不动就来个“红杏出墙”,来个混合编程的“夹心饭”卖弄一下,说心里话,只要刘前辈的硬件再好一点,像俺也很难捉到他的小虫子,像这种底层编程------汇编,缺少硬件的基础,很难玩的深,像菜农整天玩“红杏出墙”,在于菜农硬件底子较深厚,因此不容易出差错~~~

单纯玩软件的盆友,建议少用点混合编程,就算偶然必须要用,也点到为止为妙,别玩的太深,否则,小阴沟里翻船也不知怎么回事~~~

使用特权

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

本版积分规则