首页 > 解决方案 > 如何识别堆栈溢出的错误点是在 MikroC 代码中强制设备重置错误

问题描述

描述:

我尝试使用 PIC18F4550 微控制器和 MikroC 编程语言制作电路。这是我的程序序列。

我只是添加这个只是为了理解代码。

代码:

这是我用 MikroC 语言编写的这个序列的程序。还是没写完。

     // LCD module connections
    sbit LCD_RS at RD0_bit;
    sbit LCD_EN at RD1_bit;
    sbit LCD_D4 at RD4_bit;
    sbit LCD_D5 at RD5_bit;
    sbit LCD_D6 at RD6_bit;
    sbit LCD_D7 at RD7_bit;

    sbit LCD_RS_Direction at TRISD0_bit;
    sbit LCD_EN_Direction at TRISD1_bit;
    sbit LCD_D4_Direction at TRISD4_bit;
    sbit LCD_D5_Direction at TRISD5_bit;
    sbit LCD_D6_Direction at TRISD6_bit;
    sbit LCD_D7_Direction at TRISD7_bit;
    // End LCD module connections
    unsigned short shedno=0,i=0,shedc=0,streg,lsreg,rang,x,ed,edi;
    unsigned count=0,reg1, reg2, reg3, reg4, reg5, reg6,sttime=1000,editno1=0,editno2=0,editno3=0,editno4=0,editno5=0,editno6=0;
    char shednon[4]="",countn[6]="",stregn[4]="",lsregn[4]="",regval[6]="",ntrel1[6]="",ntrel2[6]="",ntrel3[6]="",ntrel4[6]="",ntrel5[6]="",ntrel6[6]="";


     void findshed(short sno){
        shedno = EEPROM_Read(0x00);
        shedno = 256 - shedno;
        shedno = shedno + sno;
        ByteToStr(shedno, shednon);

        streg = 6*shedno+4;
        lsreg = streg + 5;
        ByteToStr(streg, stregn);
        ByteToStr(lsreg, lsregn);
     }

      void shedrelay(){
              rang =0;
              for(x=streg; x<=lsreg; x++){
                regval[rang] = EEPROM_Read(x);
                Delay_ms(100);
                if(rang < 6){
                rang++;
                }
              }
              reg1 =  regval[0]+sttime+editno1;
              reg2 =  regval[1]+sttime+editno2;
              reg3 =  regval[2]+sttime+editno3;
              reg4 =  regval[3]+sttime+editno4;
              reg5 =  regval[4]+sttime+editno5;
              reg6 =  regval[5]+sttime+editno6;
              Wordtostr(reg1,ntrel1);
              Wordtostr(reg2,ntrel2);
              Wordtostr(reg3,ntrel3);
              Wordtostr(reg4,ntrel4);
              Wordtostr(reg5,ntrel5);
              Wordtostr(reg6,ntrel6);
     }
      void shedselectdis(){
              Lcd_Cmd(_LCD_CLEAR);
              Lcd_Out(1,1,"Next Shedule: S");
              Lcd_Out(1,16,shednon);
              Lcd_Out(2,1,"R1:");
              Lcd_Out(2,4,ntrel1);
              Lcd_Out(2,11,"R2:");
              Lcd_Out(2,14,ntrel2);
              Lcd_Out(3,1,"R3:");
              Lcd_Out(3,4,ntrel3);
              Lcd_Out(3,11,"R4:");
              Lcd_Out(3,14,ntrel4);
              Lcd_Out(4,1,"R5:");
              Lcd_Out(4,4,ntrel5);
              Lcd_Out(4,11,"R6:");
              Lcd_Out(4,14,ntrel6);
     }

     void editshed(){
                  Lcd_Cmd(_LCD_CLEAR);
                  Lcd_Cmd(_LCD_CURSOR_OFF);
                  Lcd_Out(1,1,"Edit Shedule: S");
                  Lcd_Out(1,16,shednon);
                  Lcd_Out(2,1,"R1:");
                  Lcd_Out(2,4,ntrel1);
                  Lcd_Out(2,11,"R2:");
                  Lcd_Out(2,14,ntrel2);
                  Lcd_Out(3,1,"R3:");
                  Lcd_Out(3,4,ntrel3);
                  Lcd_Out(3,11,"R4:");
                  Lcd_Out(3,14,ntrel4);
                  Lcd_Out(4,1,"R5:");
                  Lcd_Out(4,4,ntrel5);
                  Lcd_Out(4,11,"R6:");
                  Lcd_Out(4,14,ntrel6);
     }

     void relayssw(int x1, int x2, int x3, int x4, int x5, int x6){
              PORTA = 0b00000001;
              VDelay_ms(x1);
              PORTA = 0b00000000;
              Delay_ms(50);

              PORTA = 0b00000010;
              VDelay_ms(x2);
              PORTA = 0b00000000;
              Delay_ms(50);

              PORTA = 0b00000100;
              VDelay_ms(x3);
              PORTA = 0b00000000;
              Delay_ms(50);

              PORTA = 0b00001000;
              VDelay_ms(x4);
              PORTA = 0b00000000;
              Delay_ms(50);

              PORTA = 0b00010000;
              VDelay_ms(x5);
              PORTA = 0b00000000;
              Delay_ms(50);

              PORTA = 0b00100000;
              VDelay_ms(x6);
              PORTA = 0b00000000;
              Delay_ms(50);
     }
      void disval(){
        Lcd_Cmd(_LCD_CLEAR);
        findshed(0);
        Lcd_Out(1,1,"Shedule: S");
        Lcd_Out(1,11,shednon);
        Lcd_Out(2,1,"Count:");
        WordToStr(count, countn);
        Lcd_Out(2,1,"Count:");
        Lcd_Out(2,8,countn);
        Lcd_Out(3,1,"Steps:");
        Lcd_Out(4,1,"Temp:");
     }

    void main() {
      TRISA = 0b00000000;
      TRISB = 0b11111111;

      PORTA = 0b00000000;

      ADCON0=0;
      ADCON1=0X0F;
      CMCON=0X07;
      CCP1CON=0;
      CCP2CON=0;
      SSPCON1=0;


      Lcd_Init();
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Cmd(_LCD_CURSOR_OFF);
      Lcd_Out(1,6,"Welcome !");
      Delay_ms(2000);
      Lcd_Cmd(_LCD_CLEAR);
      disval();
      EEPROM_Write(0x00,255);
    /*for(i=1;i<131;i++){
       EEPROM_Write(i,i);
    Delay_ms(50);
      }*/
      while(1){
          if(PORTB.B7 = 1){  //proximity count
            Delay_ms(300);
            count++;
            disval();
          }
          //
          if(PORTB.B5 = 1){  //proximity count reset
            Delay_ms(300);
            Lcd_Cmd(_LCD_CLEAR);
            Lcd_Out(1,1,"Reset Count?");
            WordToStr(count, countn);
            Lcd_Out(2,1,countn);
            Lcd_Out(3,1,"Press Enter to Reset");
            Lcd_Out(4,1,"Press Up to Back");
            while(1){
              if(PORTB.B4 = 1){ //enter
                  Delay_ms(300);
                  count=0;
                  disval();
                  break;
              }else if(PORTB.B2 = 1){  //up
                  Delay_ms(300);
                  disval();
                  break;
              }
            }
          }
          //
          if(PORTB.B1 = 1){  //settings
             shedc = 0;
             Lcd_Cmd(_LCD_CLEAR);
             Lcd_Out(1,1,"Select Shedule: S");
             findshed(0);
             Lcd_Out(1,18,shednon);
             Lcd_Out(2,1,"Select Set. to Back");
             Lcd_Out(3,1,"Select Enter to Edit");
             Lcd_Out(4,1,"Select Up or Down");
             Lcd_Cmd(_LCD_FIRST_ROW);
             for(i=1;i<17;i++){
                Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
             }
             Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
             while(1){
                if(PORTB.B1 = 1){  //exit
                  Delay_ms(300);
                  disval();
                  Lcd_Cmd(_LCD_CURSOR_OFF);
                  break;
                }else if(PORTB.B2 = 1){ //up button
                  Delay_ms(300);
                  if(shedno < 20){
                     shedc++;
                   }

                  findshed(shedc);
                  Lcd_Out(1,18,shednon);
                  Lcd_Cmd(_LCD_FIRST_ROW);
                  for(i=1;i<17;i++){
                      Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
                  }
                  Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                }else if(PORTB.B3 = 1){ //down button
                  Delay_ms(300);
                  if(shedno > 1){
                     shedc--;
                   }

                  findshed(shedc);
                  Lcd_Out(1,18,shednon);
                  Lcd_Cmd(_LCD_FIRST_ROW);
                  for(i=1;i<17;i++){
                      Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
                  }
                  Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                }else if(PORTB.B4 = 1){ //enter button
                  Delay_ms(300);
                  findshed(shedc);
                  shedrelay();
                  editshed();
                  Lcd_Cmd(_LCD_SECOND_ROW);
                  Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                  editno1 = 0;
                  editno2 = 0;
                  editno3 = 0;
                  editno4 = 0;
                  editno5 = 0;
                  editno6 = 0;
                  while(1){
                       for(ed = 1; ed < 6; ed++){
                           while(1){
                               if(PORTB.B2 == 1){  //up
                                 //Delay_ms(300);
                                 if(ed ==1){
                                    editno1++;
                                 }else if(ed ==2){
                                    editno2++;
                                 }else if(ed ==3){
                                    editno3++;
                                 }else if(ed ==4){
                                    editno4++;
                                 }else if(ed ==5){
                                    editno5++;
                                 }else if(ed ==6){
                                    editno6++;
                                 }
                                 findshed(shedc);
                                 shedrelay();
                                 editshed();
                               }else if(PORTB.B3 == 1){  //down
                                  //Delay_ms(300);
                                  if(ed ==1){
                                    editno1--;
                                 }else if(ed ==2){
                                    editno2--;
                                 }else if(ed ==3){
                                    editno3--;
                                 }else if(ed ==4){
                                    editno4--;
                                 }else if(ed ==5){
                                    editno5--;
                                 }else if(ed ==6){
                                    editno6--;
                                 }
                                 findshed(shedc);
                                 shedrelay();
                                 editshed();
                               }else if(PORTB.B4 == 1){  //enter
//------------------------------------------------------------------------
                                 //Delay_ms(300); //POINT A
//------------------------------------------------------------------------
                                 break;
                               }
                           }
                       }
                    Lcd_Cmd(_LCD_CLEAR);
                  }
                }
             }
          }
          //
           if((PORTB.B2 = 1)||(PORTB.B3 = 1)){ //up or down
              shedc = 0;
              Delay_ms(300);
              Lcd_Cmd(_LCD_CLEAR);
              findshed(0);
              Lcd_Out(1,1,"Runing: S");
              Lcd_Out(1,10,shednon);
              Lcd_Out(2,1,"Next:");
              Lcd_Out(3,1,"Press Up or Down Key");
              Lcd_Out(4,1,"Press Reset to Back");
              while(1){
                  if(PORTB.B3 = 1){ //down
                      Delay_ms(300);
                      if(shedno > 1){
                         shedc--;
                      }
                      findshed(shedc);
                      shedrelay();
                      shedselectdis();
                  }else if(PORTB.B2 = 1){ //up
                      Delay_ms(300);
                      if(shedno < 20){
                         shedc++;
                      }
                      findshed(shedc);
                      shedrelay();
                      shedselectdis();
                  }else if(PORTB.B4 = 1){ //enter
                      Delay_ms(300);
                      findshed(shedc);
                      EEPROM_Write(0x00,256-shedno);
                      disval();
                      break;
                  }else if(PORTB.B6 = 1){ //test
                       Delay_ms(300);
                       PORTC = 0b00000000;
                       Delay_ms(100);
                       relayssw(reg1, reg2, reg3, reg4, reg5,reg6);
                  }else if(PORTB.B5 = 1){ //reset
                      Delay_ms(300);
                      disval();
                      break;
                  }
              }
          }
          //

      }

    }

