AT89C51通过定时器输出两路PWM波,并能通过4*4的矩阵按键调制两路的频率和占空比,给出C51代码
时间: 2024-02-26 10:52:36 浏览: 39
好的,下面是AT89C51通过定时器输出两路PWM波,并能通过4*4的矩阵按键调制两路的频率和占空比的C51代码:
```c
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 矩阵按键扫描函数
uchar keyscan()
{
uchar row, col;
uchar code keymap[16] = {0xee, 0xde, 0xbe, 0x7e, 0xed, 0xdd, 0xbd, 0x7d, 0xeb, 0xdb, 0xbb, 0x7b, 0xe7, 0xd7, 0xb7, 0x77};
P2 = 0x0f; // 将 P2 的低 4 位置 0
if (P2 != 0x0f) // 如果有按键按下
{
for (col = 0; col < 4; col++)
{
P2 = 0x0f;
P2 &= ~(0x01 << col); // 将第 col 列置 0
for (row = 0; row < 4; row++)
{
if ((P2 & (0x10 << row)) == 0) // 如果第 row 行为 0
{
return keymap[row * 4 + col]; // 返回按键编码
}
}
}
}
return 0xff; // 没有按键按下,返回 0xff
}
void timer0_init()
{
TMOD &= 0xf0; // 设置定时器 0 为模式 1
TMOD |= 0x01;
TH0 = 0xff; // 定时器初值
TL0 = 0x00;
ET0 = 1; // 打开定时器 0 中断
TR0 = 1; // 启动定时器 0
EA = 1; // 打开总中断开关
}
void main()
{
uchar key, freq1, freq2, duty1, duty2;
uint T1, T2;
timer0_init(); // 初始化定时器 0
while (1)
{
key = keyscan(); // 扫描矩阵按键
if (key != 0xff) // 如果有按键按下
{
freq1 = key >> 4; // 频率1为按键编码的高四位
freq2 = key & 0x0f; // 频率2为按键编码的低四位
T1 = 65536 - (11059200 / 12 / (freq1 * 50)); // 根据频率计算计数器初值
T2 = 65536 - (11059200 / 12 / (freq2 * 50));
TH0 = T1 >> 8; // 将计数器初值分别写入 TH0 和 TL0
TL0 = T1 & 0xff;
duty1 = keyscan(); // 再次扫描矩阵按键,得到占空比
duty1 = duty1 & 0x0f; // 占空比为按键编码的低四位
duty1 = duty1 * 10 + 10; // 计算占空比
duty1 = (duty1 * (T1 / 256)) / 100; // 根据占空比计算高电平时间
TH1 = T2 >> 8; // 将计数器初值分别写入 TH1 和 TL1
TL1 = T2 & 0xff;
duty2 = keyscan(); // 再次扫描矩阵按键,得到占空比
duty2 = duty2 >> 4; // 占空比为按键编码的高四位
duty2 = duty2 * 10 + 10; // 计算占空比
duty2 = (duty2 * (T2 / 256)) / 100; // 根据占空比计算高电平时间
TR1 = 1; // 启动定时器 1
while (TF1 == 0); // 等待定时器 1 溢出
TR1 = 0; // 关闭定时器 1
P1_0 = 1; // 输出 PWM1
delay(duty1);
P1_0 = 0;
delay(T1 / 256 - duty1);
P1_1 = 1; // 输出 PWM2
delay(duty2);
P1_1 = 0;
delay(T2 / 256 - duty2);
}
}
}
void timer0_isr() interrupt 1
{
static uchar cnt = 0;
TH0 = 0xff; // 重新赋值
TL0 = 0x00;
cnt++;
if (cnt == 20) // 20 次定时器 0 中断为 1 秒
{
cnt = 0;
P0 = ~P0; // 每秒翻转一次 P0
}
}
```
注意:上述代码中的 `delay()` 函数需要自行实现,可用 `for` 循环实现延时。同时,定时器 1 的初始化和中断处理函数也需要自行实现。
阅读全文