day12:按鍵KEY1和KEY2控制LED燈的亮滅


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;
			}
		}
	}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM