PIC18F26K80门控Timer3 TMR3IF标志置位异常求助
PIC18F26K80门控定时器调试问题求助
我花费数晚调试PIC18F26K80单片机的门控定时器功能,所用开发环境为MPLAB v4.15、XC8 v2.32。因项目需要实现长周期定时,我选用Timer4作为门控信号源驱动Timer3,查阅Microchip官方文档并多方检索相关资料后,仍无法解释以下两个核心异常问题:
- Timer3时钟源配置为Fosc/4时,
TMR3IF中断标志始终无法置位,也无法触发对应中断;临时改用Fosc时钟搭配1:4预分频的配置可正常工作,但无法定位Fosc/4时钟源失效的根本原因。 TMR3IF标志会在TMR3计数值为0x0001时提前触发。按照芯片设计逻辑,该标志应在Timer3计数值从0xFFFF溢出到0x0000时置位,当前PR4配置为0x63,理论上不应出现计数值过快跨过0x0000产生溢出的情况。
调试过程中还遇到其他异常现象,现优先求助上述两个问题的解决方案,完整测试代码如下:
/* * 门控定时器测试文件 */ // PIC18F26K80 配置位设置 // C语言源码配置位声明 // CONFIG1L #pragma config RETEN = OFF // VREG休眠使能位(超低压差稳压器禁用,由REGSLP位控制) #pragma config INTOSCSEL = HIGH // LF-INTOSC低功耗使能位(休眠模式下LF-INTOSC工作在高功耗模式) #pragma config SOSCSEL = DIG // SOSC电源选择与模式配置位(选择高功耗SOSC电路) #pragma config XINST = OFF // 扩展指令集(禁用) // CONFIG1H #pragma config FOSC = INTIO2 // 振荡器配置(内部RC振荡器) #pragma config PLLCFG = OFF // PLL 4倍频使能位(禁用) #pragma config FCMEN = OFF // 故障保护时钟监视器(禁用) #pragma config IESO = OFF // 内外振荡器切换模式(禁用) // CONFIG2L #pragma config PWRTEN = OFF // 上电定时器(禁用) #pragma config BOREN = SBORDIS // 掉电检测(硬件使能,SBOREN位禁用) #pragma config BORV = 3 // 掉电复位电压位(1.8V) #pragma config BORPWR = ZPBORMV // BORMV功耗等级(选择ZPBORMV而非BORMV) // CONFIG2H #pragma config WDTEN = SWDTDIS // 看门狗定时器(硬件使能WDT,SWDTEN位禁用) #pragma config WDTPS = 1048576 // 看门狗后分频器(1:1048576) // CONFIG3H #pragma config CANMX = PORTB // ECAN复用位(ECAN收发引脚分别映射到RB2、RB3) #pragma config MSSPMSK = MSK7 // MSSP地址屏蔽(7位地址屏蔽模式) #pragma config MCLRE = ON // 主清除使能(MCLR引脚使能,RE3引脚禁用) // CONFIG4L #pragma config STVREN = ON // 栈溢出复位(使能) #pragma config BBSIZ = BB2K // 引导块大小(2K字引导块大小) // CONFIG5L #pragma config CP0 = OFF // 代码保护 00800-03FFF(禁用) #pragma config CP1 = OFF // 代码保护 04000-07FFF(禁用) #pragma config CP2 = OFF // 代码保护 08000-0BFFF(禁用) #pragma config CP3 = OFF // 代码保护 0C000-0FFFF(禁用) // CONFIG5H #pragma config CPB = OFF // 引导区代码保护(禁用) #pragma config CPD = OFF // 数据EEPROM读保护(禁用) // CONFIG6L #pragma config WRT0 = OFF // 表写保护 00800-03FFF(禁用) #pragma config WRT1 = OFF // 表写保护 04000-07FFF(禁用) #pragma config WRT2 = OFF // 表写保护 08000-0BFFF(禁用) #pragma config WRT3 = OFF // 表写保护 0C000-0FFFF(禁用) // CONFIG6H #pragma config WRTC = OFF // 配置位写保护(禁用) #pragma config WRTB = OFF // 引导区表写保护(禁用) #pragma config WRTD = OFF // 数据EEPROM写保护(禁用) // CONFIG7L #pragma config EBTR0 = OFF // 表读保护 00800-03FFF(禁用) #pragma config EBTR1 = OFF // 表读保护 04000-07FFF(禁用) #pragma config EBTR2 = OFF // 表读保护 08000-0BFFF(禁用) #pragma config EBTR3 = OFF // 表读保护 0C000-0FFFF(禁用) // CONFIG7H #pragma config EBTRB = OFF // 引导区表读保护(禁用) // #pragma配置位声明必须放在项目头文件包含之前 // 请使用项目枚举值而非#define来定义ON和OFF #include <xc.h> #include <stdint.h> uint8_t tmr3Lprev = 0x00u; void interrupt ISR(void){ if(TMR3IF){ if(TMR3L == 0x00u){ //TMR3IF触发后,TMR3L应为0(PR4大于约0x20时) asm("BTG LATA, 2, 0"); //翻转输出引脚电平 }else{ LATAbits.LATA6 = 1; // 故障标志位 } asm("BTG LATA, 1, 0"); //翻转输出引脚电平 TMR3IF = 0; } if(TMR4IF){ if(TMR3L == ++tmr3Lprev){ //TMR4每次溢出时TMR3L应加1 asm("BTG LATA, 0, 0"); //翻转输出引脚电平 }else{ LATAbits.LATA5 = 1; // 故障标志位 } TMR4IF = 0; } return; } void main(void) { //时钟配置(系统及所有外设模块时钟源) OSCCONbits.IRCF = 0b111; OSCTUNEbits.PLLEN = 1; //开启4倍频锁相环,时钟频率为64MHz //将端口设置为输出 TRISA = 0x00; //将A口全部设置为输出 LATA = 0x00; //Timer4初始化 T4CONbits.T4OUTPS = 0; //后分频系数,实测不影响T4溢出周期 T4CONbits.T4CKPS1 = 1; //实测直接给T4CKPS赋值0x11时无法正确置位T4CKPS1 PR4 = 0x63; //循环周期值 T4CONbits.TMR4ON = 1; //1 = 使能Timer4 //Timer3初始化 T3CONbits.TMR3CS = 0b01; //时钟源选择,1 = 系统时钟Fosc;0 = 指令时钟Fosc/4 T3CONbits.T3CKPS = 0b10; // 0b11 = 1:8预分频;0b10 = 1:4预分频;0b01 = 1:2预分频;0b00 = 1:1预分频 T3CONbits.SOSCEN = 0; T3CONbits.RD16 = 1; //16位寄存器读写模式 T3CONbits.TMR3ON = 1; //1 = 使能Timer3 T3GCONbits.TMR3GE = 1; //使能Timer3门控 T3GCONbits.T3GPOL = 1; //Timer4输出高/低电平时使能Timer3计数 T3GCONbits.T3GTM = 0; //禁用翻转模式 T3GCONbits.T3GSPM = 0; //禁用单脉冲模式 T3GCONbits.T3GSS = 0x01; //选择TMR4输出作为门控源 WRITETIMER3(0x0000ul); TMR4 = 0x00; //中断配置 PIE2bits.TMR3IE = 1; PIE4bits.TMR4IE = 1; INTCONbits.GIE = 1; INTCONbits.PEIE = 1; //死循环 while(1){ } }
内容的提问来源于stack exchange,提问作者OndraCER552
相关产品推荐
相关产品推荐

