#include < reg52.h >
sbit PWMOUT = P1 ^ 7; //方波输出通道
sbit KEY1 = P3 ^ 0;
sbit KEY2 = P3 ^ 1;
sbit KEY3 = P3 ^ 2;
unsigned char HighRH = 0; //高电平重载值的高字节
unsigned char HighRL = 0; //高电平重载值的低字节
unsigned char LowRH = 0; //低电平重载值的高字节
unsigned char LowRL = 0; //低电平重载值的低字节
unsigned char KeySta[4] = { //按键的当前状态
1, 1, 1, 1
};
void ConfigPWM(unsigned int fr, unsigned char dc); //启动PWM,fr是频率,dc为占空比
void ClosePWM(); //关闭方波输出
void KeyScan(); //按键扫描函数,需在定时中断中调用
void KeyDriver(); //按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用
void main() {
unsigned int i;
EA = 1; //开总中断
while (1) {
//ConfigPWM(100, 5); //频率100Hz,占空比10%
for (i = 0; i < 40000; i++); //不断发送ConfigPWM中的方波
//ClosePWM();
KeyScan();
KeyDriver();
}
}
/* 配置并启动PWM,fr-频率,dc-占空比 */
void ConfigPWM(unsigned int fr, unsigned char dc) {
unsigned int high, low;
unsigned long tmp;
tmp = (11059200 / 12) / fr; //计算一个周期所需的计数值
high = (tmp * dc) / 100; //计算高电平所需的计数值
low = tmp - high; //计算低电平所需的计数值
high = 65536 - high + 12; //计算高电平的重载值并补偿中断延时
low = 65536 - low + 12; //计算低电平的重载值并补偿中断延时
HighRH = (unsigned char)(high >> 8); //高电平重载值拆分为高低字节
HighRL = (unsigned char) high;
LowRH = (unsigned char)(low >> 8); //低电平重载值拆分为高低字节
LowRL = (unsigned char) low;
TMOD &= 0xF0; //清零T0 的控制位
TMOD |= 0x01; //配置T0 为模式1
TH0 = HighRH; //加载T0 重载值
TL0 = HighRL;
ET0 = 1; //使能T0 中断
TR0 = 1; //启动T0
PWMOUT = 1; //输出高电平
}
/* 关闭PWM */
void ClosePWM() {
TR0 = 0; //停止定时器
ET0 = 0; //禁止中断
PWMOUT = 0; //输出低电平
}
/* 按键扫描函数,需在定时中断中调用 */
void KeyScan() {
unsigned char i;
static unsigned char keybuf[4] = { //按键扫描缓冲区
0xFF, 0xFF, 0xFF, 0xFF
};
//按键值移入缓冲区
keybuf[0] = (keybuf[0] << 1) | KEY1; //按键按下的时候,KEY会变成0XFF,使得keybuf = 0x00
keybuf[1] = (keybuf[1] << 1) | KEY2;
keybuf[2] = (keybuf[2] << 1) | KEY3;
//消抖后更新按键状态
for (i = 0; i < 3; i++) {
if (keybuf[i] == 0x00) { //连续8 次扫描值为0,即16ms 内都是按下状态时,可认为按键已稳定的按下
KeySta[i] = 0;
} else if (keybuf[i] == 0xFF) { //连续8 次扫描值为1,即16ms 内都是弹起状态时,可认为按键已稳定的弹起
KeySta[i] = 1;
}
}
}
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver() {
unsigned char i;
static unsigned char backup[4] = {
1, 1, 1, 1
}; //备份按键扫描
for (i = 0; i < 4; i++) //循环检测4 个按键
{
if (backup[i] != KeySta[i]) //检测按键动作
{ //如果不一样,代表该按键已经被按下
if (backup[i] != 0) //按键按下时执行动作
{
if (i == 0) //按键为0,旋转-90
{
ConfigPWM(50, 3); //频率50Hz,20ms,占空比10%
for (i = 0; i < 40000; i++);
ClosePWM();
} else if (i == 1) //按键为1,旋转0
{
ConfigPWM(50, 8); //频率50Hz,20ms,占空比3%
for (i = 0; i < 40000; i++);
ClosePWM();
} else if (i == 2) //按键为0,旋转90
{
ConfigPWM(50, 13); //频率50Hz,20ms,占空比8%
for (i = 0; i < 40000; i++);
ClosePWM();
}
}
backup[i] = KeySta[i]; //刷新前一次的备份值
}
}
}
/* T0 中断服务函数,产生PWM 输出 */
void InterruptTimer0() interrupt 1 {
//如果一开始是高,那么中断到了之后输出低即可完成PWM
if (PWMOUT == 1) //当前输出为高电平时,装载低电平值并输出低电平
{
TH0 = LowRH;
TL0 = LowRL;
PWMOUT = 0;
}
//如果一开始是低,那么中断到了之后输出高即可开始产生PWM
else //当前输出为低电平时,装载高电平值并输出高电平
{
TH0 = HighRH;
TL0 = HighRL;
PWMOUT = 1;
}
}
|