- #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;
- }
- }
|