打印
[PIC®/AVR®/dsPIC®产品]

关于检查程序问题的讨论

[复制链接]
9062|94
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Rain_King|  楼主 | 2013-11-18 14:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Rain_King 于 2013-11-19 11:57 编辑

            使用PIC单片机的时候,经常出现一些非常难以理解的一些现象,根本没法找出问题,我甚至称这个为诡异。以前使用51的时候,啥问题都没有,即使有问题也很容易发现,并且很好的理解为啥出现这个问题。目前我遇到这些问题,各位讨论讨论,看是啥东东,我的系统架构是消息和时间结合组成的,我个人觉得不错....
1,这个问题是按键的扫描,用2个adc接口,用来处理几个按键,我是10ms扫一次,以及利用中断消抖等等,如果有按键按下,就将此按键的消息储存在消息系统里,然后再处理,现在的问题是:
由于有2个adc值嘛,先处理的adc那个,产生按键消息非常的正常,后处理的adc,就会发现产生的按键消息非常多,貌似没有经过消抖似的,如果将这两个adc的处理顺序换一下,结果还是先处理的正常产生按键消息,后处理的产生很多按键消息.....更加奇葩的是,如果我在后处理的那个里面加一条端口处理语句,例如:Test=1;结果就正常了.....不知道说清楚了没.....还有2个adc处理的相关变量时独立的,没有共用.......
2,关于储存数据,原先存储数据妥妥的,结果换一个芯片测试之后,就发现读取数据出问题了,如果单独测试函数的功能,发现存储数据和读数据是正常的,然后一步步来测试,发现有时候,只要进入到特定的函数之后,读取函数功能就没法工作了.....例如下面的例子:
读取数据;a
Inti()
{读取数据;b}
读取数据c
这是说:就这个Inti函数的里面有读取数据的函数,如果在这个调用函数的前面,或者后面读取数据,都是正常的,结果放到这个函数里面,结果就不正常了......可是这个Init()函数里面也只是写的调用读取数据的函数啊,其他的都没有变,怎么就有问题呢......至于函数栈的溢出,不可能,以为我的嵌套也就3次而已........
3,希望各位说说一般检查程序怎么检查的,我一般是逐步来测得.....可是遇到一些诡异的现象就没法处理了.......


4、我不知道怎么回事了...我就是问问题啊...顺带和大家讨论讨论.......而且我到目前为止还没有找出真正的原因,但是我不知道为啥又是置顶,又是版主推荐.....这是要闹哪样啊.....我的心脏承受不住啊.....
沙发
Rain_King|  楼主 | 2013-11-18 15:13 | 只看该作者
本帖最后由 Rain_King 于 2013-11-22 08:34 编辑

还有就是遇到实际和理论值相差非常远的情况,一般都是发生在捕捉的时候,自己计算的值于实际的值相差非常大......都不知道怎么解决......头都想得奔溃.....



          还好留了一个楼层,经过这么久的讨论,然后我自己一个个试,已经把第一个问题给解决了,发现时代码优化问题,把设置的优化speed勾上,就没有问题了,但是代码的空间增大了8%左右了,也就是说编译器优化也只是优化了8%左右,刚才无意之中看到叶版主曾经回复的帖子说自己的写代码比较保守,我不知道这里的保守指的是啥,但是我觉得我在写代码的时候,算是比较考虑算法技巧的吧.......
        在此过程中,版主提到过临界代码的概念,但是到现在版主也没有怎么详细介绍,版主啊,能否开个帖子具体阐述一下啊,如果懒的动,你大致说一下,我可以代劳啊..........
       至于说测试方法,大家可以一个个楼层看,我觉得还是比较多的吧..............还么有完..


      继续修改...进过这么几天的整理和修改,除了捕捉的实际值和理论值差距有点大之外,其他的都已经解决了,写入数据和读取数据,我把函数稍微的修理了一下...另外关于临界代码,进过版主的大致讲解,我也只是略知一二,就用版主的那个例子来说一下:
if(msCounter>5000){
                  Startout();
                  }         
           }   
}
//------------------------------------------------------------------------
//定时中断服务程序
void interrupt Timer_1ms_ISR(void){
                                  msCounter++;
                                  }
