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

关于数组处理

[复制链接]
1198|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我的单片机型号的是PIC16F1947,用的是PICC编译器。我的程序启动不起来,经过排查,应该是电容触摸按键程序中的数组处理不当导致的。其中涉及到两个数组:volatile uint  Cap_Avg[]={0,0,0,0,0}; volatile uint  Cap_Value[]={0,0,0,0,0};。 出现问题的是这两条语句, percent=((long)Cap_Avg[Index]-(long)Cap_Value[Index]);
Cap_Avg[Index]=Cap_Avg[Index]+((long)Cap_Value[Index]-(long)Cap_Avg[Index])/16;

如果将这两条语句屏蔽,程序可以正常运行。如果将这两条语句其中一条开启,那么程序就会跑飞了。
这个触摸程序是在中断中执行的。以下是我的按键触摸的子程序和中断程序。我是个新手,跪求各位大神指教额。




volatile uint Index=0;                                    //通道
volatile uchar AvgIndex ;                                 //频率计数                    
volatile uint  Cap_Avg[]={0,0,0,0,0};                 //平均
volatile uint  Cap_Value[]={0,0,0,0,0};                   //当前值区
volatile long percent;

/////////按键判断函数//////////////
void  cap_ISR()                                        //百分比判断法
{
   Cap_Value[Index]=(TMR1H<<8)+TMR1L; //当前值 读取振荡频率TMR1值
  percent=((long)Cap_Avg[Index]-(long)Cap_Value[Index]);
   if(percent<0)
     {
      percent=0;
     }
   else
     {
      percent=percent*100;
      percent=percent/Cap_Avg[Index];
     }
if(percent<PCT_OFF)                                   //无键按下
  {
    switch(Index)
    {
     case 0:Key.gongneng=0;
            Key_confirm.gongneng_l=0;
            break;
     case 1:Key.timing =0; break;
     case 2:Key.saofeng=0; break;
     case 3:Key.standby=0;
            Key_confirm.standby_l=0;
            break;
     case 4:Key.zhaoming=0;
            Key_confirm.zhaoming_l=0;
            break;
     default:break;
    }
    if(AvgIndex<2)     AvgIndex++;
    else               AvgIndex=0;
    if(AvgIndex==2)
    {
       Cap_Avg[Index]=Cap_Avg[Index]+((long)Cap_Value[Index]-(long)Cap_Avg[Index])/16;
    }  
   }
   else if(percent>PCT_ON)                           
   {
       switch(Index)
       {
          case 0:Key.gongneng=1; break;
          case 1:Key.timing=1; break;
          case 2:Key.saofeng=1; break;
          case 3:Key.standby=1; break;
          case 4:Key.zhaoming=1; break;
          default:break;
       }
    }
     
}


/////////计数通道//////////////
void SetNext(void)
{
   Index++;
   Index=Index%5;
   CPSCON1=Index;          //通道  
}
////////TMR1启动函数///////////
void RestartTimers(void)
{   
   TMR1H=0;
   TMR1L=0;
   TMR1ON=1;       //TRM1使能
   TMR0 = TMR0INITIAL;           //初值100
   TMR0IF = 0;
}

void interrupt ISR(void)    //中断处理
{
if(TMR0IF&&TMR0IE)
{
   //////////按键检测/////////////////
    TMR1ON=0;                     //TMR1关闭
   
    cap_ISR();                    //按键判断函数

    SetNext();                    //通道设置
    RestartTimers();              //重启TMR1
}
if(TMR2IF&&TMR2IE)
{
   TMR2IF = 0;
   TMR2 = TMR2INITIAL;  
   /////////时间管理////////////
    Time_Management();
    //count_500ms ++;
   
   ////////定时任务管理/////////
   TimeTask_Management();          
}

//在中断程序结束时必须确认Timer0在ISR执行期间是否翻转
//如果翻转了,则认为是失败的采样,清除标志位重启定时器
  if(TMR0IF&&TMR0IE)        
{
   TMR1ON=0;                     //TMR1关闭
   RestartTimers();              //重启TMR1
}
}


沙发
Sandra33|  楼主 | 2016-9-22 13:30 | 只看该作者
如果将语句改成  percent=(long)(Cap_Avg[Index]-Cap_Value[Index]);
Cap_Avg[Index]=Cap_Avg[Index]+(long)(Cap_Value[Index]-Cap_Avg[Index])/16;
程序可以跑起来(mian函数中初始化语句可以执行),但是没多久就重启,然后无限循环重启。

如果将语句改成 percent=(long)(Cap_Avg[Index]-Cap_Value[Index]);
Cap_Avg[Index]+=(long)(Cap_Value[Index]-Cap_Avg[Index])/16;
程序就可以正常运行。我不懂这其中的原理额。

使用特权

评论回复
板凳
Latin_newday| | 2016-9-23 08:42 | 只看该作者
Timer0定时多久??还有没有其它更快的中断?
Long型数据运算耗时会比较长,怀疑是一直卡在中断出不来了!

