chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32按鍵消抖——入門(mén)狀態(tài)機(jī)思維

碼農(nóng)愛(ài)學(xué)習(xí) ? 來(lái)源:碼農(nóng)愛(ài)學(xué)習(xí) ? 作者:碼農(nóng)愛(ài)學(xué)習(xí) ? 2022-09-02 21:54 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

嵌入式軟件開(kāi)發(fā)中,狀態(tài)機(jī)編程是一個(gè)十分重要的編程思想,它也是嵌入式開(kāi)發(fā)中一個(gè)常用的編程框架。掌握了狀態(tài)機(jī)編程思想,可以更加邏輯清晰的實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯功能。

1 狀態(tài)機(jī)思想

狀態(tài)機(jī),或稱有限狀態(tài)機(jī)FSM(Finite State Machine),是一種重要的編程思想。

狀態(tài)機(jī)有3要素:狀態(tài)事件響應(yīng)

狀態(tài):系統(tǒng)處在什么狀態(tài)?

事件:發(fā)生了什么事?

響應(yīng):此狀態(tài)下發(fā)生了這樣的事,系統(tǒng)要如何處理?

狀態(tài)機(jī)編程前,首先要根據(jù)需要實(shí)現(xiàn)的功能,整理出一個(gè)對(duì)應(yīng)的狀態(tài)轉(zhuǎn)換圖(狀態(tài)機(jī)圖),然后就可以根據(jù)這個(gè)狀態(tài)轉(zhuǎn)換圖,套用狀態(tài)機(jī)編程模板,實(shí)現(xiàn)對(duì)應(yīng)是狀態(tài)機(jī)代碼了。

狀態(tài)機(jī)編程主要有 3 種方法:switch-case 法、表格驅(qū)動(dòng)法函數(shù)指針?lè)?/strong>,本篇先介紹最簡(jiǎn)單也最易理解的switch-case 法。

2 狀態(tài)機(jī)實(shí)例

下面以按鍵消抖功能,來(lái)介紹switch-case 法的狀態(tài)機(jī)編程思路。

2.1 按鈕消抖狀態(tài)轉(zhuǎn)換圖

狀態(tài)機(jī)機(jī)編程前,首先要明確的對(duì)應(yīng)功能的狀態(tài)機(jī)需要幾個(gè)狀態(tài),本例的按鍵功能,只檢測(cè)最基礎(chǔ)的按下與松開(kāi)狀態(tài)(暫不實(shí)現(xiàn)長(zhǎng)按、雙擊等狀態(tài)),并增加對(duì)應(yīng)的按鈕去抖功能,因此,需要用到4個(gè)狀態(tài):

穩(wěn)定松開(kāi)狀態(tài)

按下抖動(dòng)狀態(tài)

穩(wěn)定按下?tīng)顟B(tài)

松開(kāi)抖動(dòng)狀態(tài)

對(duì)應(yīng)的狀態(tài)轉(zhuǎn)換圖如下:

poYBAGMSCi2AVy31AAA8AKcyDe0236.png

由于按鍵通常處于松開(kāi)狀態(tài),這里讓狀態(tài)機(jī)的初始化狀態(tài)為松開(kāi)狀態(tài),然后在這4個(gè)狀態(tài)中來(lái)回切換。

圖中的VT代表按鍵檢測(cè)到電平,VT=0即檢測(cè)到低電平,可能是按鍵按下,由初始的“穩(wěn)定松開(kāi)”狀態(tài)轉(zhuǎn)為“按下抖動(dòng)”狀態(tài)

當(dāng)持續(xù)檢測(cè)到低電平(VT=0)一段時(shí)間后,認(rèn)為消抖完成,由“按下抖動(dòng)”狀態(tài)轉(zhuǎn)為“穩(wěn)定按下”狀態(tài)

在“按下抖動(dòng)”狀態(tài)時(shí),在指定的一段時(shí)間內(nèi),再次檢測(cè)到高電平(VT=1),說(shuō)明確實(shí)是按鈕抖動(dòng)(比如按鍵被快速撥動(dòng)了一下又彈起,或強(qiáng)烈震動(dòng)導(dǎo)致的按鍵抖動(dòng)),則由“按下抖動(dòng)”狀態(tài)轉(zhuǎn)為“穩(wěn)定松開(kāi)”狀態(tài)

2.2 編程實(shí)現(xiàn)