//------------------------------------------------------------------------
       在8位MCU上,msCounter>5000,5000对应的16进制数值就是0x1388,超过了一字节数域的表示范围,这个对应的ASM指令,一般都是多条指令来判断大小,基本上编译器生成的汇编指令都是分成两次分别比较高字节和低字节值的大小,当MCU执行比较时,如果恰好中断发生并导致了进位,此时就产生了临界。
    这个是版主给的解释,进过我的思考后,我觉得所谓的临界代码应该是极其特殊的情况,没有考虑到的时候,也就是说几乎是概率事件......不过这需要经验和时间来总结这样的情况吧....
    最后关于程序的检查,首先肯定是语法的啦,这是最基本的,然后才是逻辑的问题...这个最伤透脑筋了,不过你可以一个一个功能去测试,可以屏蔽掉不相干的功能,特别是定时器,这个最容易造成逻辑混乱的问题了。我一般的检查方法是,要么用一个不用的脚,来测试,如下:
if(Test==1)
{
   Test=0;
}
else
{
  Test=1;
}
我用这个一搬是为了测试时间,或者是是否运行到这个地方...当然你必须还得有数字示波器 才行了。。。
      另外。就是变量的的检测了,时时监测重要变量的值得变化,当然这你需要有显示屏才可以的啦,也有用在线调试的,我原先也是用这个来监测变量值得,结果由于有时间上的差异,而且程序大了之后,总感觉在线调试很烂.....不过简单的在线调试还是可以的.....
     最最后,就是感谢各位大神的帮助了.....具体细节 大家可以看下面的回复............



使用特权

评论回复
板凳
ayb_ice| | 2013-11-18 15:34 | 只看该作者
你都用消息处理机制+时间片了

这些问题应该都不是问题吧,
不用想了,肯定程序问题

使用特权

评论回复
地板
Rain_King|  楼主 | 2013-11-18 15:41 | 只看该作者
ayb_ice 发表于 2013-11-18 15:34
你都用消息处理机制+时间片了

这些问题应该都不是问题吧,

至少说一下方向和方法啊..............

使用特权

评论回复
5
frlop| | 2013-11-18 15:59 | 只看该作者
略诡异,帮你顶一下。

使用特权

评论回复
6
Rain_King|  楼主 | 2013-11-18 16:02 | 只看该作者
frlop 发表于 2013-11-18 15:59
略诡异,帮你顶一下。

感谢啦............头都想大了.....

使用特权

评论回复
7
ayb_ice| | 2013-11-18 16:10 | 只看该作者
先处理的没有问题,后处理的有问题,
应该是ADC结果不正常吧,可能ADC配置不对吧,
可以发个假的数据试试算法嘛,这很难吗

使用特权

评论回复
8
Rain_King|  楼主 | 2013-11-18 16:16 | 只看该作者
ayb_ice 发表于 2013-11-18 16:10
先处理的没有问题,后处理的有问题,
应该是ADC结果不正常吧,可能ADC配置不对吧,
可以发个假的数据试试算 ...

ADC的值是正确的,这个我检测过了....即时不正确,也不会导致产生很多消息啊....主要原因是比如我30ms-500ms之间是相当于短按,按照道理只会产生一个按键消息,可是我测试的时候,产生好几个消息....感觉消抖貌似没有起作用,可是变量就在哪里啊.....真是没法理解...

使用特权

评论回复
9
ayb_ice| | 2013-11-18 16:33 | 只看该作者
既然ADC结果是正确的,那肯定算法错误,

一步步跟踪不就知道结果了

使用特权

评论回复
10
Rain_King|  楼主 | 2013-11-18 16:50 | 只看该作者
本帖最后由 Rain_King 于 2013-11-18 16:52 编辑

if(AdcValue[1]<DOWN_B_KEY&&AdcValue[1]>=UP_B_KEY)    //this is Down Key
{
     ++KeyCntB;                      //用于消抖                                                               
     if((KeyCntB<=CNTS_KEY+2)&&(KeyCntB>=CNTS_KEY))   //短按时相关处理
    {
       if(LongKeyB!=LONG_KEY)
       {
           LongKeyB=SHORT_KEY;
       }
       KeyKindB=DOWNB_KEY;
    }
    else if(KeyCntB>=CNTL_KEY)     //长按时相关处理
    {
        if(RA7_NU==1)       //加这个端口就正常了,不加就不正常
       {
           RA7_NU=0;
       }
       else
      {
            RA7_NU=1;
       }
       SaveKStatus=KeyStatus;
       KeyCntB=0;
       LongKeyB=LONG_KEY;
       WriteMessage(1,KeyStatus|PRESS_LBS_MSG);
  }
}
说明:问题就是出在一步步检测啊,如果我检测数据KeyCntB的值得变化,就没有任何问题,如果我检测其他变量,立马问题再现......特别是我只是轻轻的按一下,都会有长按的消息.....总觉得KeyCntB这个变量的问题....但是就是找不出哪里有问题....

使用特权

