找回密码
 立即注册
查看: 152|回复: 12

Ai8051U 内置比较器做过零检测 - 移相触发输出驱动可控硅调光

[复制链接]

12

主题

53

回帖

844

积分

高级会员

积分
844
发表于 2026-10-27 17:34:25 | 显示全部楼层 |阅读模式
近来在做一个调光的案子,打了一次板子,测出来的过零点不是太理想,网上找了一圈,电路也大同小异,要么复杂元件多,要么与我的一样简单但效果不太好。

论坛内的一个例子这个链接内二楼的方案不错,桥式整流+光耦隔离
1.png
但成本和PCB占用较大,我本次是非隔离方案,不采用此电路,网上找到的参考电路还有如下几种:
2.png
3.png
4.png
5.png
6.png
7.png
本着节省元件,也用上比较器来精准点,就尝试用Ai8051U 内置比较器做过零检测,是否可靠呢?
电路图如下:
9.png
各位大师来判断下是否可行:
  1. /******************************************************
  2. main.c
  3. Ai8051U 内置比较器过零检测 + P1.0 移相触发输出
  4. 芯片:AI8051U-34K64-LQFP48
  5. 系统时钟:40MHz(在 STC-ISP 下载时选择 40MHz)
  6. 硬件连接说明:
  7.   - 过零信号从 L 极引出,经 3 个 200K/0805 电阻降压,
  8.     接入 P4.6,并在端口处用分压电阻抬高到 1.19V。电源3.3V,上电阻10K,下电阻5.65K
  9.   - P4.6 为比较器正端 CMP+,配置成高阻输入。
  10.   - 比较器负端 CMP- 使用内部 BandGap 经 OP 后的 REFV(1.19V)。
  11.   - P4.5 为比较器硬件输出脚(CMPO_S = 0),仅用于示波器观察。
  12.   - P1.0 为移相触发脉冲输出,推挽输出,接光耦/可控硅触发电路。
  13. 工作过程:
  14.   1. 交流电每次过零,比较器中断置 zero_flag;
  15.   2. 主循环检测到 zero_flag 后启动定时器0,延时 PHASE_US 微秒;
  16.   3. 定时器0 中断里 P1.0 = 0(触发脉冲开始),并把定时器重装载值
  17.      改为 PULSE_US 后继续运行;
  18.   4. 第二次定时器0 中断里 P1.0 = 1(触发脉冲结束),关闭定时器0。
  19. 注意:定时器0 中断里用计数器 to0_step 区分“延时到”和“脉宽到”两个阶段。
  20. ******************************************************/
  21. #include "Ai8051U.H"      
  22. #include "intrins.h"
  23. #define SYS_CLK         40000000UL  // 系统时钟 40MHz,必须与 ISP 下载时选择的频率一致
  24. #define TM0_PS          0           // 定时器0 预分频 TM0PS,0 表示不分频
  25. #define PHASE_US        5000UL      // 移相延时,单位 us(50Hz 半周期为 10000us,
  26.                                     // 5000us 即 90 度相位)
  27. #define PULSE_US        200UL       // 触发脉宽,单位 us
  28. bit  zero_flag;                     // 过零标志,比较器中断置 1,主循环清 0
  29. unsigned char to0_step = 0;         // 定时器0 阶段标志:0 空闲,1 等待移相结束,2 等待脉宽结束
  30. /* 根据 us 计算定时器0 重装载值 */
  31. /* 依据:定时器周期 = (65536-[TH0,TL0]) / (SYSclk/(TM0PS+1)) */
  32. void Timer0_LoadUS(unsigned int us)
  33. {
  34.     unsigned long ticks;
  35.     ticks = (unsigned long)us * (SYS_CLK / 1000000UL) / (TM0_PS + 1);
  36.     ticks = 65536UL - ticks;
  37.     TR0 = 0;                        // 先停定时器,保证写入的是重装载寄存器
  38.     TL0 = (unsigned char)(ticks & 0xff);
  39.     TH0 = (unsigned char)((ticks >> 8) & 0xff);
  40. }
  41. /*----------- 比较器中断:过零捕获 -----------*/
  42. void CMP_Isr(void) interrupt 21
  43. {
  44.     CMPIF = 0;                      // 清比较器中断标志,必须软件清零
  45.     zero_flag = 1;                  // 通知主循环:已到过零点
  46. }
  47. /*----------- 定时器0 中断:移相延时 + 触发脉宽 -----------*/
  48. void TM0_Isr(void) interrupt 1
  49. {
  50.     if (to0_step == 1)              // 移相延时结束
  51.     {
  52.         P10 = 0;                    // 输出触发脉冲(低电平有效)
  53.         to0_step = 2;
  54.         Timer0_LoadUS(PULSE_US);    // 重装载为脉宽时间
  55.         TR0 = 1;                    // 重新启动
  56.     }
  57.     else if (to0_step == 2)         // 脉宽结束
  58.     {
  59.         P10 = 1;                    // 结束触发脉冲
  60.         to0_step = 0;
  61.         TR0 = 0;                    // 关闭定时器0
  62.     }
  63. }
  64. void main(void)
  65. {
  66.     /* ---------- 系统基本初始化 ---------- */
  67. #if (defined 32位模式)
  68.     EAXFR = 1;                      // 32位模式:允许访问扩展特殊功能寄存器 XFR
  69. #else
  70.     P_SW2 |= 0x80;                  // 8位模式:允许访问扩展特殊功能寄存器 XFR
  71. #endif
  72.     WTST = 0;                       // 设置取程序代码等待时间,0 表示不等待,最快运行
  73.     CKCON = 0;                      // 设置访问片内 xdata 速度,0 表示最快速度访问
  74.     /* ---------- I/O 口工作模式设置 ---------- */
  75.     P0M0 = 0x00;  P0M1 = 0x00;      // P0 准双向口
  76.     P1M0 = 0x00;  P1M1 = 0x00;      // P1 先全部为准双向口
  77.     P1M0 |= 0x01;                   // P1.0 推挽输出(M1=0, M0=1)
  78.     P1M1 &= ~0x01;
  79.     P1 = 0xff;                      // P1.0 初始输出高电平(不触发)
  80.     P2M0 = 0x00;  P2M1 = 0x00;      // P2 准双向口
  81.     P3M0 = 0x00;  P3M1 = 0x00;      // P3 准双向口
  82.     P4M0 = 0x00;  P4M1 = 0x00;      // P4 先全部为准双向口
  83.     P4M0 |= 0x20;                   // P4.5 推挽输出(M1=0, M0=1),比较器输出观察脚
  84.     P4M1 &= ~0x20;
  85.     P4M0 &= ~0x40;                  // P4.6 高阻输入(M1=1, M0=0),比较器正端
  86.     P4M1 |= 0x40;
  87.     P5M0 = 0x00;  P5M1 = 0x00;      // P5 准双向口
  88.     /* ---------- 定时器0 初始化:模式0,16位自动重载,1T ---------- */
  89.     TMOD &= 0xf0;                   // 清 T0_M1/T0_M0/T0_C/T/T0_GATE
  90.     TMOD |= 0x00;                   // 模式0:16位自动重载,GATE=0,C/T=0(定时)
  91.     AUXR |= 0x80;                   // T0x12 = 1,定时器0 工作在 1T 模式
  92.     TM0PS = TM0_PS;                 // 定时器0 时钟 = SYSclk / (TM0PS+1)
  93.     TR0 = 0;                        // 定时器0 暂不启动
  94.     ET0 = 1;                        // 使能定时器0 中断
  95.     /* ---------- 比较器扩展配置 CMPEXCFG ---------- */
  96.     CMPEXCFG = 0x00;                // 先清零
  97.     CMPEXCFG |= 0x80;               // CHYS[1:0]=10:DC 迟滞 20mV,滤除噪音
  98.     CMPEXCFG &= ~0x03;              // CMPPS[1:0]=00:P4.6 为 CMP+ 输入脚
  99.     CMPEXCFG |= 0x04;               // CMPNS=1:内部 1.19V REFV 为 CMP- 输入脚
  100.     /* ---------- 比较器控制寄存器 ---------- */
  101.     CMPCR1 = 0x00;                  // 关闭比较器、清标志、禁止中断和输出
  102.     CMPCR2 = 0x00;                  // INVCMPO=0 正向输出,DISFLT=0 使能0.1us模拟滤波
  103.     CMPCR2 |= 0x10;                 // LCDTY[5:0]=0x10,经16个去抖时钟后输出
  104.                                     // (实际滤波时间为 (n+2) 个系统时钟)
  105.     P_SW2 &= ~0x08;                 // CMPO_S=0:比较器结果输出到 P4.5
  106.     PIE = 1;                        // 使能比较器上升沿中断
  107.     NIE = 1;                        // 使能比较器下降沿中断
  108.     CMPOE = 1;                      // 使能比较器结果输出到 P4.5
  109.                                     // 若 P4.5 不用作观察,改为 CMPOE = 0
  110.     CMPEN = 1;                      // 使能比较器模块
  111.     /* ---------- 中断优先级:比较器最高,定时器0 最低 ---------- */
  112.     IP2H |= 0x20;  IP2 |= 0x20;     // PCMPH,PCMP = 11,比较器中断优先级 3 级(最高)
  113.     IPH  &= ~0x02; IP  &= ~0x02;    // PT0H,PT0 = 00,定时器0 中断优先级 0 级(最低)
  114.     EA = 1;                         // 打开总中断
  115.     while (1)
  116.     {
  117.         if (zero_flag)              // 检测到过零点
  118.         {
  119.             zero_flag = 0;
  120.             to0_step = 1;           // 进入"移相延时"阶段
  121.             Timer0_LoadUS(PHASE_US);
  122.             TR0 = 1;                // 启动定时器0,开始移相计时
  123.         }
  124.     }
  125. }
