#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 == 0x00)
{ //连续8 次扫描值为0,即16ms 内都是按下状态时,可认为按键已稳定的按下
KeySta = 0;
}
else if (keybuf == 0xFF)
{ //连续8 次扫描值为1,即16ms 内都是弹起状态时,可认为按键已稳定的弹起
KeySta = 1;
}
}
}
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
{
unsigned char i;
static unsigned char backup[4] = {1,1,1,1};//备份按键扫描
for (i=0; i<4; i++) //循环检测4 个按键
{
if (backup != KeySta) //检测按键动作
{ //如果不一样,代表该按键已经被按下
if (backup != 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 = KeySta; //刷新前一次的备份值
}
}
}
/* T0 中断服务函数,产生PWM 输出 */
void InterruptTimer0() interrupt 1
{
//如果一开始是高,那么中断到了之后输出低即可完成PWM
if (PWMOUT == 1) //当前输出为高电平时,装载低电平值并输出低电平
{
TH0 = LowRH;
TL0 = LowRL;
PWMOUT = 0;
}
//如果一开始是低,那么中断到了之后输出高即可开始产生PWM
else //当前输出为低电平时,装载高电平值并输出高电平
{
TH0 = HighRH;
TL0 = HighRL;
PWMOUT = 1;
}
}
|