PIC12F675休眠时WDT复位问题:需实现长间隔唤醒
解决PIC12F675长休眠唤醒的WDT复位问题
问题概述
基于PIC12F675的项目需求:
- 利用GPIO1内置ADC采集电压,根据测量结果控制LED点亮2秒
- 进入休眠状态,约1~2小时后自动唤醒,重复采集流程
当前遇到的问题:看门狗定时器(WDT)最长仅支持约2.3秒超时,将SLEEP()放入循环后,单片机仍会在2.3秒后被WDT复位,无法实现长周期休眠。要求无需外部触发,解决该WDT复位问题。
问题根源
代码中仅通过配置位开启了WDT(WDTE = ON),但未将WDT设置为唤醒模式。默认情况下,PIC12F675的WDT超时会触发单片机复位,而非仅唤醒休眠状态,导致循环休眠逻辑失效。
解决方案
1. 切换WDT至唤醒模式
通过OPTION_REG寄存器的WDTE位(运行时寄存器位,非配置位)将WDT设置为唤醒模式:
WDTE = 0:WDT超时仅唤醒休眠,不触发复位WDTE = 1:WDT超时触发复位(默认状态)
2. 配置WDT最大预分频
将WDT预分频器设为最大(1:128),对应最长约2.3秒的超时时间,通过多次休眠循环累计实现长周期休眠。
3. 休眠前的必要操作
每次休眠前调用CLRWDT()清除WDT定时器,确保从0开始计时,避免提前超时。
修正后的代码
#include <xc.h> // Configuration bits #pragma config FOSC = INTRCIO // Internal oscillator #pragma config WDTE = ON // Enable WDT (required for wake-up) #pragma config PWRTE = OFF // Disable Power-up Timer #pragma config MCLRE = OFF // MCLR pin is digital I/O #pragma config BOREN = ON // Enable Brown-out Reset #pragma config CP = OFF // Disable Code Protection #define _XTAL_FREQ 4000000 // Internal oscillator frequency for delay functions #define SLEEP_CYCLES_1H 1563 // ~2.3s per cycle × 1563 ≈ 3600s (1 hour) #define SLEEP_CYCLES_2H 3126 // ~2.3s per cycle × 3126 ≈ 7200s (2 hours) void main() { TRISIO = 0b00000010; // GP1 (ADC input) = input, GP0 (LED output) = output ANSEL = 0b00000010; // Set GP1 as analog input OPTION_REG = 0b00000111; // WDT prescaler 1:128 (~2.3s timeout), WDTE=0 (wake-up mode) while (1) { // ADC Measurement ADCON0 = 0b00000001; // Select GP1 as ADC channel __delay_us(20); // ADC acquisition delay GO_nDONE = 1; // Start conversion while (GO_nDONE); // Wait for conversion complete // Control LED based on ADC result uint16_t adcResult = ((ADRESH << 8) + ADRESL); if (adcResult > 512) { GP0 = 1; __delay_ms(2000); GP0 = 0; } // Cycle sleep to accumulate total duration for (unsigned int i = 0; i < SLEEP_CYCLES_1H; i++) { CLRWDT(); // Reset WDT timer before sleep SLEEP(); // Enter sleep, wake on WDT timeout } } }
关键细节说明
OPTION_REG配置:0b00000111的最后三位(PS2-PS0)设置为111,对应WDT预分频比1:128,结合内部振荡器得到最长约2.3秒的超时周期。- 休眠次数计算:1小时=3600秒,3600÷2.3≈1563次循环,以此累计实现长休眠。
CLRWDT():必须在每次休眠前调用,确保WDT从头开始计时,避免因残留计时导致提前唤醒或复位。
内容的提问来源于stack exchange,提问作者Samuel
相关产品推荐
相关产品推荐