复制代码



回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-10-27 19:35:08 | 显示全部楼层
我的看法是,
1直接接L不安全。
2p4.6过零输入端静态时在1.19v,在临界状态,容易干扰。
回复

使用道具 举报 送花

已绑定手机

11

主题

484

回帖

1362

积分

金牌会员

积分
1362
发表于 2026-10-27 20:18:03 | 显示全部楼层
全波整流经限流电阻、钳位二极管接外部中断INT,由于下降沿触发中断的时间会超前过零点。通过示波器测出下降沿触发中断的时间与过零点的时间差,由外部中断启动定时器就可获得精准过零点。再以此增加延时移相触发可控硅调光。
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-10-27 20:50:43 | 显示全部楼层
你的目的是调光,即调功率。
追求过零准确性意义不大。
过零点只影响设计的pwm占空比上限。
比如ac在30v时检测到过零,功率调整最大依然能达到90%左右。
追求在ac在 1v,2v,3v...等检测到,意义不大。
真要准确,先隔离后,再放大比较。

回复

使用道具 举报 送花

83

主题

8317

回帖

1万

积分

超级版主

积分
17932
发表于 2026-10-27 22:35:53 | 显示全部楼层
调光灯的过零检测基本都是不隔离的,也能很可靠的,可以用三极管,也可以不用,如果使用贴片电阻,220V输入一定是串联3个电阻(推荐0805封装),比如3个200K串联到三极管B极或IO(外部中断口),三极管B极或IO对地接一个nF电容。
回复

