今天心情不錯,寫篇日記來記錄一下我學習STM32按鍵控制LED的大抵情況
***************************************************************************************************************************************
開發闆 :奮鬥STM32
CPU :STM32F103
開發環境:keil uVsion4
****************************************************************************************************************************************
本文主要是通過輪詢的方法來實作按鍵控制LED的亮滅,我初始化led為滅的狀态,也就是一開始上電LED就是滅着的,當實作按鍵按下時,LEd亮,再按下按鍵是LEd滅。 led對應的開發闆GPIO管腳如圖:
我寫的按鍵輪詢功能是所要實作的功能是:按下K1,LED1亮(按鍵K1對應PC5管腳,LED1對應PB5管腳) 代碼如下: main.c
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "led.h"
#include "key.h"
int main(void)
{
SystemInit();
init_led_gpio();
Key_GPIO_Config();
/* turn_led(LED1,ON);
turn_led(LED2,ON);
turn_led(LED3,ON); */
while (1)
{
if (KeyScan(GPIOC,GPIO_Pin_5) == KEY_ON)
{
/* LED1反轉 讀取GPIOB 5端口位的值并用1減去之後再寫入此位即LED1的控制位 */
GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)));
}
if (KeyScan(GPIOC,GPIO_Pin_2) == KEY_ON)
{
/* LED2反轉 讀取GPIOD 6端口位的值并用1減去之後再寫入此位即LED2的控制位 */
GPIO_WriteBit(GPIOD, GPIO_Pin_6,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_6)));
}
if (KeyScan(GPIOC,GPIO_Pin_3) == KEY_ON)
{
/* LED3反轉 讀取GPIOD 3端口位的值并用1減去之後再寫入此位即LED3的控制位 */
GPIO_WriteBit(GPIOD, GPIO_Pin_3,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_3)));
}
}
}
led.c
#include "stm32f10x.h"
#define ON 1
#define OFF 0
enum
{
LED1 = 0,
LED2,
LED3,
MAX_LED,
};
typedef struct led_gpio_s
{
int num; /* LED編号 */
GPIO_TypeDef *group; /* LED使用的GPIO在哪一組: GPIOB or GPIOD */
uint16_t pin; /* LED使用的GPIO組中的那一個pin: GPIO_Pin_x */
} led_gpio_t;
led_gpio_t leds_gpio[MAX_LED] =
{
{LED1, GPIOB, GPIO_Pin_5}, /* LED1 用的GPB5 */
{LED2, GPIOD, GPIO_Pin_6}, /* LED2 用的GPD6 */
{LED3, GPIOD, GPIO_Pin_3}, /* LED3 用的GPD3 */
};
/*LED的初始化*/
void init_led_gpio(void)
{
int i;
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能PB和PD組 GPIO的時鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);
/*設定 PB5(LED1), PD6(LED2), PD3(LED3)為 GPIO 輸出推免模式,口線翻轉速度為50MHz */
for(i=0; i<MAX_LED; i++)
{
/*設定 PB5(LED1)為 GPIO 輸出推免模式,口線翻轉速度為50MHz */
GPIO_InitStructure.GPIO_Pin = leds_gpio[i].pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(leds_gpio[i].group, &GPIO_InitStructure);
}
}
/*使LED在初始化後處于全滅狀态*/
void turn_led(int which, int cmd)
{
if(which<0 || which> MAX_LED )
return ;
if(OFF == cmd)
GPIO_ResetBits(leds_gpio[which].group, leds_gpio[which].pin);
else
GPIO_SetBits(leds_gpio[which].group, leds_gpio[which].pin);
}
key.c
#include "stm32f10x.h"
#define KEY_ON 1
#define KEY_OFF 0
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--);
}
}
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_2 |GPIO_Pin_3;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHZ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init (GPIOC,&GPIO_InitStructure);
}
/*
* @brief : 按鍵按下檢測
* @param : 端口 : GPIOx 端口位 : GPIO_Pin_x
* @retval : 按鍵的狀态 : 按下 彈起
*/
uint8_t KeyScan( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin_x )
{
/* 檢測是否有按鍵按下 */
if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON )
{
/* 延時消抖 延時大約5ms */
delay_ms(5);
if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON )
{
while ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON ); /* 等待按鍵釋放 */
return KEY_ON;
}
else
{
return KEY_OFF;
}
}
return KEY_OFF;
}
寫這個程式主要是為了完成相關的配置工作: 1.初始化LED和初始化時鐘
void init_led_gpio(void)
{
int i;
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能PB和PD組 GPIO的時鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);
/*設定 PB5(LED1), PD6(LED2), PD3(LED3)為 GPIO 輸出推免模式,口線翻轉速度為50MHz */
for(i=0; i<MAX_LED; i++)
{
/*設定 PB5(LED1)為 GPIO 輸出推免模式,口線翻轉速度為50MHz */
GPIO_InitStructure.GPIO_Pin = leds_gpio[i].pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(leds_gpio[i].group, &GPIO_InitStructure);
}
}
由于奮鬥STM32開發闆有3個按鍵控制3個LED,為了代碼的簡潔和美觀,本文用了一個for循環來實作LED的管腳的配置 2.配置按鍵以及初始化時鐘
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_2 |GPIO_Pin_3;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHZ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init (GPIOC,&GPIO_InitStructure);
}
3.delay_ms函數用于消抖
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--);
}
}
關于按鍵消抖: 按鍵消抖:按鍵消抖通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,由于機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴随有一連串的抖動,為了不産生這種現象而作的措施就是按鍵消抖。
********************************************************************************************************************************************************************************************************************************************************