個人學習筆記:按鍵實驗
一.所使用的函式
1.時鐘使能函式
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
2.引腳初始化函式
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
3.對IO口置1
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
4.對IO口置0
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
5.讀取引腳輸入資料的函式
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
二.代碼撰寫程序整理
1.撰寫button.h檔案
# ifndef __Button_H
# define __Button_H
void button_Init(void);
uint8_t Botton_scan(uint8_t); //在原始的檔案中寫的是u8,但是在新的stm32f10x.h頭檔案中未定義,所以無法直接使用
#endif
2.撰寫button.c檔案
void button_Init(void)
{
GPIO_InitTypeDef GPIO_Initstructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //使能GPIOE的時鐘
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPU; //設定模式為上拉輸入
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_Initstructure); //初始化PE3
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPU; //設定模式為上拉輸入
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_Initstructure); //初始化PE4
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA的時鐘
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IPD; //設定模式為下拉輸入
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstructure); //初始化PA0
}
正點原子的精英板一共有三個按鍵:WK_UP、KEY1、KEY2 ,其中KEY1和KEY2分別對應PE3和PE4,WK_UP對應的是PA0.在無按鍵按下時PE3和PE4對應引腳的資料是1,按下按鍵時PE3和PE4對應引腳輸入的資料是0,為上拉輸入,所以在模式選擇的時候我們選擇了上拉輸入GPIO_Mode_IPU;在無按鍵按下時WK_UP對應引腳的資料是0,按下按鍵時WK_UP對應引腳輸入的資料是1,為上拉輸入,所以在模式選擇的時候我們選擇了下拉輸入GPIO_Mode_IPD.
總結 上拉輸入和下拉輸入:當一個按鍵按下的時候,對應的引腳輸入資料是0或1是不確定的,還要看外部電路的組成是上拉還是下拉,當外部電路時上拉的時候,即外部接正的時候,讀入的資料是1;當外部電路是下拉的時候,讀入的資料是0.所以上拉輸入就是無按鍵按下時是1,有按鍵按下時是0;而下拉輸入就是無按鍵按下時是0,有按鍵按下時是1.
uint8_t Botton_scan(uint8_t mode)
{
static uint8_t button_up = 1;
if(mode == 1)
button_up = 1; //模式1支持連續按鍵,無論之前button_up的值為多少,這里都將其置1,不管button_up之前的資料
if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
{
button_up =0; //不支持連續按鍵模式時,按下按鈕時置0,為了保存按鍵狀態
delay_ms(10); //軟體消抖
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
return 1;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
return 2;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
return 3;
}
else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 1|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 1|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0)
{
button_up = 1; //無按鍵按下
}
return 0;
}
這個是正點原子所提供的按鍵代碼,為了讓這段代碼更方便分析,我把它所有的宏定義都替換掉了,這個按鍵代碼是集“支持連續按鍵”和“不支持連續按鍵”功能于一身,連續按鍵:當mode等于1時它支持連續按鍵,原因是那一句if讓button_up = 1,這樣子它就可以不管static保存上一次呼叫代碼所得的值,也就是不管按鍵之前的狀態,只要按下就回傳其對應的值,從而實作連續按鍵,不支持連續按鍵:不支持連續按鍵的關鍵是將button_up設定為一個static值,它可以保存上一次呼叫該函式,最后button_up的值,不支持連續按鍵,就是上一次如果是非按下狀態,那么在這次檢測到的按下狀態就可以回傳對應按鈕所對應的值;但是如果上次是按下狀態,在這次檢測到的狀態還是按下狀態,它就不會回傳對應的值而是回傳0,下面我把該代碼拆成兩部分,這樣可以更清楚地了解二者不同之處:
uint8_t Botton_scan(uint8_t mode) //連續按鍵
{
button_up = 1;
if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
{
delay_ms(10); //軟體消抖
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
return 1;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
return 2;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
return 3;
}
}
uint8_t Botton_scan(uint8_t mode) //不支持連續按鍵
{
static uint8_t button_up = 1;
if(button_up == 1&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1))
{
button_up =0;
delay_ms(10); //軟體消抖
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
return 1;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
return 2;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1)
return 3;
}
else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 1|GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 1|GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0)
{
button_up = 1; //無按鍵按下
}
return 0;
}
3.撰寫main.c函式
# include "Button.h"
# include "Led.h"
# include "Beep.h"
# include "stm32f10x.h"
# include "delay.h"
int main(void)
{
button_Init();
delay_init();
led_Init();
beep_Init();
while(1)
{
uint8_t button = 0;
button = Botton_scan(0); //選擇不支持連續按鍵模式
if (button != 0)
{
switch(button)
{
case 1 :
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
break;
case 2 :
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
break;
case 3 :
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
GPIO_SetBits(GPIOB,GPIO_Pin_8);
break;
}
}
else delay_ms(10);
}
}
在主函式中我為了讓按鍵效果可以體現出來,讓KEY1按下LED0亮,讓KEY2按下LED1亮,按下KEY_UP時,LED0和LED1同時亮,并且有蜂鳴器響,點亮led和讓蜂鳴器響的代碼前兩天分享過了,大家可以自己結合一下,
三.發現的問題
在自己寫代碼的時候發現了那些視頻可能是幾年前的視頻了,在我的stm32f10x.h頭檔案中它沒有了對uint8_t的宏定義,所以我在移植代碼的時候使用u8會報錯,
總的來說,st定義無符號8位整形資料有很多種表示方法:
1 unsigned int 8——標準寫法;
2 uint8_t ;
3 u8; ——有問題
這個錯誤我找到的原因是這個,如果有其他的原因希望大家可以幫我指出,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/250284.html
標籤:其他
上一篇:I/O埠的簡單應用
