PIC16F716 风机调速实战:PWM 与 ADC 抢时基,一张表算清 10~40 kHz 采样窗口

PIC16F716 只有一路 ECCP,PWM 模式下用不了硬件特殊事件触发 ADC。按 DS41206A_CN 的 9.5 TAD、1.6 µs 最小 TAD 与 20 µs 采集时间,用一张表算清 10/20/40 kHz 的采样窗口,并给出七步配置与六条排查。

2026-11-08
PIC16F716ECCPPWM 调速ADC 采样时序TAD风机控制

一台 24 V 轴流风机的调速板用 PIC16F716:P1A 输出 20 kHz PWM 推外部 MOSFET,AN0 采母线电流做限流,AN1 接 NTC 测模块温度。样机在 30% 占空比时读数稳定,转速拉到 70% 以上,电流采样值开始跳 20~30 个码,PID 输出跟着抖。结论先给:PIC16F716 只有一路 ECCP,PWM 模式下 CCP1M 必须写 1100~1111,而硬件“特殊事件触发 ADC”要求 CCP1M=1011,两者互斥;调速时 ADC 只能由软件启动,采样点要靠 TMR2 周期中断加一段定时延时挪到开关沿之后。20 MHz、20 kHz 下一次转换占 15.2 µs,真正留给采样的窗口只剩 32.4 µs。

本文按 Microchip《PIC16F716 数据手册》DS41206A_CN 第 5、6、7、8、12 章整理,寄存器位定义、TAD 档位、9.5 TAD 转换时间、1.6 µs 最小 TAD、20 µs 采集时间与 PWM 频率表均取自该手册;文中的微秒数是把 TOSC=1/FOSC、TCY=4 TOSC 代入后的算例。

一、现象:转速越高,电流采样越脏

把示波器两个通道分别接 P1A 和采样电阻,问题一眼能看出来:PWM 上升沿处采样电阻上有一个几微秒的尖峰,而 ADC 的结果恰好在这个尖峰上刷新。低占空比时尖峰窄、离下一次采样远,读数还看得过去;占空比一高,开关沿和采样点几乎重合,8 位 ADC 一个码是 5.12 V 参考下的 20 mV,跳 20~30 个码就是 400~600 mV 的误差,限流环自然跟着抖。

先说清一个前提:PIC16F716 的 ADC 是 8 位、4 通道(AN0~AN3),参考电压可选 VDD 或 RA3 上的外部电平,手册给出的总绝对误差、积分与微分线性误差都在 ±1 LSb 以内(VREF=VDD=5.12 V 条件)。分辨率只有 8 位,意味着没有余量去“滤”掉开关噪声,采样点必须自己找对。

二、两个时基,先分清楚谁管谁

PWM 走 Timer2:Timer2 的输入是 FOSC/4,预分频 1:1、1:4、1:16,8 位 TMR2 与 8 位 PR2 比较,相等后的下一个递增周期做三件事——TMR2 清零、P1A 置位、占空比从 CCPR1L 锁存到 CCPR1H。后分频器只影响 TMR2 中断频率,不参与 PWM 频率。

比较与捕捉走 Timer1:Timer1 是 16 位,内部时钟同样是 FOSC/4,预分频 1:1、1:2、1:4、1:8。这一点很容易记错:Timer1 数的是指令周期 TCY,不是 TOSC。20 MHz 时一个计数就是 200 ns,写 CCPR1 时要按 200 ns 算,不能按 50 ns 算。

ADC 自己没有时基。手册第 8 章给的启动方式只有两种:软件置位 GO/DONE,或者 ECCP 的特殊事件触发。没有“定时器溢出自动启动转换”这条硬件通路,这决定了后面的所有取舍。

模块时钟来源分频在本方案里的角色
Timer2FOSC/4预分频 1/4/16,后分频 1~16PWM 周期与占空比的时基
Timer1FOSC/4(内部)预分频 1/2/4/8特殊事件模式的周期寄存器;本方案用作单次延时
ECCPTimer1(比较)/ Timer2(PWM)—P1A 单输出;CCP1M 决定模式
A/DTAD:2/8/32 TOSC 或内部 RC9.5 TAD / 次8 位转换,无独立触发定时器

三、三个算式,把周期和占空比算准

手册 7.3.1 与 7.3.2 给了两条公式:PWM 周期 = (PR2+1) × 4 × TOSC × TMR2 预分频比;占空比时间 = TOSC × (CCPR1L:CCP1CON<5:4>) × TMR2 预分频比。第三条是最大分辨率 = log(FOSC/FPWM)/log2,硬件上限 10 位。

20 MHz 下想跑 10 kHz,周期 100 µs,PR2 只有 8 位,1:1 预分频最大只能做到 51.2 µs,必须把预分频提到 1:4,PR2=124,这时占空比只有 500 级,约 8.97 位;20 kHz 用 1:1、PR2=249,能做到 1000 级;40 kHz 是 PR2=124、500 级。手册表 7-3 中 19.53 kHz / 10 位那一行,就是 1:1 加 PR2=0xFF 的结果。

