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

浙公网安备 33010602011771号