2.2.1 狀態(tài)定義

對(duì)應(yīng)上面的按鈕狀態(tài)圖,可以知道需要用到4個(gè)狀態(tài):

穩(wěn)定松開(kāi)狀態(tài)(KS_RELEASE)

按下抖動(dòng)狀態(tài)(KS_PRESS_SHAKE)

穩(wěn)定按下?tīng)顟B(tài)(KS_PRESS)

松開(kāi)抖動(dòng)狀態(tài)(KS_RELEASE_SHAKE)

這里使用枚舉來(lái)定義這4個(gè)狀態(tài)。為了在調(diào)試時(shí),能夠把對(duì)應(yīng)狀態(tài)名稱以字符串的形式打印出來(lái),這里使用宏定義的一個(gè)小技巧:

#符號(hào)+自定義的枚舉名稱

即可自動(dòng)轉(zhuǎn)變?yōu)樽址问?,再將這些字符串放到const char* key_status_name[]數(shù)組中,便可通過(guò)數(shù)組的形式訪問(wèn)這些狀態(tài)的字符串名稱形式。

此外,為了不重復(fù)書(shū)寫(xiě)枚舉名稱與對(duì)應(yīng)的枚舉字符串(#+枚舉名稱),進(jìn)一步使用宏定義的方式,只定義一次狀態(tài),然后通過(guò)下面兩條宏定義,實(shí)現(xiàn)對(duì)枚舉項(xiàng)枚舉項(xiàng)對(duì)應(yīng)的字符串的分別獲?。?/p>

#define ENUM_ITEM(ITEM) ITEM,

#define ENUM_STRING(ITEM) #ITEM,

具體是宏定義、枚舉定義與枚舉名稱數(shù)組聲明如下:

#define ENUM_ITEM(ITEM) ITEM,
#define ENUM_STRING(ITEM) #ITEM,

#define KEY_STATUS_ENUM(STATUS)                   \
	STATUS(KS_RELEASE)       /*穩(wěn)定松開(kāi)狀態(tài)*/       \
	STATUS(KS_PRESS_SHAKE)   /*按下抖動(dòng)狀態(tài)*/       \
	STATUS(KS_PRESS)         /*穩(wěn)定按下?tīng)顟B(tài)*/       \
	STATUS(KS_RELEASE_SHAKE) /*松開(kāi)抖動(dòng)狀態(tài)*/       \
	STATUS(KS_NUM)           /*狀態(tài)總數(shù)(無(wú)效狀態(tài))*/  \
	
typedef enum
{
	KEY_STATUS_ENUM(ENUM_ITEM)
}KEY_STATUS;

const char* key_status_name[] = {
	KEY_STATUS_ENUM(ENUM_STRING)
};

宏定義不便理解的,可以將宏定義分別帶入,轉(zhuǎn)為最終的結(jié)果,理解替代后的具體形式,比如下面的宏定義帶入替換示意:

/*
KEY_STATUS_ENUM(STATUS) --> STATUS(KS_RELEASE) ... STATUS(KS_NUM)

KEY_STATUS_ENUM(ENUM_ITEM)
--> ENUM_ITEM(KS_RELEASE) ... ENUM_ITEM(KS_NUM)
--> KS_RELEASE, ... KS_NUM,

KEY_STATUS_ENUM(ENUM_STRING)
--> ENUM_STRING(KS_RELEASE) ... ENUM_STRING(KS_NUM)
--> #KS_RELEASE, ... #KS_NUM,
*/

2.2.2 狀態(tài)機(jī)實(shí)現(xiàn)

下面是狀態(tài)機(jī)的具體實(shí)現(xiàn):

狀態(tài)機(jī)函數(shù)key_status_check在一個(gè)循環(huán)中,被每隔10ms調(diào)用一次

定義一個(gè)g_keyStatus表示狀態(tài)機(jī)所處的狀態(tài)

在每個(gè)循環(huán)中,switch根據(jù)當(dāng)前的狀態(tài),執(zhí)行對(duì)應(yīng)狀態(tài)所需要執(zhí)行的邏輯

定義一個(gè)g_DebounceCnt用于消抖時(shí)間計(jì)算,當(dāng)持續(xù)進(jìn)入消抖狀態(tài),每次循環(huán)(10ms)中將此值加1,持續(xù)一定次數(shù)(5次,即50ms),認(rèn)為是穩(wěn)定的按下或松開(kāi),消抖完成,跳轉(zhuǎn)到穩(wěn)定方向或穩(wěn)定松開(kāi)狀態(tài)

在每個(gè)狀態(tài)的執(zhí)行邏輯中,當(dāng)檢測(cè)到某些條件滿足時(shí),跳轉(zhuǎn)到其它的狀態(tài)

通過(guò)狀態(tài)的不斷跳轉(zhuǎn),實(shí)現(xiàn)狀態(tài)機(jī)的運(yùn)行

此外,為方便觀察狀態(tài)機(jī)中狀態(tài)的變化,定義了一個(gè)g_lastKeyStatus表示前一狀態(tài),當(dāng)狀態(tài)發(fā)生變化時(shí),可以將狀態(tài)名稱打印出來(lái)

KEY_STATUS g_keyStatus = KS_RELEASE; //當(dāng)前按鍵的狀態(tài)
KEY_STATUS g_lastKeyStatus = KS_NUM; //上一狀態(tài)
int g_DebounceCnt = 0; //消抖時(shí)間計(jì)數(shù)

void key_status_check()
{
	switch(g_keyStatus)
	{
		//按鍵釋放(初始狀態(tài))
		case KS_RELEASE:
		{
			//檢測(cè)到低電平,先進(jìn)行消抖
			if (KEY0 == 0)
			{
				g_keyStatus = KS_PRESS_SHAKE;
				g_DebounceCnt = 0;
			}
		}
		break;
		
		//按下抖動(dòng)
		case KS_PRESS_SHAKE:
		{
			g_DebounceCnt++;
			
			//確實(shí)是抖動(dòng)
			if (KEY0 == 1)
			{
				g_keyStatus = KS_RELEASE;
			}
			//消抖完成
			else if (g_DebounceCnt == 5)
			{
				g_keyStatus = KS_PRESS;
				printf("=====> key press\r\n");
			}
		}
		break;
		
		//穩(wěn)定按下
		case KS_PRESS:
		{
			//檢測(cè)到高電平,先進(jìn)行消抖
			if (KEY0 == 1)
			{
				g_keyStatus = KS_RELEASE_SHAKE;
				g_DebounceCnt = 0;
			}
		}
		break;
		
		//松開(kāi)抖動(dòng)
		case KS_RELEASE_SHAKE:
		{
			g_DebounceCnt++;
			
			//確實(shí)是抖動(dòng)
			if (KEY0 == 0)
			{
				g_keyStatus = KS_PRESS;
			}
			//消抖完成
			else if (g_DebounceCnt == 5)
			{
				g_keyStatus = KS_RELEASE;
				printf("=====> key release\r\n");
			}
		}
		break;
		
		default:break;
	}
	
	if (g_keyStatus != g_lastKeyStatus)
	{
		g_lastKeyStatus = g_keyStatus;
		printf("new key status:%d(%s)\r\n", g_keyStatus, key_status_name[g_keyStatus]);
	}
}

int main(void)
{	
	delay_init();	    //延時(shí)函數(shù)初始化	  
	KEY_Init();
	uart_init(115200);
	printf("hello\r\n");
	
	while(1)
	{
		key_status_check();
		delay_ms(10);
	}
}

注:本例程需要使用一個(gè)按鍵,需要初始化對(duì)應(yīng)的GPIO,這里不再貼代碼。

2.3 使用測(cè)試

將完整的代碼編譯后燒錄到板子中,連接串口,按下與松開(kāi)按鍵,觀察串口輸出信息。

我的測(cè)試輸出信息如下:

pYYBAGMSCpeADWb3AACpThu0Gj0100.png

前兩次撥動(dòng)按鍵模擬按鈕抖動(dòng)的情況,可以看到串口打印出兩次從松開(kāi)到按下抖動(dòng)的狀態(tài)切換。

然后是按下按鍵,再松開(kāi)按鍵,可以看到狀態(tài)的變化:松開(kāi) -> 按下抖動(dòng) -> 按下 -> 松開(kāi)抖動(dòng) -> 松開(kāi)

3 總結(jié)

本篇介紹了嵌入式軟件開(kāi)發(fā)中常用的狀態(tài)機(jī)編程實(shí)現(xiàn),并通過(guò)按鍵消抖實(shí)例,以常用的switch-case形式,實(shí)現(xiàn)了對(duì)應(yīng)的狀態(tài)機(jī)編程代碼實(shí)現(xiàn),并通過(guò)測(cè)試,串口打印對(duì)應(yīng)狀態(tài),分析狀態(tài)機(jī)的狀態(tài)跳轉(zhuǎn)過(guò)程。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6067

    文章

    44991

    瀏覽量

    650435
  • 嵌入式
    +關(guān)注

    關(guān)注

    5152

    文章

    19673

    瀏覽量

    317536
  • STM32
    +關(guān)注

    關(guān)注

    2293

    文章

    11032

    瀏覽量

    364906
  • 狀態(tài)機(jī)
    +關(guān)注

    關(guān)注

    2

    文章

    493

    瀏覽量

    28240
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    STM32按鍵狀態(tài)機(jī)2——狀態(tài)簡(jiǎn)化與增加長(zhǎng)按功能

    本篇繼續(xù)介紹狀態(tài)機(jī)的使用,在上篇的基礎(chǔ)上,通過(guò)簡(jiǎn)化按鍵邏輯,并增加按鍵長(zhǎng)按功能,進(jìn)一步介紹狀態(tài)圖的修改與
    的頭像 發(fā)表于 09-03 21:26 ?4690次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>按鍵</b><b class='flag-5'>狀態(tài)機(jī)</b>2——<b class='flag-5'>狀態(tài)</b>簡(jiǎn)化與增加長(zhǎng)按功能

    【連載視頻教程(八)】小梅哥FPGA設(shè)計(jì)思想與驗(yàn)證方法視頻教程之基于狀態(tài)機(jī)的獨(dú)立按鍵

    ,主要通過(guò)獨(dú)立按鍵這樣一個(gè)實(shí)驗(yàn),來(lái)進(jìn)一步舉例講解狀態(tài)機(jī)的設(shè)計(jì)思想,獨(dú)立按鍵
    發(fā)表于 09-29 14:19

    利用狀態(tài)機(jī)按鍵程序

    與過(guò)程分離. 把和按鍵狀態(tài)相關(guān)的東西統(tǒng)統(tǒng)塞到結(jié)構(gòu)里, 把的代碼放在一個(gè)函數(shù)中.//key.h 頭文件
    發(fā)表于 02-18 19:58

    怎樣去設(shè)計(jì)一個(gè)基于stm32標(biāo)準(zhǔn)庫(kù)獨(dú)立按鍵的多按鍵狀態(tài)機(jī)

    寫(xiě)在前面??一般引用都寫(xiě)在最后,但是這篇博文對(duì)我這個(gè)狀態(tài)機(jī)的影響很大,我這里有許多借鑒他的思維。所以寫(xiě)在前面,如有侵權(quán)立即刪除簡(jiǎn)單按鍵檢測(cè)??一開(kāi)始學(xué)習(xí)單片機(jī)的時(shí)候我接觸到
    發(fā)表于 12-09 07:48

    STM32單片機(jī)按鍵和FPGA按鍵的相關(guān)資料分享

    寫(xiě)在前面:STM32單片機(jī)按鍵和FPGA按鍵
    發(fā)表于 01-18 06:39

    請(qǐng)問(wèn)按鍵狀態(tài)機(jī)的長(zhǎng)按和短按測(cè)試該怎樣去實(shí)現(xiàn)呢

    什么是按鍵呢?按鍵狀態(tài)機(jī)的長(zhǎng)按和短按測(cè)試該怎樣去實(shí)現(xiàn)呢?
    發(fā)表于 01-20 06:45

    如何用狀態(tài)機(jī)法實(shí)現(xiàn)單片機(jī)矩陣鍵盤(pán)的控制

    看了藍(lán)橋杯單片機(jī)的培訓(xùn)視頻,發(fā)現(xiàn)用狀態(tài)機(jī)法實(shí)現(xiàn)矩陣鍵盤(pán)時(shí)左邊兩列沒(méi)有用,這是因?yàn)镻36、P37口實(shí)際是P42、P44口,所以我們?cè)谟眯辛袙呙璺〞r(shí)會(huì)出錯(cuò)。但習(xí)慣了
    發(fā)表于 02-17 07:47

    基于FPGA的按鍵電路設(shè)計(jì)

    采用了VHDL語(yǔ)言編程的設(shè)計(jì)方法,通過(guò)FPGA來(lái)實(shí)現(xiàn)按鍵的硬件電路。論述了基于計(jì)數(shù)器、RS觸發(fā)器和狀態(tài)機(jī)3種方法來(lái)實(shí)現(xiàn)按鍵
    發(fā)表于 12-05 14:13 ?224次下載

    利用狀態(tài)機(jī)按鍵程序

    利用狀態(tài)機(jī)按鍵程序講解,很好的資料下載吧。
    發(fā)表于 01-11 09:32 ?30次下載

    VHDL—按鍵

    達(dá)到去抖動(dòng)的目的。本例中用狀態(tài)機(jī)實(shí)現(xiàn)了電路:端口描述:clk 輸入檢測(cè)時(shí)鐘;reset 復(fù)位信號(hào);din 原始按鍵信號(hào)輸入; dout 去抖動(dòng)輸出信號(hào)。
    發(fā)表于 11-11 17:17 ?2次下載

    使用狀態(tài)機(jī)按鍵處理方法電子鐘程序免費(fèi)下載

    之前的電子鐘程序中,用的按鍵處理方法是10ms的延時(shí),這種方法效率比較低所以現(xiàn)在利用狀態(tài)機(jī)原理重寫(xiě)一下,效率很高啊 4個(gè)獨(dú)立按鍵中用到
    發(fā)表于 07-09 17:41 ?8次下載
    使用<b class='flag-5'>狀態(tài)機(jī)</b>的<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>處理方法電子鐘程序免費(fèi)下載

    使用51單片機(jī)實(shí)現(xiàn)按鍵的資料和程序免費(fèi)下載

    抖動(dòng)是機(jī)械按鍵存在的現(xiàn)象,是必須要進(jìn)行處理的。一般處理有兩種方式:一種是硬件,另一種是軟件。硬件
    發(fā)表于 07-05 17:41 ?5次下載
    使用51單片<b class='flag-5'>機(jī)</b>實(shí)現(xiàn)<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的資料和程序免費(fèi)下載

    基于stm32標(biāo)準(zhǔn)庫(kù)獨(dú)立按鍵的多按鍵狀態(tài)機(jī)的實(shí)現(xiàn)

    寫(xiě)在前面??一般引用都寫(xiě)在最后,但是這篇博文對(duì)我這個(gè)狀態(tài)機(jī)的影響很大,我這里有許多借鑒他的思維。所以寫(xiě)在前面,如有侵權(quán)立即刪除簡(jiǎn)單按鍵檢測(cè)??一開(kāi)始學(xué)習(xí)單片機(jī)的時(shí)候我接觸到
    發(fā)表于 11-26 13:36 ?50次下載
    基于<b class='flag-5'>stm32</b>標(biāo)準(zhǔn)庫(kù)獨(dú)立<b class='flag-5'>按鍵</b>的多<b class='flag-5'>按鍵</b><b class='flag-5'>狀態(tài)機(jī)</b>的實(shí)現(xiàn)

    基于STM32按鍵的防和松開(kāi)處理:狀態(tài)機(jī)

    用延時(shí)和while();去處理按鍵很浪費(fèi)資源,這里我們用定時(shí)器來(lái)做一個(gè)按鍵的處理-狀態(tài)機(jī);typedef enum {KEY_RELEASED,KEY_PRESSED,KEY_PROCESSED
    發(fā)表于 12-09 09:21 ?8次下載
    基于<b class='flag-5'>STM32</b><b class='flag-5'>按鍵</b>的防<b class='flag-5'>抖</b>和松開(kāi)處理:<b class='flag-5'>狀態(tài)機(jī)</b>

    狀態(tài)機(jī)法實(shí)現(xiàn)藍(lán)橋杯單片機(jī)矩陣鍵盤(pán)的控制

    看了藍(lán)橋杯單片機(jī)的培訓(xùn)視頻,發(fā)現(xiàn)用狀態(tài)機(jī)法實(shí)現(xiàn)矩陣鍵盤(pán)時(shí)左邊兩列沒(méi)有用,這是因?yàn)镻36、P37口實(shí)際是P42、P44口,所以我們?cè)谟眯辛袙呙璺〞r(shí)會(huì)出錯(cuò)。但習(xí)慣了
    發(fā)表于 12-20 19:42 ?6次下載
    用<b class='flag-5'>狀態(tài)機(jī)</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>法實(shí)現(xiàn)藍(lán)橋杯單片<b class='flag-5'>機(jī)</b>矩陣鍵盤(pán)的控制