描述:
我尝试使用 PIC18F4550 微控制器和 MikroC 编程语言制作电路。这是我的程序序列。
- 有 20 个时间表可供选择,每个时间表有 6 个计时值。
- 该计划编号存储在第一个 EEPROM 中,其他时间数据存储在 10 到 129 个 EEPROM 存储器中。(6 个时序值 x 20 个计划,从 10 个内存开始)
- 用户可以选择其中一个时间表并且可以编辑每个时间表的时间。
- 当用户选择时间表时,输出延迟的这些时间值。
- LCD显示屏上的数据显示
- 这有 6 个输入。(设置 (B1)、向上 (B2)、向下 (B3)、进入 (B4)、重置 (B5)、测试 (B6)、接近 (B7)
我只是添加这个只是为了理解代码。
代码:
这是我用 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 也有很多空闲的内存位置。