错误:

当我在此代码中再添加一行时,例如Delay_ms(300);行,那么我的 Proteus Simulation 和真正的实用程序都不起作用。但IC 中的程序存储器未满。IC 正在复位

备忘录

Proteus Simulation不断给我以下错误信息。

[PIC18 堆栈] PC=0x09BC。堆栈溢出正在强制设备复位。[U1]

我认为这不是嵌套调用限制错误,因为此代码没有比推荐的函数调用更多的函数调用。

mikroC PRO for PIC 将非递归嵌套调用的数量限制为:

8 次调用 PIC12 系列,8 次调用 PIC16 系列,16 次调用 PIC16 增强系列。PIC18 系列的 31 次调用。

问题:

如何识别代码中的错误点以及如何解决这个问题?什么是0x09BC重点。

如果您想要任何其他数据来识别错误,请告诉我。

这是 Proteus 和 MikroC 代码链接下载

模拟实战:

我做了以下实际操作,但我无法识别错误点。

这是 CPU Stack 和 CPU Data Memory 中没有 Stack Overflow 错误的数据。CPU 数据内存存储在最后一个内存位置和中间内存位置是空闲的。

没有错误

这是 CPU 堆栈和 CPU 数据存储器中出现堆栈溢出错误的数据。CPU 数据内存存储在最后一个内存位置和中间内存位置是空闲的。

同样在 CPU 堆栈中,连续从 31 变为 0,即变为0x09BC.

有错误

EEPROM 也有很多空闲的内存位置。

记忆

标签: cmicrocontrollerpicmikroc

解决方案


推荐阅读