Proteus中PIC18F4520带风扇温度传感器仿真异常排查
PIC18F4520温度风扇电路Proteus仿真异常排查
问题描述
基于PIC18F4520设计带风扇的温度传感器电路及配套代码,仿真时出现异常。电路设计参考条件:
仿真错误截图:
已尝试网络搜索解决方案但未找到有效办法,完整代码如下:
// PIC18F4520 Configuration Bit Settings // 'C' source line config statements // CONFIG1H #pragma config OSC = HS // Oscillator Selection bits (HS oscillator) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software) #pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting) // CONFIG2H #pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3H #pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset) #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation) #pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-001FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 (002000-003FFFh) not code-protected) #pragma config CP2 = OFF // Code Protection bit (Block 2 (004000-005FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection bit (Block 3 (006000-007FFFh) not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-001FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 (002000-003FFFh) not write-protected) #pragma config WRT2 = OFF // Write Protection bit (Block 2 (004000-005FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection bit (Block 3 (006000-007FFFh) not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #include"LCD4b_EXSTO.h" #include <stdio.h> #define _XTAL_FREQ 8000000 #define FAN1 PORTCbits.RC0 #define FAN2 PORTCbits.RC1 #define RES PORTCbits.RC2 //botao #define B1 PORTBbits.RB0 unsigned int VdigADC; float TENSAO, graus, porcen; void config_IO() { TRISC = 0X00; PORTC = 0XFF; } void config_ADC() {// PARA O AN0 ADCON0 = 0X01; // Seleção dos canais analógicos; Estado da conversão e Habilitação do Conversor A/D PADRAO ADCON1 = 0X0E; // Tensão de referência; Seleção de entrada analógica | PORTA AN3 -> 1011 ADCON2 = 0X87; // Alinhamento dos Bits (ADRES); Tempo de aquisição; Fonte de Clock para o converesor A/D PADRAO } void config_FOSC() { OSCCON = 0X00; OSCTUNE = 0X00; } void equacao(){ TENSAO = VdigADC * 0.004887585532746823069403714565; graus = TENSAO / 0.01190476190476190476190476190476; porcen = (graus * 100) / 420; } void conv_AN0() { __delay_ms(200); ADCON0bits.GO = 1; while(ADCON0bits.GO); VdigADC = ADRESH; VdigADC = (VdigADC << 8) + ADRESL; equacao(); } void porc(){ conv_AN0(); if(porcen<25) { RES=0; FAN1=1; FAN2=1; } else if(porcen>25 && porcen<=50) { RES=0; FAN1=0; FAN2=1; } else if(porcen>50 && porcen<=75) { RES=0; FAN1 =0; FAN2=0; } else if(porcen>75) { RES=1; FAN1 =0; FAN2=0; } } void lcd(){//BLOCO DO LCD char temperatura[16]; char percentual[16]; char fan1[16]; char fan2[16]; char res[16]; lcd_init(); lcd_clear(); __delay_ms(100); while(B1 == 1){ lcd_clear(); porc(); lcd_write(1,1,"FAN 1:");//linha 1 fan1 sprintf(fan1, "%d",FAN1); lcd_write(1,7,fan1); lcd_write(1,9,"FAN 2:");//linha 1 fan2 sprintf(fan2, "%d",FAN2); lcd_write(1,16,fan2); lcd_write(2,1,"RES:");//linha 2 res sprintf(res, "%d ",RES); lcd_write(2,6,res); __delay_ms(100); } lcd_clear(); __delay_ms(100); while(B1==0)// exibe temperatura e porcentagem { lcd_clear(); __delay_ms(100); porc(); //linha 1 lcd_write(1,1,"Temp:"); sprintf(temperatura, "%.1f%cC ", graus, 0XDF); lcd_write(1,9,temperatura); //linha 2 lcd_write(2,1,"Percent:"); sprintf(percentual, "%.1f%c ", porcen, 0X25); lcd_write(2,10,percentual); __delay_ms(100); } } void main() { config_FOSC(); config_ADC(); config_IO(); lcd(); }
异常原因排查及解决方案
1. 振荡器配置不匹配
代码中配置OSC = HS(高速外部振荡器),需检查Proteus电路:
- 为PIC18F4520添加8MHz外部晶振,与
_XTAL_FREQ 8000000匹配 - 晶振正确连接到OSC1(RA7)和OSC2(RA6)引脚
- 若未添加晶振或参数错误,单片机无法正常运行,直接引发仿真异常
2. ADC配置与硬件冲突
PBADEN = ON将PORTB<4:0>设为模拟输入,但代码中把RB0作为数字按键输入,需在config_IO()中添加:ADCON1bits.PCFG3 = 1; // 将RB0配置为数字引脚 TRISBbits.TRISB0 = 1; // 设置RB0为输入模式conv_AN0()中ADC读数顺序错误,正确的10位ADC合并方式应为:
原代码先赋值VdigADC = (ADRESH << 8) | ADRESL;VdigADC = ADRESH再移位,会导致高位数据被覆盖,读数错误
3. 端口初始化不完整
config_IO()仅配置了TRISC和PORTC,未配置TRISB,按键引脚RB0需设置为输入才能正确读取状态- 建议在
config_IO()中补充PORTB的配置:TRISB = 0x01; // RB0为输入,其余PORTB引脚根据需求配置
4. LCD驱动兼容性问题
- 确认
LCD4b_EXSTO.h中的引脚定义与Proteus电路中LCD的连接一致 - 驱动中的延时函数需与
_XTAL_FREQ匹配,若延时参数错误会导致LCD无法初始化或显示异常 - 尝试替换为标准LCD4位驱动代码,排除自定义驱动的问题
5. 仿真模型与代码配置冲突
- 检查Proteus中PIC18F4520的配置是否与代码中的
#pragma config一致,尤其是振荡器、MCLRE等关键配置 - 更新Proteus的PIC器件库,旧模型可能存在配置兼容性bug
6. 代码逻辑死循环
lcd()函数中的两个while循环会导致程序卡在单一模式,无法响应按键切换,需添加防抖处理并优化循环逻辑:// 示例:添加按键防抖 while(1){ if(B1 == 1){ __delay_ms(20); // 防抖延时 if(B1 == 1){ // 显示风扇状态逻辑 while(B1 == 1); // 等待按键释放 __delay_ms(20); } }else{ // 显示温度和百分比逻辑 __delay_ms(100); } }
内容的提问来源于stack exchange,提问作者AllryaLinez
相关产品推荐
相关产品推荐

