您现在所在的是:

单片机论坛

回帖:7个,阅读:904 [上一页] [1] [下一页]
50
645504699
文章数:3
年度积分:50
历史总积分:50
注册时间:2020/5/10
发站内信
发表于:2020/5/10 17:15:51
#0楼
各位大神帮我看看程序哪里出了问题,想用状态机搞一个PWM的电机调速,并且用一个按键设置做两种功能,1S内短按则打开或者关闭电机,长按PWM调速,1~6S内PWM是一直加速,6~11S是减速,大于11秒则PWM为0
#include <reg52.h>

#define Key_State_0   0 //定义按键动作时的状态0
#define Key_State_1   1 //定义按键动作时的状态1
#define Key_State_2   2 //定义按键动作时的状态2
#define Key_State_3   3 //定义按键动作时的状态3
#define Key_State_4   4 //定义按键动作时的状态4

sbit Key_Input=P1^0;
sbit PWM=P2^0;

char Read_Key();
void Init_Timer0(void);
void Key_Scan();

static unsigned char Pwm_Count=0;  //定义PWM进入中断的次数
static unsigned char Pwm_Vlaue=0; //定义PWM占空比的值
char Key_Return;

/*----------------------------------------------
              主函数
------------------------------------------------*/

void main()
{
Init_Timer0();  //初始化定时器0
while(1)
{
Key_Scan();
}
}

/*------------------------------------------------
             定时器初始化函数
------------------------------------------------*/

void Init_Timer0(void)
{
TMOD |= 0x01;  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响    
TH0=0xff;      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
TL0=0xa4;
EA=1;            //总中断打开
ET0=1;           //定时器中断打开
TR0=1;           //定时器开关打开
}

/*------------------------------------------------
             定时器中断函数
------------------------------------------------*/
void PWM_Timer0() interrupt 1 using 1
{

TH0=0xff;  //重新赋值
TL0=0xa4;
Pwm_Count++;  //PWM进入中断的次数自加1
if(Pwm_Count==100) //如果PWM进入中断的次数=100
{
Pwm_Count=0; //次数归0
Read_Key();   //按键函数10ms扫描一次
}
if(Pwm_Count<Pwm_Vlaue)   //改变Pwm_Vlaue可以改变占空比的值
{
PWM=1; //电机打开
}
else
{
PWM=0; //电机关闭
}
}

/*------------------------------------------------
             读按键状态函数
------------------------------------------------*/

char Read_Key()  //按键状态处理函数
{
static char Key_State=0,Key_Time=0;  //按键状态值Key_State初始化为0,按键按下的时间Key_Time初始化为0
unsigned char Key_Press;  //Key_Press为按键状态储存值,Key_Return为按键的状态返回值

Key_Press=Key_Input; //读按键I/O口的电平
switch(Key_State)
{

case 0:   //按键的初始状态0
if(Key_Press!=1)    //按键按下
{
Key_State=Key_State_1;  //状态切换到确认态1
Key_Return=1; //按键的状态返回值输出“1”  
}
break;
case 1:  //按键的确认状态1
if(Key_Press!=1)  //按键仍然按下
{
Key_State=Key_State_2; //状态切换到计时状态2
Key_Time=0; //按键时间计数器清0
}
else   //按键已经松开
{
Key_State=Key_State_0; //状态切换到初始状态0

}
break;

case 2:  //按键的计时状态2
if(Key_Press) //按键已经松开  --短按
{
Key_State=Key_State_0; //状态切换到初始状态0
Key_Return=1; //按键的状态返回值输出“1”
}
else if(Key_Time>=100) //按键按下的时间计数  --长按
{
Key_State=Key_State_3;  //按键按下的时间大于1S,状态切换到计时状态3
Key_Time=0;  //按键时间计数器清0
Key_Return=2;  //按键的状态返回值输出“2”

}
break;

case 3:  //按键的计时状态3
if(Key_Press) //按键已经松开
{
Key_State=Key_State_0; //状态切换到初始状态0
}
else
{
Key_Time++;
if(Key_Time>=0&&Key_Time<500) //按键按下的时间计数
{
Key_State=Key_State_4;  //按键按下的时间大于6S,状态切换到计时状态4
Key_Time=0;
Key_Return=3;  //按键的状态返回值输出“3”
}
}
break;
case 4:  //按键的计时状态3
if(Key_Press) //按键已经松开
{
Key_State=Key_State_0; //状态切换到初始状态0
}
else
{
Key_Time++;
if(++Key_Time>=100&&++Key_Time<500) //按键按下的时间计数
{
Key_State=Key_State_4;  //按键按下的时间大于6S,状态切换到计时状态4
Key_Time=0;
Key_Return=4;   //按键的状态返回值输出“4”
}
}
break;
default:Key_Time=0; break;

}
return Key_Return;
}

