用52单片机,计数器,定时器,过零检测,双向可控硅,控制一个220v灯泡,实现8个档位调节,外部中断控制按键,一个按键增加亮度,一个按键减少亮度,写一个调光程序
时间: 2024-05-09 20:16:41 浏览: 17
以下是一个基于52单片机的调光程序。程序使用定时器和过零检测来控制双向可控硅的触发角,从而控制220V灯泡的亮度。外部中断控制按键用于增加或减少灯泡的亮度。
```
#include <reg52.h>
sbit keyUp = P1^0; // 增加亮度按键
sbit keyDown = P1^1; // 减少亮度按键
sbit triac = P1^2; // 双向可控硅控制引脚
sbit zc = P1^3; // 过零检测引脚
unsigned char dimming = 0; // 当前亮度档位
unsigned char lastDimming = 0; // 上一个亮度档位
void delay(unsigned int t)
{
while (t--);
}
void timer0Init()
{
// 定时器工作在模式1,自动重载
TMOD |= 0x01;
// 定时器初值为65536-5000=60536,即50ms
TH0 = 0xEB;
TL0 = 0x38;
// 开启定时器0中断
ET0 = 1;
EA = 1;
// 启动定时器0
TR0 = 1;
}
void triacOn(unsigned char angle)
{
// 触发角计算公式:(1 + 正弦值) * 500,angle取值0~99
unsigned int triggerAngle = (1 + (unsigned int)(sin(angle * 3.1415926 / 100) * 100)) * 500;
triac = 1;
delay(triggerAngle);
triac = 0;
}
void zcInterrupt() interrupt 0
{
// 当过零检测引脚检测到下降沿时,触发双向可控硅
triacOn(dimming);
}
void timer0Interrupt() interrupt 1
{
static unsigned char count = 0;
count++;
if (count == 20) // 20 * 50ms = 1s
{
count = 0;
// 检查亮度档位是否有变化,有变化则重新计算触发角
if (lastDimming != dimming)
{
lastDimming = dimming;
triacOn(dimming);
}
}
}
void main()
{
// 配置外部中断0,用于过零检测
IT0 = 1;
EX0 = 1;
EA = 1;
timer0Init();
while (1)
{
if (keyUp == 0) // 增加亮度按键按下
{
delay(1000); // 延时消除按键抖动
if (keyUp == 0 && dimming < 8)
{
dimming++;
}
while (keyUp == 0); // 等待按键松开
}
if (keyDown == 0) // 减少亮度按键按下
{
delay(1000); // 延时消除按键抖动
if (keyDown == 0 && dimming > 0)
{
dimming--;
}
while (keyDown == 0); // 等待按键松开
}
}
}
```
程序的核心是 `triacOn` 函数,它根据当前的亮度档位计算触发角,并触发双向可控硅。`zcInterrupt` 函数用于检测过零点,并在过零点时触发 `triacOn` 函数。定时器中断用于检查亮度档位是否发生变化,并重新计算触发角。外部中断用于检测过零点,触发双向可控硅。
在 `main` 函数中,通过检测外部中断和按键状态来增加或减少亮度档位。由于双向可控硅的响应时间很短,因此可以通过这种方式实现实时调光。
注意,程序中采用的是简单的延时方式实现延时,这种方式并不精确,实际应用中需要根据需要选择更为精确的方式。此外,程序也没有考虑到电网电压波动的情况,如果需要更为稳定的调光效果,可以采用反馈控制等方式。