PWM 频率TMR2 预分频PR2最大分辨率占空比级数
1.22 kHz1:160xFF10 位1024
4.88 kHz1:40xFF10 位1024
19.53 kHz1:10xFF10 位1024
78.12 kHz1:10x3F8 位256
156.3 kHz1:10x1F7 位128
208.3 kHz1:10x176.6 位92

写占空比时,10 位值拆成 CCPR1L 的高 8 位和 CCP1CON<5:4> 的低 2 位。50% 对应 10 位值 500,即 CCPR1L=125、DC1B1:DC1B0=00。CCPR1L 可以随时写,但真正锁存到 CCPR1H 是在 PR2 与 TMR2 匹配的那一刻,这个双缓冲就是用来消掉改占空比时的毛刺。

还有一个手册自身的小坑:7.3.3 节“PWM 操作设置”第 3 步写的是清 TRISC<3>,但这颗器件的 P1A 在 RB3 上,7.3 节正文和表 7-4 都写 TRISB<3>。按 RB3 处理,别照着那一步去清 RC3。

四、8 位 ADC 的硬约束:TAD 不短于 1.6 µs

一次 8 位转换需要 9.5 个 TAD,而 TAD 最小 1.6 µs。20 MHz 下 2 TOSC 只有 100 ns、8 TOSC 只有 400 ns,都低于下限;32 TOSC 正好 1.6 µs,是唯一能用 TOSC 派生的档位。内部 RC 档典型 4 µs,但手册注明器件频率高于 1 MHz 时,RC 时钟只建议在休眠方式下使用。换算下来,20 MHz 时一次转换固定 15.2 µs。

器件频率2 TOSC8 TOSC32 TOSC内部 RC
20 MHz100 ns(不合规)400 ns(不合规)1.6 µs(可用)2~6 µs(仅休眠建议)
5 MHz400 ns(不合规)1.6 µs(可用)6.4 µs(可用)2~6 µs(仅休眠建议)
1.25 MHz1.6 µs(可用)6.4 µs(可用)25.6 µs(可用)2~6 µs(可用)

采集时间同样不能省。手册给的最小采集时间典型值 20 µs;只有输入电压相对上一次采样变化不超过 1 LSb(5.12 V 参考下 20 mV)时,才可以按 5 µs 估。采样保持电容 51.2 pF,建议信号源阻抗不超过 10 kΩ——分压电阻取大了,采集时间还得往上加。转换结束到重新开始采样之间还要 1.5 TAD,20 MHz 下是 2.4 µs。

五、特殊事件触发,为什么调速时用不上

手册 8.5 节说 ADC 可以由 ECCP 的特殊事件触发启动:CCP1M<3:0> 写 1011,触发信号一来就置位 GO/DONE、把 Timer1 复位为 0,而且不置位 TMR1IF、不影响 CCP1 引脚;ADON=0 时触发被 ADC 忽略,但 Timer1 照样复位。看起来正好是给周期采样准备的。

问题在于这个 1011 和 PWM 抢的是同一个寄存器字段。PWM 模式是 1100~1111,CCP1CON 只有一个,ECCP 也只有一个,同一时刻不可能既输出 PWM 又工作在特殊事件比较模式。所以只要风机是这颗芯片自己调速,硬件触发这条路就断了,ADC 只能靠软件置位 GO/DONE;特殊事件触发留给“不输出 PWM、只做定时采样”的场合,比如用外部驱动器的方案。

顺带记一条手册 5.4 节的细节:对 Timer1 的写操作和特殊事件复位同时发生时,写操作优先。以后真用到这个模式,初始化时先关 Timer1 再装值,能省掉一类偶发相位错位。

六、一张时序账:10/20/40 kHz 各剩多少采样窗口

采样窗口的算法很直接:一个 PWM 周期里,减去 9.5 TAD 的转换时间和 1.5 TAD 的恢复时间,剩下的才是采样保持电容真正跟踪输入的时间。20 MHz、32 TOSC 下这两段合计 17.6 µs,于是 10 kHz 剩 82.4 µs、20 kHz 剩 32.4 µs、40 kHz 只剩 7.4 µs。

PWM 频率周期PR2 / 预分频转换 9.5 TAD恢复 1.5 TAD剩余采集窗口对照 20 µs
10 kHz100 µs124 / 1:415.2 µs2.4 µs82.4 µs满足
20 kHz50 µs249 / 1:115.2 µs2.4 µs32.4 µs满足
40 kHz25 µs124 / 1:115.2 µs2.4 µs7.4 µs不满足(仅够 5 µs 快采条件)

这张表解释了两件事。第一,40 kHz 不是不能跑,但电流纹波必然超过 20 mV,7.4 µs 的窗口撑不起 20 µs 的采集时间,读数会随负载漂;要么把频率降到 20 kHz,要么换分辨率更高、采集更快的器件。第二,20 kHz 是这颗芯片的比较舒服的档位:1000 级占空比、32.4 µs 采集窗口,余量够放下 RC 滤波和源阻抗带来的额外时间。

