89C52RC单片机PWM波输出控制程序(频率50kHz,占空比可调)
由于涉及到定时器中断和按键扫描,需要使用中断和定时器来实现。
首先,需要配置定时器的计时器模式和计数值,以实现PWM波的生成。计时器模式选择16位自动重装载模式,计数值为12,即定时器每计满12个时钟周期就会产生一个中断。然后,需要通过占空比计算来设置定时器中断的触发时间,即占空比越大,定时器中断的触发时间越晚,PWM波的高电平时间越长。
其次,需要配置按键的输入方式和中断方式,以实现按键的响应。按键的输入方式选择上拉输入,按键的中断方式选择下降沿触发中断。按下S1键,占空比就增加5%,按下S2键,占空比就减少5%,需要通过修改占空比计算来实现。
最后,需要在主函数中循环等待中断触发,以保持程序的运行。
下面是程序的具体实现:
#include <reg52.h>
sbit S1 = P1^0; // S1键
sbit S2 = P1^1; // S2键
unsigned int count; // 定时器计数值
unsigned int period; // PWM波周期
unsigned int high_time; // PWM波高电平时间
unsigned char duty; // 占空比
void timer0_init(void)
{
TMOD |= 0x01; // 16位自动重装载模式
count = 12; // 计数值为12
period = 20000; // PWM波周期为1/50000秒
high_time = period / 2; // PWM波高电平时间为半个周期
duty = 50; // 占空比初始值为50%
TH0 = (65536 - count) / 256; // 设置定时器初值
TL0 = (65536 - count) % 256;
ET0 = 1; // 允许定时器0中断
EA = 1; // 允许总中断
TR0 = 1; // 启动定时器0
}
void key_init(void)
{
P1 = 0xff; // 上拉输入
EX1 = 1; // 允许INT1中断
IT1 = 1; // 下降沿触发
EX0 = 1; // 允许INT0中断
IT0 = 1; // 下降沿触发
}
void increase_duty(void)
{
if (duty < 100) {
duty += 5;
high_time = period * duty / 100;
}
}
void decrease_duty(void)
{
if (duty > 0) {
duty -= 5;
high_time = period * duty / 100;
}
}
void main(void)
{
timer0_init();
key_init();
while (1);
}
void timer0_isr(void) interrupt 1
{
TH0 = (65536 - count) / 256; // 重置定时器初值
TL0 = (65536 - count) % 256;
if (high_time == 0) {
P2 = 0x00; // 输出低电平
} else if (high_time == period) {
P2 = 0xff; // 输出高电平
} else if (high_time == count * 4) {
P2 = ~P2; // 输出方波
}
high_time--;
}
void key_isr(void) interrupt 0
{
if (!S1) {
increase_duty();
}
}
void key2_isr(void) interrupt 2
{
if (!S2) {
decrease_duty();
}
}
原文地址: https://www.cveoy.top/t/topic/obLn 著作权归作者所有。请勿转载和采集!