评论回复
11
Rain_King|  楼主 | 2013-11-18 16:54 | 只看该作者
ayb_ice 发表于 2013-11-18 16:33
既然ADC结果是正确的,那肯定算法错误,

一步步跟踪不就知道结果了


if(AdcValue[1]<DOWN_B_KEY&&AdcValue[1]>=UP_B_KEY)    //this is Down Key
{
     ++KeyCntB;                      //用于消抖                                                               
     if((KeyCntB<=CNTS_KEY+2)&&(KeyCntB>=CNTS_KEY))   //短按时相关处理
    {
       if(LongKeyB!=LONG_KEY)
       {
           LongKeyB=SHORT_KEY;
       }
       KeyKindB=DOWNB_KEY;
    }
    else if(KeyCntB>=CNTL_KEY)     //长按时相关处理
    {
        if(RA7_NU==1)       //加这个端口就正常了,不加就不正常
       {
           RA7_NU=0;
       }
       else
      {
            RA7_NU=1;
       }
       SaveKStatus=KeyStatus;
       KeyCntB=0;
       LongKeyB=LONG_KEY;
       WriteMessage(1,KeyStatus|PRESS_LBS_MSG);
  }
}
说明:问题就是出在一步步检测啊,如果我检测数据KeyCntB的值得变化,就没有任何问题,如果我检测其他变量,立马问题再现......特别是我只是轻轻的按一下,都会有长按的消息.....总觉得KeyCntB这个变量的问题....但是就是找不出哪里有问题....

使用特权

评论回复
12
Rain_King|  楼主 | 2013-11-18 16:55 | 只看该作者
很明了的程序啊............实在费解....................

使用特权

评论回复
13
huangxz| | 2013-11-18 17:01 | 只看该作者
Rain_King 发表于 2013-11-18 16:55
很明了的程序啊............实在费解....................

可以把这个代码加载到其他芯片上去试试,pic的芯片好像没有jtag,不太好跟踪调试

使用特权

评论回复
14
ayb_ice| | 2013-11-18 17:06 | 只看该作者
你的按键一旦大于CNTL_KEY值,

KeyCntB=0;
这个逻辑不正常吧,应该是没有按键按下时才能将KeyCntB清0吧

使用特权

评论回复
15
Rain_King|  楼主 | 2013-11-18 17:18 | 只看该作者
本帖最后由 Rain_King 于 2013-11-18 17:24 编辑
ayb_ice 发表于 2013-11-18 17:06
你的按键一旦大于CNTL_KEY值,

KeyCntB=0;


KeyCntB是用来消抖和确认长按的...每个10ms扫一次,CNTL_KEY是长按的确定,一旦大于这个值,就表示按键长按了,发送一个长按消息,那么就需要从新在来计算一次,所以将KeyCntB=0了,当然但检测到抬起键时,也会清零,我的长按是可以连续发送长按消息的.....

使用特权

评论回复
16
Rain_King|  楼主 | 2013-11-18 17:29 | 只看该作者
ayb_ice 发表于 2013-11-18 17:06
你的按键一旦大于CNTL_KEY值,

KeyCntB=0;

其实我还做过一些测试,else if(KeyCntB>=CNTL_KEY)这个判断语句下面检测一个++i的数据,发现即时我短按都会发现i变化了......总感觉貌似程序跳过KeyCntB>=CNTL_KEY这个判断了,这就是我说的诡异的地方.....理论明明不可能发生的.....

使用特权

评论回复
17
Rain_King|  楼主 | 2013-11-18 17:42 | 只看该作者
huangxz 发表于 2013-11-18 17:01
可以把这个代码加载到其他芯片上去试试,pic的芯片好像没有jtag,不太好跟踪调试 ...

我只有pic系列的单片机啊..........其他的木有..............

使用特权

评论回复
18
huangxz| | 2013-11-18 17:57 | 只看该作者
Rain_King 发表于 2013-11-18 17:42
我只有pic系列的单片机啊..........其他的木有..............

实在不行就看看汇编代码吧,最彻底的解决方法

使用特权

评论回复
19
Rain_King|  楼主 | 2013-11-18 18:00 | 只看该作者
huangxz 发表于 2013-11-18 17:57
实在不行就看看汇编代码吧,最彻底的解决方法

对....这个方法不错....可是怎么找到定位的语句啊...我可是有几千行,很难找到对应的汇编啊....

使用特权

评论回复
20
黄小俊| | 2013-11-18 18:08 | 只看该作者
呵呵

使用特权

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

本版积分规则

个人签名:努力学习,积极回复,只为申请版主.......

29

主题

784

帖子

4

粉丝