本帖最后由 求學長 于 2020-5-10 20:07 編輯
想用狀態機搞一個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=50; //定義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;
}
}
|