PIC10F320的TMR0计数器异常及触摸传感器复位失效问题求助
PIC10F320 触摸传感器复位TMR0功能调试问题
我是PIC编程新手,当前采用C语言开发(ASM汇编学习成本较高暂未使用),基于PIC10F320开发时遇到基础问题:自行配置的TMR0计数器工作异常,用于复位计数器的触摸传感器无响应,卡壳许久特来求助,感谢大家帮忙排查。
更新
大家好,感谢Kozmotronik指出错误,我已重新计算参数并重新分配寄存器位,解决了全局中断溢出问题;因T0CS默认是8位定时器,已移除option_reg相关错误配置,在Proteus中仿真10秒后定时器工作已恢复正常。目前仅剩触摸传感器复位功能未调试通,因没有触摸传感器仿真模型,我暂用普通按键替代,已附上Proteus电路图,麻烦各位帮忙查看问题,相关代码如下:
// CONFIG #pragma config FOSC = INTOSC // 振荡器选择 #pragma config BOREN = OFF // 掉电复位关闭 #pragma config WDTE = OFF // 看门狗定时器关闭 #pragma config PWRTE = OFF // 上电定时器关闭 #pragma config MCLRE = OFF // MCLR引脚功能选择位->MCLR引脚为数字输入,内部接VDD #pragma config CP = OFF // 代码保护关闭 #pragma config LVP = OFF // 低压编程关闭 #pragma config LPBOR = OFF // 掉电复位选择位关闭 #pragma config BORV = LO // 掉电复位电压选择为低阈值 #pragma config WRT = OFF // 闪存自写保护关闭 // #pragma配置语句需放在项目文件包含之前 // 开关状态请使用枚举定义,不要用#define定义ON/OFF #include <xc.h> #include <pic10f320.h> #define _XTAL_FREQ 8000000 #define SWITCH PORTAbits.RA2 #define PWMPin PORTAbits.RA1 #define LEDPin PORTAbits.RA0 unsigned long cnt; /* 主应用 */ void setup(void) { /** LATx寄存器配置 */ LATA = 0x00; /** TRISx寄存器配置 */ TRISA = 0x04; /** ANSELx寄存器配置 */ ANSELA = 0x00; // 清空占空比寄存器 PR2 = 255; T2CONbits.T2CKPS = 0b00; T2CONbits.TMR2ON = 0x01; /* * 计算说明: * 8MHz主频下,Tosc为125ns,Tcyc=4*Tosc=500ns * PR2设为十进制52、预分频器为1时,PWM周期为Tcyc*(PR2+1) = 500ns*53 = 26.5us * 100%占空比时: * 脉宽 = PWMxDCH/L(10位) * Tosc * 1(预分频系数) * 26.5us/125ns = PWMxDCH/L = 十进制212 * PWMxDCH = 0xd4 * PWMxDCL = 0x00 * * 75%占空比时,需计数的脉宽为26.5us*0.75=19.9us * 19.9us/125ns = PWMxDCH/L = 十进制159 * PWMxDCH = 0x9f * PWMxDCL = 0x00 */ // 配置TMR0用于生成延时 TMR0 = 0xFF; // 初始化TMR0值 // OPTION_REG = 0x07; //INTCON = 0xA0; > INTCONbits.TMR0IF = 0; // 清除TMR0中断标志位 > INTCONbits.TMR0IE = 1; OPTION_REGbits.T0CS = 0; // TMR0时钟源选择为系统时钟 OPTION_REGbits.PSA = 1; // TMR0不分配预分频器 /* * 计算公式: Fosc/4 = 8MHZ/4 = 2MHZ 单计数周期= 1 / 2MHZ = 0.0000005s 8位计数器溢出周期 = 0.0000005 * 256 = 0.000128s * * 每128us溢出一次 * 1秒延时所需溢出次数 = 1000000*(1/128) = 7812.5 * 1分钟所需计数 = 7812.5*60 = 468750 * 1小时所需计数 = 468750*60 = 28125000 * 12小时所需计数 = 28125000*12 = 337500000 */ } void main(void) { setup(); cnt = 0; //OSCCON = 2; while(1){ PWMPin = 1; LEDPin = 1; if(SWITCH==1){ cnt++; } if(INTCONbits.TMR0IF){ cnt++; > TMR0 = 0 ; /// 重置TMR0值 INTCONbits.TMR0IF=0; // 重置定时器中断标志位 } // 达到10秒阈值时触发(修改该数值可调整延时长度) if(cnt>78125){ // RA1输出75%占空比 // PWM1POL高电平有效;PWM1OE输出使能;PWM1EN模块使能; PWM2CON = 0xC0; PWM1CONbits.PWM1OE = 0x01; // 开启PWM1输出 PWM1CONbits.PWM1EN = 0x01; // 使能PWM1模块 PWM2DCH = 0x00; PWM2DCL = 0x00; PWM1DCH = 0x00; PWM1DCL = 0x00; PWM2DCH = 0xBF; PWM2DCL = 0x00; // LED呼吸灯效果 for(int i=0;i<212;i++){ PWM1DCH = i; __delay_ms(25); } for(int i=212;i>0;i--){ PWM1DCH = i; __delay_ms(25); } } } }
问题排查与修复方案
根据你提供的代码和描述,按键复位功能异常的核心问题和修复方式如下:
- 按键逻辑错误:当前代码检测到按键按下时执行
cnt++,而非你需要的重置计数器逻辑,这是最直接的问题 - 缺少按键消抖处理:机械按键按下/释放时会产生电平抖动,直接检测电平会导致触发不灵敏或误触发,需添加10~20ms的消抖逻辑
- TMR0初始值错误:setup函数中你将TMR0初始化为
0xFF,会导致第一次溢出时间远短于128us,建议改为0保持计数周期一致 - 全局中断未开启:你已经开启了TMR0的中断使能位
TMR0IE,但未开启全局中断使能位GIE和外设中断使能位PEIE,当前轮询TMR0IF的工作模式不受影响,后续如果启用中断功能必须补充这两个配置
修复后的核心代码片段
// setup函数补充配置 INTCONbits.GIE = 1; INTCONbits.PEIE = 1; TMR0 = 0; // 修正TMR0初始值 // 主循环按键逻辑修改为: if(SWITCH==1){ __delay_ms(20); // 消抖 if(SWITCH==1){ // 二次确认按键状态 cnt = 0; // 重置计数器 while(SWITCH==1); // 等待按键释放,避免单次按下多次触发 } }
内容的提问来源于stack exchange,提问作者Jones
相关产品推荐
相关产品推荐

