KEY1控制LED1,KEY2控制LED2
bsp_led.h:
/* 和LED功能模塊相關的程序 */ #ifndef __BSP_LED_H__ #define __BSP_LED_H__ #include "stm32f10x.h" /*宏定義*/ #define GPIO_CLK_D4 RCC_APB2Periph_GPIOC // 時鍾 #define GPIO_PORT_D4 GPIOC // C端口 #define GPIO_PIN_D4 GPIO_Pin_2 // PC2引腳 #define GPIO_CLK_D5 RCC_APB2Periph_GPIOC // 時鍾 #define GPIO_PORT_D5 GPIOC // C端口 #define GPIO_PIN_D5 GPIO_Pin_3 // PC2引腳 /*參數宏定義*/ /* digitalTOGGLE(p,i)是參數宏定義,p表示LED的端口號,ODR是數據輸出寄存器, 查stm32f10x的官方中文手冊的第8.2章的ODR寄存器,要點亮LED,根據原理圖,要輸出低電平0, C語言中,^表示異或,即a^b表示a和b不同時輸出為1,相同時輸出為0,比如0^1=1,1^1=0,0^0=0, 這里為什么操作ODR,p是什么?查看stm32f10x.h文件,搜索GPIO_TypeDef就會明白, i是LED的引腳對應的位電平,經過digitalTOGGLE(p,i) {p->ODR ^= i;}之后, 第一次p為0,i一直為1,第一次異或結果輸出1,第二次輸出0,第三次輸出1,這樣間斷輸出010101,燈不斷亮滅 */ #define digitalTOGGLE(p,i) {p->ODR ^= i;} #define LED1_TOGGLE digitalTOGGLE(GPIO_PORT_D4,GPIO_PIN_D4) #define LED2_TOGGLE digitalTOGGLE(GPIO_PORT_D5,GPIO_PIN_D5) /*配置GPIO*/ void LED_GPIO_Config(void); #endif /*__BSP_LED_H__*/
bsp_led.c:
/* 和LED功能模塊相關的程序頭文件 */ #include "./led/bsp_led.h" /*絕對路徑,也可在Options for target中設置頭文件*/ /*GPIO初始化*/ void LED_GPIO_Config(void) { /*外設結構體*/ GPIO_InitTypeDef GPIO_InitStruct_D4, GPIO_InitStruct_D5; /*第一步:打開外設的時鍾,看stm32f10x_rcc.c這個文件的RCC_APB2PeriphClockCmd函數介紹*/ RCC_APB2PeriphClockCmd(GPIO_CLK_D4, ENABLE); /*第二步:配置外設的初始化結構體*/ GPIO_InitStruct_D4.GPIO_Pin = GPIO_PIN_D4; // PC2的那盞LED燈(D4)的引腳 GPIO_InitStruct_D4.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出模式 GPIO_InitStruct_D4.GPIO_Speed = GPIO_Speed_10MHz; // 引腳速率 GPIO_InitStruct_D5.GPIO_Pin = GPIO_PIN_D5; // PC3的那盞LED燈(D5)的引腳 GPIO_InitStruct_D5.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出模式 GPIO_InitStruct_D5.GPIO_Speed = GPIO_Speed_10MHz; // 引腳速率 /*第三步:調用外設初始化函數,把配置好的結構體成員寫到寄存器里面*/ GPIO_Init(GPIO_PORT_D4, &GPIO_InitStruct_D4); GPIO_Init(GPIO_PORT_D5, &GPIO_InitStruct_D5); }
bsp_key.h:
#ifndef __BSP_KEY_H__ #define __BSP_KEY_H__ #include "stm32f10x.h" #define KEY_ON 1 #define KEY_OFF 0 // 按鍵相關的宏定義 #define GPIO_CLK_KEY1 RCC_APB2Periph_GPIOA // 端口A時鍾 #define GPIO_PORT_KEY1 GPIOA // A端口 #define GPIO_PIN_KEY1 GPIO_Pin_0 // PA0引腳 #define GPIO_CLK_KEY2 RCC_APB2Periph_GPIOC // 端口C時鍾 #define GPIO_PORT_KEY2 GPIOC // C端口 #define GPIO_PIN_KEY2 GPIO_Pin_13 // PC13引腳 // 配置GPIO void KEY_GPIO_Config(void); // 按鍵掃描,看按鍵是否被按下,如果按下返回KEY_ON,否則返回KEY_OFF(進行宏定義) uint8_t KEY_SCAN(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); #endif /* __BSP_KEY_H__ */
bsp_key.c:
#include "./key/bsp_key.h" /* 按鍵初始化 */ void KEY_GPIO_Config(void) { /*外設結構體*/ GPIO_InitTypeDef GPIO_InitStruct_KEY1, GPIO_InitStruct_KEY2; /*第一步:打開外設的時鍾,看stm32f10x_rcc.c這個文件的RCC_APB2PeriphClockCmd函數介紹*/ RCC_APB2PeriphClockCmd(GPIO_CLK_KEY1|GPIO_CLK_KEY2, ENABLE); // 按下KEY1或KEY2 /*第二步:配置外設的初始化結構體*/ GPIO_InitStruct_KEY1.GPIO_Pin = GPIO_PIN_KEY1; // KEY1的引腳 GPIO_InitStruct_KEY1.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空輸出模式(引腳電平由外部決定) GPIO_InitStruct_KEY1.GPIO_Speed = GPIO_Speed_10MHz; // 引腳速率 GPIO_InitStruct_KEY2.GPIO_Pin = GPIO_PIN_KEY2; // KEY1的引腳 GPIO_InitStruct_KEY2.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空輸出模式(引腳電平由外部決定) GPIO_InitStruct_KEY2.GPIO_Speed = GPIO_Speed_10MHz; // 引腳速率 /*第三步:調用外設初始化函數,把配置好的結構體成員寫到寄存器里面*/ GPIO_Init(GPIO_PORT_KEY1, &GPIO_InitStruct_KEY1); GPIO_Init(GPIO_PORT_KEY2, &GPIO_InitStruct_KEY2); } /* 按鍵掃描(檢測按鍵是否被按下):GPIOx為端口,GPIO_Pin為引腳 */ uint8_t KEY_SCAN(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { /*查看stm32f10x_gpio.h文件最后面的函數,這個函數表示讀引腳的輸入電平(按鍵觸發后輸入的)*/ // 這個函數,如果按鍵按下,則輸出1.8V高電平,置1,否則為0 if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON) { // 如果一直按着就進入死循環 while(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON); // 放開按鍵就置1 return KEY_ON; } else { // 否則置0 return KEY_OFF; } }
main.c:
#include "stm32f10x.h" #include "./led/bsp_led.h" #include "./key/bsp_key.h" // 延遲函數 void delay(unsigned int i) { for(; i!=0; i--); } int main(void) { /*GPIO初始化,在程序來到main函數的時候,系統時鍾已經配置成72MHz*/ LED_GPIO_Config(); // LED初始化 KEY_GPIO_Config(); // KEY初始化 while(1) { // 如果按下KEY1,則D4亮滅,KEY1對應的是PA0,A端口的第1個引腳 if(KEY_SCAN(GPIOA, GPIO_PIN_KEY1) == KEY_ON) { LED1_TOGGLE; } // 如果按下KEY2,則D5亮滅,KEY2對應的是PC13,C端口的第14個引腳 if(KEY_SCAN(GPIOC, GPIO_PIN_KEY2) == KEY_ON) { LED2_TOGGLE; } } }
實驗現象:
程序燒錄到板子中,一開始LED1和LED2都是亮的(應該都是滅的才對),按下KEY1控制LED1的亮和滅,按下KEY2控制LED2的亮和滅
============================================
下面是默認情況下LED2和LED2都是熄滅的情況:
main.c
/* KEY控制LED亮滅實驗,LED一開始默認都熄滅,等按下KEY1或KEY2后才能亮 */ #include "stm32f10x.h" #include "./led/bsp_led.h" #include "./key/bsp_key.h" // 延遲函數 void Delay(unsigned int time) { for(;time!=0;time--); } int main(void) { uint8_t count = 1; KEY_GPIO_Config(); while(1) { // LED默認情況下是滅的,等按下KEY1或KEY2時,對應的LED才會亮 if(KEY_SCAN(GPIO_PORT_KEY1, GPIO_PIN_KEY1) == KEY_ON) { if(count == 1) { LED_GPIO_Config(); // 按下KEY1時兩個LED都亮 LED2_TOGGLE; // 讓LED2滅(其實是亮-->滅),時間很短,人眼分辨不出來 count++; } else { LED1_TOGGLE; } } if(KEY_SCAN(GPIO_PORT_KEY2, GPIO_PIN_KEY2) == KEY_ON) { if(count == 1) { LED_GPIO_Config(); // 按下KEY2時兩個LED都亮 LED1_TOGGLE; // 讓LED1滅(其實是亮-->滅),時間很短,人眼分辨不出來 count++; } else { LED2_TOGGLE; } } } }