使用道具 举报 送花

12

主题

53

回帖

844

积分

高级会员

积分
844
 楼主| 发表于 2026-10-28 07:44:05 | 显示全部楼层
wul*** 发表于 2026-10-27 20:18
全波整流经限流电阻、钳位二极管接外部中断INT,由于下降沿触发中断的时间会超前过零点。通过示波器测出下 ...

本意是不想用全波整流,四个二极管或者桥堆占PCB不少面积了
回复

使用道具 举报 送花

12

主题

53

回帖

844

积分

高级会员

积分
844
 楼主| 发表于 2026-10-28 07:49:02 | 显示全部楼层
jrc*** 发表于 2026-10-27 20:50
你的目的是调光,即调功率。
追求过零准确性意义不大。
过零点只影响设计的pwm占空比上限。

功率调整差异点问题不大,主要考虑点是正半周或者负半周如果过零点不同,有可能个别LED会有闪烁的可能,这个是猜想,没实证。
用桥堆的话,正负半周都是相同的,能破除电源供电的畸形波和瞬态脉冲就基本没事了
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-10-28 09:48:15 | 显示全部楼层
如果用可控硅控制LED,频闪比较明显。
LED适合使用恒流控制。

在15V到30V检测到过零,都是可以的。
如在AC30V导通,功率占比>99.9x%,见下图AI给的计算;
由此可知,AC30V以下导通,功率已经没有多大变化。
简单说,5V导通,与30V导通,区别不大。

截图202610280947063965.jpg

回复

使用道具 举报 送花

9

主题

772

回帖

5311

积分

论坛元老

积分
5311
发表于 2026-10-28 12:39:16 | 显示全部楼层
如果用光耦做精确过零检测,必须考虑光耦开关速度对过零点的影响.初级经过限流电阻和整流桥后再接光耦,如果脉宽很窄,
初级电压幅度,初级侧限流电阻大小,光耦电流传输比,光耦输出上拉电阻对输出波形有很大影响,很可能输出波形不再是方的,而是幅度更低的三角波,
更不好的是光耦的电流传输比是个一致性很大的参数,对温度也非常敏感,量产时很难保证过零信号稳定一致.
所以设计精密过零电路时候元件参数要留足够的余量.并且根据实际需求,增加合适的过零点补偿算法.

回复

使用道具 举报 送花

12

主题

53

回帖

844

积分

高级会员

积分
844
 楼主| 发表于 2026-10-28 14:21:11 | 显示全部楼层
网*** 发表于 2026-10-28 12:39
如果用光耦做精确过零检测,必须考虑光耦开关速度对过零点的影响.初级经过限流电阻和整流桥后再接光耦,如果 ...

也就是说,非隔离的更好处理?
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-8 01:07 , Processed in 0.076828 second(s), 86 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表