在中断程序结束时必须确认Timer0在ISR执行期间是否翻转,这里应该是放在Timer2中断函数里面处理,否则就很难抓到按键数据。

使用特权

评论回复
地板
兰天白云| | 2016-9-23 09:04 | 只看该作者
从楼主的实验情况看,是这部分程序的运行问题,如果都是无符号整型,原来的程序也应该可以正常

使用特权

评论回复
5
兰天白云| | 2016-9-23 09:06 | 只看该作者
电容触摸屏用得着long吗?既然把代码放中断里运行,说明效率和实时性很高,而实时性很高就不能用太复杂的运算,楼主的出发点自相矛盾

使用特权

评论回复
6
Sandra33|  楼主 | 2016-9-23 14:20 | 只看该作者
Latin_newday 发表于 2016-9-23 08:42
Timer0定时多久??还有没有其它更快的中断?
Long型数据运算耗时会比较长,怀疑是一直卡在中断出不来了!
...

Timer0定时时间是20ms.现象是程序还没运行到main()函数,程序就崩溃了。

使用特权

评论回复
7
Sandra33|  楼主 | 2016-9-23 14:22 | 只看该作者
兰天白云 发表于 2016-9-23 09:06
电容触摸屏用得着long吗?既然把代码放中断里运行,说明效率和实时性很高,而实时性很高就不能用太复杂的运 ...

额,这个程序我也是移植Microchip给的例程的。

使用特权

评论回复
8
Sandra33|  楼主 | 2016-9-23 14:28 | 只看该作者
兰天白云 发表于 2016-9-23 09:04
从楼主的实验情况看,是这部分程序的运行问题,如果都是无符号整型,原来的程序也应该可以正常 ...

好像是我方向弄错了。经过昨天查错,并不是屏蔽以上两句代码程序才可以正常启动。屏蔽其他语句(只要屏蔽的代码量足够)程序也可以正常启动。

使用特权

评论回复
9
Sandra33|  楼主 | 2016-9-23 14:42 | 只看该作者
我用单步运行的方法观察了程序的运行,发现程序在还没进入main()函数的时候程序就跑飞了。我发现程序从地址0000h开始运行,当运行到地址0038h时 (图1),再运行一步程序就跑到0FF3h (图二)然后程序就会一直往下走。但是再往下走,下面就没有我的代码了。我不知道为什么这段启动代码会被挤到这个位置。

使用特权

评论回复
10
Sandra33|  楼主 | 2016-9-23 14:45 | 只看该作者
兰天白云 发表于 2016-9-23 09:06
电容触摸屏用得着long吗?既然把代码放中断里运行,说明效率和实时性很高,而实时性很高就不能用太复杂的运 ...

额,这是电容触摸按键检测程序,不是触摸屏.

使用特权

评论回复
11
MOn51| | 2016-9-25 10:43 | 只看该作者
你是数组越界吧?

使用特权

评论回复
12
XIEYUANBIN| | 2016-9-25 20:51 | 只看该作者
1.WDT溢出
2.数组越界
3.堆栈溢出

使用特权

评论回复
13
Sandra33|  楼主 | 2016-9-26 17:43 | 只看该作者
我用相同的源文件重新建了一个工程,然后就正常了。但是我对比了前后两个工程的配置字和bulid project,里面的选项是一样的。导致这问题的具体原因我还是不知道。

使用特权

评论回复
14
Sandra33|  楼主 | 2016-9-26 17:50 | 只看该作者
XIEYUANBIN 发表于 2016-9-25 20:51
1.WDT溢出
2.数组越界
3.堆栈溢出

我已经将WDT关闭了,程序是在进入main()函数之前就崩溃了,这样也会堆栈溢出吗?我后来屏蔽了数组,程序正常了。但是当我增加了一些代码后,程序还是崩溃了。我后来屏蔽了一些其他一些代码(让代码控制在7FFh地址以内)就正常了。

使用特权

评论回复
15
Sandra33|  楼主 | 2016-9-26 17:52 | 只看该作者
Sandra33 发表于 2016-9-26 17:50
我已经将WDT关闭了,程序是在进入main()函数之前就崩溃了,这样也会堆栈溢出吗?我后来屏蔽了数组,程序 ...

我后来用相同源文件重建了工程,就完全正常了。具体原因我不知道

使用特权

评论回复
16
XIEYUANBIN| | 2016-9-26 20:54 | 只看该作者
Sandra33 发表于 2016-9-26 17:52
我后来用相同源文件重建了工程,就完全正常了。具体原因我不知道

确实,MPLAB工程在反复拷贝使用后会崩溃,原因不知

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Sandra33 + 1 很给力!
17
Sandra33|  楼主 | 2016-9-28 12:18 | 只看该作者
XIEYUANBIN 发表于 2016-9-26 20:54
确实,MPLAB工程在反复拷贝使用后会崩溃,原因不知

你好,请问怎么结贴给分额?

使用特权

评论回复
18
XIEYUANBIN| | 2016-9-29 12:22 | 只看该作者
楼顶上下有显示吧

使用特权

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

本版积分规则

1

主题

11

帖子

0

粉丝