- /*直接復制以下代碼,實現*/
- #include "stm32f10x.h"
- #include "bitband_cm3.h"
- #include "systick.h"
- #define N_key 0 //無鍵
- #define S_key 1 //單鍵
- #define D_key 2 //雙鍵
- #define L_key 3 //長鍵
- #define KEY_AN (GPIOA->IDR & 1<<0)
- #define BEEF PCout(3)
- /**********************************************************************
- *函數名:delay_us
- *功 能:延遲1us
- *參 數:us最大2^24/9=1864135us
- *返 回:無
- *備 注:無
- **********************************************************************/
- void delay_us(u16 us)
- {
- SysTick->LOAD = us * 9; //裝載計數值
- SysTick->VAL = 0; //清空當前值
- SysTick->CTRL |= 1; //使能計數器
- while(!(SysTick->CTRL & (1 << 16)));//等待計數結束
- SysTick->CTRL &=~ 1;//關閉計數
- }
- //LED初始化
- void LED_Init(void)
- {
- #if 0
- RCC->APB2ENR |= 3<<3;//開啟PB/PC口時鐘
- GPIOB->CRL &=~(0XF<<4*1);//清PB1
- GPIOB->CRL |=(0X3<<4*1);//通用輸出 50M
- GPIOC->CRL &=~(0XF<<4*5);//清PC5
- GPIOC->CRL |=(0X3<<4*5);//通用輸出 50M
- GPIOB->ODR |=(1<<1);//默認給高電平,關燈,
- GPIOC->ODR |=(5<<1);
- // GPIOB->ODR &=~(1<<1);//點燈
- // GPIOC->ODR &=~(5<<1);
- #else
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB,ENABLE);//開啟PB/PC口時鐘.
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
- GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽
- GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//50M
- GPIO_Init(GPIOB, &GPIO_InitStruct);//PB1
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
- GPIO_Init(GPIOC, &GPIO_InitStruct);//PC5
- GPIO_SetBits(GPIOB, GPIO_Pin_1);//默認給高電平,關燈,不能少了這步,因為輸出數據寄存器默認值給低電平
- GPIO_SetBits(GPIOC, GPIO_Pin_5);
- // GPIO_ResetBits(GPIOB, GPIO_Pin_1);//開燈
- // GPIO_ResetBits(GPIOC, GPIO_Pin_5);
- // PBout(1)=0;
- // PCout(5)=0;
- #endif
- }
- //按鍵初始化
- void KEY_Iint(void)
- {
- RCC->APB2ENR |= 1<<2;//開啟PA口時鐘
- }
- //蜂鳴器初始化
- void BEEF_Iint(void)
- {
- RCC->APB2ENR |= 1<<4;//開啟PC口時鐘
- GPIOC->CRL &=~(0XF<<4*3);//清PC3
- GPIOC->CRL |=(0X3<<4*3);//通用輸出 50M
- }
- /*
- 驅動層
- 1.完成按鍵的消抖,松手檢測
- 2.把過程細分為一個個狀態
- 3.實現長按與單擊功能
- 按鍵初始態
- 按鍵確認態
- 按鍵計時態
- 等待按鍵釋放態
- */
- unsigned char key_driver()
- {
- static u8 key_state = 0, key_time = 0;
- u8 key_return = N_key;
- switch (key_state)
- {
- case 0: // 按鍵初始態
- if (!KEY_AN) key_state = 1; // 鍵被按下,狀態轉換到按鍵消抖和確認狀態
- break;
- case 1: // 按鍵消抖與確認態
- if (!KEY_AN)
- {
- key_time = 0;
- key_state = 2; // 按鍵仍然處于按下,消抖完成,狀態轉換到按下鍵時間的計時狀態,但返回的還是無鍵事件
- }
- else
- key_state = 0; // 按鍵已抬起,轉換到按鍵初始態。此處完成和實現軟件消抖,其實按鍵的按下和釋放都在此消抖的。
- break;
- case 2: // 按下鍵時間的計時狀態
- if(KEY_AN)
- {
- key_return = S_key; // 此時按鍵釋放,說明是產生一次短操作,回送S_key
- key_state = 0; // 轉換到按鍵初始態
- }
- else if (++key_time >= 100) // 繼續按下,計時加10ms(10ms為本函數循環執行間隔)
- {
- key_return = L_key; // 按下時間>1000ms,此按鍵為長按操作,返回長鍵事件
- key_state = 3; // 轉換到等待按鍵釋放狀態
- }
- break;
- case 3: // 等待按鍵釋放狀態,此狀態只返回無按鍵事件
- if (KEY_AN) key_state = 0; // 按鍵已釋放,轉換到按鍵初始態
- break;
- }
- return key_return;
- }
- /*
- 業務邏輯層
- 1.單擊、雙擊、長按的分配
- */
- unsigned char key_read()
- {
- static u8 key_m = 0, key_time_1 = 0;
- u8 key_return = N_key,key_temp;
- key_temp = key_driver();
- switch(key_m)
- {
- case 0:
- if (key_temp == S_key )
- {
- key_time_1 = 0; // 第1次單擊,不返回,到下個狀態判斷后面是否出現雙擊
- key_m = 1;
- }
- else
- key_return = key_temp; // 對于無鍵、長鍵,返回原事件
- break;
- case 1:
- if (key_temp == S_key) // 又一次單擊(間隔肯定<500ms)
- {
- key_return = D_key; // 返回雙擊鍵事件,回初始狀態
- key_m = 0;
- }
- else
- { // 這里500ms內肯定讀到的都是無鍵事件,因為長鍵>1000ms,在1s前低層返回的都是無鍵
- if(++key_time_1 >= 30)
- {
- key_return = S_key; // 500ms內沒有再次出現單鍵事件,返回上一次的單鍵事件
- key_m = 0; // 返回初始狀態
- }
- }
- break;
- }
- return key_return;
- }
- /*
- 單擊:300ms~1000ms之間
- 雙擊:300ms內
- 長按:超過1s
- 單擊:控制LED1
- 雙擊:控制LED2
- 長按:控制蜂鳴器
- */
- int main(void)
- {
- LED_Init();
- KEY_Iint();
- BEEF_Iint();
- while(1)
- {
- switch(key_read())
- {
- case N_key:
- delay_ms(10);
- break;
- case S_key:
- PBout(1)=!PBout(1);
- break;
- case D_key:
- PCout(5)=!PCout(5);
- break;
- case L_key:
- BEEF = !BEEF;
- break;
- }
- }
- return 0;
- }
復制代碼
【必讀】版權免責聲明
1、本主題所有言論和內容純屬會員個人意見,與本論壇立場無關。2、本站對所發內容真實性、客觀性、可用性不做任何保證也不負任何責任,網友之間僅出于學習目的進行交流。3、對提供的數字內容不擁有任何權利,其版權歸原著者擁有。請勿將該數字內容進行商業交易、轉載等行為,該內容只為學習所提供,使用后發生的一切問題與本站無關。 4、本網站不保證本站提供的下載資源的準確性、安全性和完整性;同時本網站也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的損失或傷害。 5、本網站所有軟件和資料均為網友推薦收集整理而來,僅供學習用途使用,請務必下載后兩小時內刪除,禁止商用。6、如有侵犯你版權的,請及時聯系我們(電子郵箱1370723259@qq.com)指出,本站將立即改正。
|