void Key_Scan()
{
switch(Key_Return)
{
case 0:break;
case 1:PWM=~PWM;break;
case 2:break;
case 3:Pwm_Vlaue++;break; //PWM占空比自减
case 4:Pwm_Vlaue--;break; //PWM占空比自减
default:break;
}
}


[此贴子已经被作者于2020/5/10 20:06:06编辑过]
1分悬赏
27950
guanyumou 版主
文章数:10552
年度积分:1133
历史总积分:27950
注册时间:2008/7/13
发站内信
2018论坛优秀版主
2018春节活动(三)
2017论坛优秀版主
2017国庆活动(二)
2017春节活动(三)
发表于:2020/5/11 11:52:57
#1楼
还不如直接把程序工程文件发出来,这样发出来可读性不好,很少有人有耐心仔细去看。
基于各种组态软件\触摸屏\PLC\单片机\变频器Modbus TCP\RTU\ASCII通信编程服务,需要请直接
联系!腾讯扣扣149034219
37237
cvlsam 版主
文章数:12401
年度积分:1589
历史总积分:37237
注册时间:2001/12/22
发站内信
2018论坛贡献奖
2017论坛贡献奖
2016论坛贡献奖
2015论坛贡献奖
2013论坛贡献奖
2012论坛贡献奖
2011论坛贡献奖
2011国庆活动
2010论坛杰出贡献奖
发表于:2020/5/11 13:49:09
#2楼
if(Pwm_Count==100) //如果PWM进入中断的次数=100
{
Pwm_Count=0; //次数归0
Read_Key();   //按键函数10ms扫描一次
}

1秒钟检测一次按键输入状态?

Good Luck~
50
645504699
文章数:3
年度积分:50
历史总积分:50
注册时间:2020/5/10
发站内信
发表于:2020/5/11 18:05:03
#3楼
回复 #2楼 cvlsam
10ms检测一次
37237
cvlsam 版主
文章数:12401
年度积分:1589
历史总积分:37237
注册时间:2001/12/22
发站内信
2018论坛贡献奖
2017论坛贡献奖
2016论坛贡献奖
2015论坛贡献奖
2013论坛贡献奖
2012论坛贡献奖
2011论坛贡献奖
2011国庆活动
2010论坛杰出贡献奖
发表于:2020/5/12 5:42:10
#4楼
以下是引用6455046992020/5/11 18:05:03的发言:
10ms检测一次
显然,if逻辑中的按钮输入处理需要一秒钟才能被执行一次。
50
645504699
文章数:3
年度积分:50
历史总积分:50
注册时间:2020/5/10
发站内信
发表于:2020/5/12 17:51:34
#5楼
回复 #4楼 cvlsam
额,我的时钟是100us中断一次的,100次就是10ms
788
微鑫科技
文章数:1232
年度积分:788
历史总积分:788
注册时间:2019/11/26
发站内信
发表于:2020/7/1 20:05:30
#6楼
这个应该在定时器中断里去计时判断,在主程序里执行,这样比较准确。
遇到SB,请不要和他争辩,认同他所有的观点,让他变成一个大SB。
788
微鑫科技
文章数:1232
年度积分:788
历史总积分:788
注册时间:2019/11/26
发站内信
发表于:2020/7/1 20:07:22
#7楼
话说,你的按键就这么紧张吗?如果实在是太紧张的话,可以用一个模拟量口,用电阻分压的方式去检测哪个按键,这样可以一个端口做出很多个按键出来,没有必要一个按键搞那么多的功能出来,使用者要疯掉。
遇到SB,请不要和他争辩,认同他所有的观点,让他变成一个大SB。

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

78.0005