七、七步落地:把采样点固定在开关沿后 10 µs

思路是用 TMR2 的周期中断当时基锚点——它和 PWM 同源,周期边界必然对齐;在中断里给 Timer1 装一个 10 µs 的单次延时,溢出时再启动转换。这样采样点落在开关尖峰之后,且每周期位置固定。20 MHz、Timer1 1:1 时 10 µs 是 50 个计数,预装值 65536−50=65486,即 0xFFCE。

初始化顺序按手册 7.4.7 的要求走,关键是“先配模式、等一个完整周期、最后才把引脚交给 ECCP”,避免上电瞬间 P1A 锁存状态不确定导致 MOSFET 误导通。极性也必须在引脚变成输出之前定好。

// PIC16F716,FOSC=20 MHz,PWM 20 kHz,采样点在周期起点后 10 µs
void fan_pwm_adc_init(void)
{
    TRISB3 = 1;                 // P1A 先保持输入
    PR2 = 249;                  // 50 µs 周期
    CCPR1L = 125;               // 占空比 500/1000 = 50%
    CCP1CON = 0b00001100;       // P1M=00 单输出,CCP1M=1100 高电平有效
    T2CON = 0b00000100;         // TMR2 预分频 1:1,后分频 1:1,开 Timer2
    ADCON1 = 0b000;             // PCFG=000,AN3~AN0 全模拟,VREF=VDD
    ADCON0 = 0b10000001;        // ADCS=10(32 TOSC),CHS=000,ADON=1
    T1CON = 0b00000000;         // Timer1 1:1,内部时钟 FOSC/4
    TMR2IE = 1; TMR1IE = 1; ADIE = 1;
    PEIE = 1; GIE = 1;
    while (!TMR2IF);            // 等第一个完整 PWM 周期结束
    TMR2IF = 0;
    TRISB3 = 0;                 // 现在才把 P1A 交给 ECCP
}

void isr_tmr2(void)             // 周期边界:装 10 µs 单次延时
{
    TMR2IF = 0;
    TMR1ON = 0;
    TMR1H = 0xFF; TMR1L = 0xCE; // 65536-50=65486,50×200 ns=10 µs
    TMR1ON = 1;
}

void isr_tmr1(void)             // 延时到:启动一次转换
{
    TMR1ON = 0; TMR1IF = 0;
    GO = 1;                     // 不要和开 ADON 写在同一条指令里
}

void isr_adc(void)              // 转换完成:读结果
{
    ADIF = 0;
    current_raw = ADRES;
}

几个容易漏的点:GO/DONE 只负责启动,转换完成后由硬件清零并置位 ADIF;读 ADRES 要在下一个 TCY 之后才可靠。Timer1 的写入会清零预分频计数器,1:1 时影响可以忽略,用了 1:4 以上就要把这段误差算进延时。中断响应本身有 2~3 个 TCY 的延迟,20 MHz 下大约 0.4~0.6 µs,示波器实测的采样点会比 10 µs 晚这一点,属于固定偏置,按实测值修一次预装值即可。

八、六条排查

现象根因改法
采样值随占空比跳采样点落在开关沿上TMR2 中断后加固定延时再置 GO/DONE
读数整体偏低且发散TAD 用了 2 TOSC,只有 100 ns20 MHz 改用 32 TOSC,保证 1.6 µs
换通道后第一码不准采集时间不足换通道后等满 20 µs;变化≤20 mV 才可按 5 µs
PWM 使能瞬间引脚乱跳先清 TRIS 后配 CCP1CON先配模式,等 TMR2IF 后再清 TRISB<3>
低速正常、高速丢码40 kHz 下窗口只剩 7.4 µs降到 20 kHz,或改用采集更快的器件
特殊事件触发没反应CCP1M 仍是 1100~11111011 与 PWM 互斥,调速时改软件启动

一句话总结:PIC16F716 的 PWM 和 ADC 共用同一颗芯片的有限资源,先把 PR2、TAD、采集时间三笔账算清,再决定 PWM 频率;调速方案里硬件特殊事件触发用不了,采样点要用 TMR2 中断加单次延时钉死在开关沿之后,这比事后加滤波更有效。

还想接着看:PIC18F4320 ECCP 半桥/全桥引脚映射与死区、PIC18F2480 ADC 采集时间与 ACQT/TAD 配置、dsPIC30F 输出比较单脉冲/双脉冲 PWM。

本文基于 Microchip《PIC16F716 数据手册》DS41206A_CN 第 5、6、7、8、12 章技术资料整理优化。

需要定制开发?

沧州艾诺威电子 — 国家高新技术企业,20+项国家专利
嵌入式系统开发 · 物联网方案 · AI智能硬件 · 一站式交付

立即微信咨询

电话:13930711029 | 邮箱:tech@czinv.com | 24小时内响应