使用PIC16F18313测量PWM脉宽控制LED时无法进入逻辑循环的问题
PIC16F18313 PWM捕获无法进入脉宽判断逻辑的问题解决
问题场景
使用PIC16F18313测量Futaba遥控器接收器输出的PWM信号(输入RA2引脚),要求信号脉宽为1ms时熄灭LED(RA4引脚),1.5ms时点亮LED,但代码无法进入脉宽判断的逻辑分支。
问题根源分析
1. CCP捕获模式配置错误
代码中捕获上升沿后,仍将CCP1CON设置为0b00000101(上升沿捕获模式),导致永远无法捕获到下降沿,自然进不了脉宽计算的分支。正确逻辑应该是捕获上升沿后切换为下降沿捕获模式,完成脉宽计算后再切回上升沿捕获模式。
2. 脉宽判断数值完全错误
系统时钟为4MHz,定时器1设置了1:8预分频,因此定时器1的计数周期为:(4MHz / 4) / 8 = 125kHz → 每个计数对应8μs
1ms脉宽对应计数为 1000μs / 8μs = 125,1.5ms对应187.5,但原代码中判断的850-1150、1350-1650完全不符合实际计数范围,即使捕获到脉宽也无法触发正确的LED控制逻辑。
3. 冗余的引脚电平判断
在中断中直接读取RA2电平容易受信号抖动或中断延迟影响,且edge_flag已经标记了当前要捕获的边沿阶段,无需额外判断引脚电平。
修改后的代码
#include <xc.h> #include <pic16f18313.h> #pragma config FEXTOSC = OFF #pragma config RSTOSC = HFINT1 #pragma config WDTE = OFF #pragma config MCLRE = OFF #define _XTAL_FREQ 4000000 volatile unsigned int time_diff = 0; volatile unsigned int prev_capture = 0; volatile unsigned int capture_value = 0; volatile unsigned char edge_flag = 0; // 0:等待上升沿,1:等待下降沿 void __interrupt() ISR(void) { if (PIR4bits.CCP1IF) { PIR4bits.CCP1IF = 0; capture_value = (CCPR1H << 8) | CCPR1L; if (edge_flag == 0) { // 捕获上升沿,记录起始计数 prev_capture = capture_value; edge_flag = 1; // 切换为下降沿捕获模式 CCP1CON = 0b00000110; } else { // 捕获下降沿,计算脉宽 time_diff = capture_value - prev_capture; edge_flag = 0; // 切换回上升沿捕获模式 CCP1CON = 0b00000101; // 基于8μs计数周期,给10%余量的判断范围 if (time_diff >= 112 && time_diff <= 137) { // 对应0.896ms - 1.096ms LATA4 = 0; } else if (time_diff >= 168 && time_diff <= 207) { // 对应1.344ms - 1.656ms LATA4 = 1; } } } } void main(void) { OSCFRQ = 0x03; // 配置系统时钟为4MHz TRISA2 = 1; // RA2设为输入(PWM信号输入) TRISA4 = 0; // RA4设为输出(LED控制) ANSELA = 0; // 禁用所有模拟引脚功能 T1CON = 0b00110001; // 定时器1:1:8预分频,内部时钟,使能定时器 CCP1CON = 0b00000101;// 初始为上升沿捕获模式 CCP1EN = 1; // 使能CCP1模块 PIR4bits.CCP1IF = 0; // 清除CCP1中断标志 PIE4bits.CCP1IE = 1; // 使能CCP1中断 INTCONbits.GIE = 1; // 开启全局中断 while (1); }
额外调试建议
- 用示波器确认RA2引脚的PWM信号是否正常输出(1ms/1.5ms高电平,20ms周期)
- 可在中断中添加调试逻辑(比如翻转另一个LED引脚),确认CCP中断是否正常触发
- 检查硬件接线:RA2是否正确连接接收器输出,RA4是否正确连接LED(注意添加限流电阻)
内容的提问来源于stack exchange,提问作者Tiberiu Berchez
相关产品推荐
相关产品推荐

