PIC16F716 只有一路 ECCP,PWM 模式下用不了硬件特殊事件触发 ADC。按 DS41206A_CN 的 9.5 TAD、1.6 µs 最小 TAD 与 20 µs 采集时间,用一张表算清 10/20/40 kHz 的采样窗口,并给出七步配置与六条排查。
一台 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 的特殊事件触发。没有“定时器溢出自动启动转换”这条硬件通路,这决定了后面的所有取舍。
| 模块 | 时钟来源 | 分频 | 在本方案里的角色 |
|---|---|---|---|
| Timer2 | FOSC/4 | 预分频 1/4/16,后分频 1~16 | PWM 周期与占空比的时基 |
| Timer1 | FOSC/4(内部) | 预分频 1/2/4/8 | 特殊事件模式的周期寄存器;本方案用作单次延时 |
| ECCP | Timer1(比较)/ Timer2(PWM) | — | P1A 单输出;CCP1M 决定模式 |
| A/D | TAD:2/8/32 TOSC 或内部 RC | 9.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 kHz | 1:16 | 0xFF | 10 位 | 1024 |
| 4.88 kHz | 1:4 | 0xFF | 10 位 | 1024 |
| 19.53 kHz | 1:1 | 0xFF | 10 位 | 1024 |
| 78.12 kHz | 1:1 | 0x3F | 8 位 | 256 |
| 156.3 kHz | 1:1 | 0x1F | 7 位 | 128 |
| 208.3 kHz | 1:1 | 0x17 | 6.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 位转换需要 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 TOSC | 8 TOSC | 32 TOSC | 内部 RC |
|---|---|---|---|---|
| 20 MHz | 100 ns(不合规) | 400 ns(不合规) | 1.6 µs(可用) | 2~6 µs(仅休眠建议) |
| 5 MHz | 400 ns(不合规) | 1.6 µs(可用) | 6.4 µs(可用) | 2~6 µs(仅休眠建议) |
| 1.25 MHz | 1.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 再装值,能省掉一类偶发相位错位。
采样窗口的算法很直接:一个 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 kHz | 100 µs | 124 / 1:4 | 15.2 µs | 2.4 µs | 82.4 µs | 满足 |
| 20 kHz | 50 µs | 249 / 1:1 | 15.2 µs | 2.4 µs | 32.4 µs | 满足 |
| 40 kHz | 25 µs | 124 / 1:1 | 15.2 µs | 2.4 µs | 7.4 µs | 不满足(仅够 5 µs 快采条件) |
这张表解释了两件事。第一,40 kHz 不是不能跑,但电流纹波必然超过 20 mV,7.4 µs 的窗口撑不起 20 µs 的采集时间,读数会随负载漂;要么把频率降到 20 kHz,要么换分辨率更高、采集更快的器件。第二,20 kHz 是这颗芯片的比较舒服的档位:1000 级占空比、32.4 µs 采集窗口,余量够放下 RC 滤波和源阻抗带来的额外时间。
思路是用 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 ns | 20 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~1111 | 1011 与 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小时内响应