You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:25:35