【?聲明:版權所有,歡迎轉載,請勿用于商業用途。 聯系信箱:feixiaoxing @163.com】
? ? ? ? 做技術的同學,大部分都會把精力放在技術本身,卻忽視了學的東西有什么實際的用途。就拿gpio來說,一般我們點燈也好、做輸入也好,最多也就是當成一個實驗demo在使用。可是大家有沒有思考過,其實這樣一個模塊就已經是一個完整的輸入、輸出的系統了。簡單的方面,我們可以做一個2-4譯碼器、3-8譯碼器,復雜一點的,我們可以做玩具、做一個設備改造的模塊。
? ? ? ? 很多同學不理解這個設備改造的模塊,還是以卷簾門為例。過去卷簾門,一般就是向上按鍵按下去,卷簾門上升;向下按鍵按下去,卷簾門下降。如果我們想擴展一下這個功能,比如向上按下去的時候,為了安全需要,不僅卷簾門上升,還要有一個語音和紅綠燈顯示,這個時候就可以用這樣一個模塊來完成了。過去可能非標領域一般都是通過plc來完成,現在我們自己學會了mcu開發,就很自然地想通過mcu來完成。
1、按鍵輸入
? ? ? ? 按鍵輸入是和按鍵輸出對應的。按鍵輸出,一般是led點亮、熄滅,又或者是蜂鳴器呼叫等等而按鍵輸入,更多時候來自于外部的反饋,它表示使用的人員希望開啟、使用或者是關閉某個功能。
2、main函數分析
? ? ? ? 首先,我們還是看下整個demo的原貌,
int main(void)
{SystemClock_Config();LED_GPIO_Config(); Key_GPIO_Config();while(1) { if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ){LED1_ON;}else{LED1_OFF;}}
}
? ? ? ? 和之前相比較,整個流程多了兩部分,第一個是添加Key_GPIO_Config,這個主要是告訴mcu,哪些按鍵希望被當做是key輸入使用。第二個是Key_Scan,主要用于檢測當前KEY1_PIN是不是已經被按下。如果是被按下了,那么LED1點亮,反之熄滅。
3、配置按鍵輸入
? ? ? ? 前面我們說過,要配置按鍵輸入,需要看下Key_GPIO_Config是如何實現的。這部分關注的重點,集中在它和之前GPIO輸出有什么差別。
void Key_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;KEY1_GPIO_CLK_ENABLE();GPIO_InitStructure.Pin = KEY1_PIN; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Pull = GPIO_NOPULL;HAL_GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
}
? ? ? ? 這里的KEY1_PIN是a0,不過不是重點。重點在于,當key處于輸入狀態的時候,它的mode和pull是不一樣的。這部分,大家可以對比一下之前led的設置,這樣看起來效果更好。
void LED_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;LED1_GPIO_CLK_ENABLE();GPIO_InitStruct.Pin = LED1_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStruct); LED_RGBOFF;
}
4、輪詢檢查key的狀態
? ? ? ? 較早讀書的時候,我會認為輪詢是非常低效的一種情況。但是到了mcu這里,輪詢是非常常見的一種開發方式。特別是功能比較單一的時候,輪詢其實很簡潔、很魯棒,幾乎不會出錯,
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{ if(HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON ) {return KEY_ON; }else{return KEY_OFF;}
}
5、測試方法
? ? ? ? 之前野火提供的測試demo其實不是這樣,它的case其實是依據它自身的開發板實現的。上面有現成的實體按鍵。這邊的話,我們既然是用一個stm32f103的核心板進行測試,那么就用一根短接線進行測試好了。
? ? ? ? 短接線的一頭連接在a0上面,另外一頭可以連接到電源3.3v,又或者是gnd上面。如果是連接在電源3.3v上面,c13應該亮起;反之則熄滅。通過這樣的方式,也可以觀察到按鍵輸入的實際效果。另外還有一點要注意的是,我們核心板上面只有一個c13可以點燈,這和野火官方的demo不太一樣,所以同樣需要改造一下,
#define LED1_PIN GPIO_PIN_13
#define LED1_GPIO_PORT GPIOC
#define LED1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
6、美中不足
? ? ? ? 這邊按鍵按下去的時候,正常情況下都會delay延時一下,一段事件之后確認按鍵是不是真的被按下。這樣做的好處是防止誤觸、或者是抖動的發生。當然,我們也可以讓測試做的更好玩一點,比如設置成閃爍的形式,
int main(void)
{SystemClock_Config();LED_GPIO_Config(); Key_GPIO_Config();while(1) { if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ){HAL_Delay(1000);LED1_ON;HAL_Delay(1000);LED1_OFF;}else{LED1_OFF;}}
}