PIC16F877A外部中断是否影响所有端口?LCD乱码问题求助
问题分析与解决方案
1. LCD乱码核心原因
晶体管切换继电器/电机时,9V电池供电能力不足,会产生电源电压骤降和电磁干扰,这是LCD显示乱码的主要诱因,而非外部中断直接导致。此外,中断服务程序(ISR)执行时间过长,可能打断LCD的时序操作(LCD对指令发送时序要求严格,中途被打断会导致指令接收错误)。
2. PIC16F877A外部中断的影响范围
PIC16F877A的外部中断(INT0)仅绑定RB0引脚,触发时仅会触发中断服务程序,不会直接影响其他端口的硬件状态。但如果ISR中对端口寄存器进行操作,或者ISR执行时间过长导致主程序中端口操作(如LCD驱动)被打断,会间接影响端口功能。
3. 具体修复建议
电源侧优化
- 在继电器/电机的线圈两端并联1N4007续流二极管,抑制切换时产生的反向电动势,避免电源波动。
- 在PIC16F877A的VCC引脚和LCD的电源引脚旁,分别并联100nF陶瓷电容作为去耦电容,稳定局部供电。
- 若9V电池压降过大,改用7805稳压模块提供稳定5V电源,替代直接电池供电。
中断程序优化
- 简化ISR逻辑:将按键检测的复杂判断移到主程序,ISR仅设置标志位。例如:
主程序中再根据void interrupt() { if(INTCON.b0 ==1){ turnON=1; // 仅设置按键标志,不做复杂计算 key_pressed = 1; intcon.b0=0; } // 其他中断逻辑同理简化 }key_pressed标志处理按键逻辑,减少ISR执行时间。 - 避免在ISR中执行
delay_ms()等耗时操作,确保ISR快速退出。
LCD驱动优化
- 在更新LCD显示前,添加简单的状态判断,确保LCD处于可接收指令的状态;或者通过标志位控制,在中断触发时暂停LCD更新操作。
原问题
我正在基于PIC16F877A与LCD开展项目,当使用9V电池供电、通过继电器驱动电机的晶体管工作时,LCD出现显示异常。我在其他端口使用了外部中断按钮,怀疑该问题由外部中断导致?我已修改程序但问题仍未解决,晶体管切换时LCD始终显示乱码。此外想咨询:PIC16F877A的外部中断是否会影响所有端口?
电路图:相关电路已提供
项目代码
int SetMoist=85; int SetMoistR=0; int SetMoistL=0; int cset=0; int sensingCounter=0; int screenCounter=0; int getMoist=0; char *buffer = "00"; int turnON=1; #define LCD_ON lcd_cmd(_LCD_TURN_ON); #define LCD_OFF lcd_cmd(_LCD_TURN_OFF); //LCD sbit LCD_RS at RC1_bit; sbit LCD_EN at RC2_bit; sbit LCD_D4 at RC3_bit; sbit LCD_D5 at RC4_bit; sbit LCD_D6 at RC5_bit; sbit LCD_D7 at RC6_bit; sbit LCD_RS_Direction at TRISC1_bit; sbit LCD_EN_Direction at TRISC2_bit; sbit LCD_D4_Direction at TRISC3_bit; sbit LCD_D5_Direction at TRISC4_bit; sbit LCD_D6_Direction at TRISC5_bit; sbit LCD_D7_Direction at TRISC6_bit; //End of LCD void interrupt() { //Hardware interrupt flag if(INTCON.b0 ==1){ turnON=1; if(portb.b7==1){ if(SetMoist==99) {} else{ SetMoist++; cset=0; } } if(portb.b6==1){ turnON=1; if(SetMoist==5) {} else{ SetMoist--; cset=0; } } if(portb.b5==1){ turnON=1; portc.b0 =!portc.b0; } intcon.b0=0; } if(portb.b4==1){ turnON=1; } //End of Hardware interrupt flag // Timer0 flag if(INTCON.b2 ==1){ sensingCounter++; screenCounter++; //2 minutes timer for moisture if(sensingCounter==50){ sensingCounter=0; getMoist=ADC_Read(0); getMoist=(getMoist/1024.0)*100.0; if(getMoist>setMoist){ portc.b0=0b1; } else if(getMoist<setMoist){ portc.b0=0b0; } } //end moisture if(screenCounter==1000){ screenCounter=0; turnON=0; } intcon.b2=0; } //End of timer0 flag //interrupt } void main() { INTCON = 0b10101000; //Timer0 option_reg= 0b10000111; //TMR0=0; //End of timer0 trisb= 0b11111111; trisd = 0b00000000; trisc.b7 =0; trisc.b0=0; portc.b0=0; portd.b7=1; portc.b7= 1; trisa=0xff; Lcd_Init(); lcd_cmd(_LCD_CURSOR_OFF); lcd_out(1,1,"PENYIRAM TANAMAN"); lcd_out(2,5,"OTOMATIS"); delay_ms(1500); Lcd_cmd(_LCD_CLEAR); lcd_cmd(_LCD_CURSOR_OFF); lcd_out(1,3,"DENGAN CINTA"); lcd_out(2,4,"KELOMPOK 2"); delay_ms(1500); Lcd_cmd(_LCD_CLEAR); lcd_cmd(_LCD_CURSOR_OFF); lcd_out(1,3,"MENGHITUNG"); lcd_out(2,2,"KEKERINGAN..."); delay_ms(1500); lcd_cmd(_LCD_CLEAR); lcd_out(1,4,"KEKERINGAN:"); while(1){ if(cset==0){ cset=1; //calculate R SetMoistR= SetMoist % 10; switch (SetMoistR) { case 0: SetMoistR=0x3F; break; case 1: SetMoistR=0x06; break; case 2: SetMoistR=0x5B; break; case 3: SetmoistR=0x4F; break; case 4: SetmoistR=0x66; break; case 5: SetmoistR=0x6D; break; case 6: SetmoistR=0x7D; break; case 7: SetmoistR=0x07; break; case 8: SetmoistR=0x7F; break; case 9: SetmoistR=0x6F; break; } // end of R calculation //calculate L SetMoistL= (SetMoist/10) % 10; switch (SetMoistL) { case 0: SetMoistL=0x3F; break; case 1: SetMoistL=0x06; break; case 2: SetMoistL=0x5B; break; case 3: SetmoistL=0x4F; break; case 4: SetmoistL=0x66; break; case 5: SetmoistL=0x6D; break; case 6: SetmoistL=0x7D; break; case 7: SetmoistL=0x07; break; case 8: SetmoistL=0x7F; break; case 9: SetmoistL=0x6F; break; } //end of L calculation } //7Segment portd=SetmoistR; portc.b7=0; portd.b7=1; delay_ms(100); portd=SetmoistL; portd.b7=0; portc.b7=1; delay_ms(50); //End_7Segment //IntToStr(getMoist,buffer); buffer[0] = (getMoist/10)%10 +48; buffer[1] = (getMoist)%10+48; lcd_chr(2,8,buffer[0]); lcd_chr(2,9,buffer[1]); lcd_chr(2,11,'%'); if(turnON==1){ LCD_ON; } else{ LCD_OFF; } } //while } //main
内容的提问来源于stack exchange,提问作者Muhammad Rizki Saputra
相关产品推荐
相关产品推荐

