如何用51写一个pwm占空比和频率都可调的灯(要求按下s1键小灯占空比加%10,按下s2键小灯占空比减小%10,按下s3键小灯频率加50hz,按下s4键小灯频率减50hz)
#include <reg51.h>
sbit S1 = P1^0; // S1键
sbit S2 = P1^1; // S2键
sbit S3 = P1^2; // S3键
sbit S4 = P1^3; // S4键
sbit LED = P2^0; // 控制小灯的引脚
unsigned int pwm_duty_cycle = 500; // 初始占空比为50%(0-1000)
unsigned int pwm_frequency = 1000; // 初始频率为1000Hz
// 延时函数
void delay(unsigned int count)
{
unsigned int i, j;
for (i = 0; i < count; i++)
for (j = 0; j < 1000; j++);
}
// 初始化定时器0
void init_timer0()
{
TMOD |= 0x01; // 设置定时器0为工作在模式1(16位定时器)
TH0 = (65536 - 50000) / 256; // 定时50ms
TL0 = (65536 - 50000) % 256;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 允许总中断
}
// 更新占空比和频率
void update_pwm()
{
CCAP0L = pwm_duty_cycle % 256;
CCAP0H = pwm_duty_cycle / 256;
TH0 = (65536 - (50000 / pwm_frequency)) / 256;
TL0 = (65536 - (50000 / pwm_frequency)) % 256;
}
// 定时器0中断处理函数
void timer0_isr() interrupt 1
{
TF0 = 0; // 清除定时器0溢出标志位
LED = ~LED; // 反转小灯状态
}
// 主函数
void main()
{
init_timer0(); // 初始化定时器0
update_pwm(); // 更新占空比和频率
while (1)
{
if (S1 == 0) // 检测S1键是否按下
{
delay(20); // 延时去抖动
if (S1 == 0)
{
while (S1 == 0); // 等待按键释放
pwm_duty_cycle += 100; // 增加占空比10%
if (pwm_duty_cycle > 1000)
pwm_duty_cycle = 1000;
update_pwm(); // 更新占空比和频率
}
}
if (S2 == 0) // 检测S2键是否按下
{
delay(20); // 延时去抖动
if (S2 == 0)
{
while (S2 == 0); // 等待按键释放
pwm_duty_cycle -= 100; // 减小占空比10%
if (pwm_duty_cycle > 1000)
pwm_duty_cycle = 0;
update_pwm(); // 更新占空比和频率
}
}
if (S3 == 0) // 检测S3键是否按下
{
delay(20); // 延时去抖动
if (S3 == 0)
{
while (S3 == 0); // 等待按键释放
pwm_frequency += 50; // 增加频率50Hz
update_pwm(); // 更新占空比和频率
}
}
if (S4 == 0) // 检测S4键是否按下
{
delay(20); // 延时去抖动
if (S4 == 0)
{
while (S4 == 0); // 等待按键释放
if (pwm_frequency > 50)
pwm_frequency -= 50; // 减小频率50Hz
update_pwm(); // 更新占空比和频率
}
}
}
}