做公益的网站,跨境电商开发公司,icp备案在哪里查询,信阳市工程建设信息网站目录
前言
STM32第七节#xff1a;GPIO输入——按键检测#xff08;包含带参宏#xff09;
带参宏
代码替换展示
定义带参宏
GPIO输入——按键检测
硬件部分
端口输入数据寄存器#xff08;GPIOx_IDR#xff09;
编写程序
配置以及编写bsp_key文件
main函数编程…目录
前言
STM32第七节GPIO输入——按键检测包含带参宏
带参宏
代码替换展示
定义带参宏
GPIO输入——按键检测
硬件部分
端口输入数据寄存器GPIOx_IDR
编写程序
配置以及编写bsp_key文件
main函数编程
bsp_led.c以及bsp_led.h文件函数编程
使用固件库控制io口
直接操作寄存器的方法控制IO
小结 前言 上节课我们学习了GPIO输出——使用固件库点亮LED包含LED以及GPIO的讲解以及具体代码的编写。那么我们节本课就接着上节课讲讲带参宏以及GPIO输入——按键检测。 创作不易点个三连霸 STM32第七节GPIO输入——按键检测包含带参宏
带参宏
代码替换展示 我们在编写程序的时候在其他代码里见到过带参宏的定义例如LED_G(ON/OFF)这种定义那么带参宏是纯粹的C语言知识我们看以下的代码这里就在上一节的基础上相当于替换掉了GPIO口操作的两行代码换成了带参宏。 //GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);LED_G(OFF);Delay(0xFFFFF);//GPIO_ResetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);LED_G(ON);Delay(0xFFFFF); 那么我们该如何定义带参宏呢
定义带参宏 那么我们打开bsp_led.h再次定义两个宏ON/OFF
#define ON 1
#define OFF 0#define LED_G(a) if(a) \GPIO_ResetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);\else GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN); 这里我们其实是写了一个宏定义函数我们设置了ON为1OFF为0在下面的宏函数中定义LED_G(a)中的参量是否为1或0这样我们就可以控制输出的具体代码使得main.c文件更加简洁明了可读性更强。
GPIO输入——按键检测 上节课讲了GPIO口的输出这节课我们来讲讲输入。我们可以通过一个按键来改变外部的这个电平的状态让io口来读取电平的状态。
硬件部分 在我们的指南者板子上只有两个按键K1,K2。 我们看右边的高电平为3V3但是我们的GPIO对于这个是有限制的所以我们在前面接了一个限流电阻R4,R5,R7,R11,当按键没有按下的时候默认接地为低电平按键按下之后就变成了高电平。因为PA0有自动唤醒的功能wakeup而wakeup一定要是上升沿才能唤醒的为了统一风格所以是上升沿输入。 电路图中的电容又有什么用呢之前在学51单片机的时候我们采取的消抖方式为软件消抖我们这个是机械按键需要延时20ms消抖是前后都要消抖要不然就会像交流电一样不断接通3.3V如果我们接了这个电容的话就会一直给电容充放电直到稳定。之后无论是按下还是抬起电容也在不断的充放电对我们的电路没有影响。所以我们就不需要软件消抖。如果等于高电平我们就确认按键按下了如果等于低电平我们就抬起了按键进行相应的动作。
端口输入数据寄存器GPIOx_IDR 很显然这个寄存器还是配置低位的寄存器不做更改时为0若配置某位为1即接通3.3V变为高电平。 编写程序 我们现在还没讲中断等以后我们还会写中断函数类似51单片机
配置以及编写bsp_key文件 我们先打开bsp_key.h文件定义KEY1和KEY2的宏定义包括打开时钟宏定义接口以及设定Pin的值为0和13。
#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_PIN GPIO_Pin_0#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
#define KEY2_GPIO_PORT GPIOC
#define KEY2_GPIO_PIN GPIO_Pin_13 定义好之后类似bsp_led.c中我们打开bsp_key.c然后创建一个函数LED_KEY_Config(void)然后再该函数中定义结构体类型打开APB2上的时钟配置模式以及初始化GPIO。
void LED_KEY_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK,ENABLE);GPIO_InitStruct.GPIO_Pin KEY1_GPIO_PIN;GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(KEY1_GPIO_PORT,GPIO_InitStruct); //地址即可
} 然后我们要创建一个按键检测的函数。刚刚讲过我们的按键是硬件消抖所以我们这里就不再需要进行delay函数的消抖。我们宏定义按键按下为KEY_ON,释放按键为KEY_OFF
#define KEY_ON 1
#define KEY_OFF 0 紧接着我们编写函数由于有返回值我们使用uint8_t写函数先使用if检测是否有按键按下如果没有就是OFF。然后在按下之后我们需要检测是否松手也就是按键的释放。使用while关键字检测是否一直为按下状态。这里使用了GPIO_ReadInputDataBit函数用来读取按键的状态
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{ /*检测是否有按键按下 */if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) KEY_ON ) { /*等待按键释放 */while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) KEY_ON); return KEY_ON; }elsereturn KEY_OFF;
} 这样我们就编写完成函数记得要声明一下
void Key_GPIO_Config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin); 到这里我们的bsp_key的函数就全部编写完成了接下来编写其他函数。
main函数编程 我们在这里首先引用Key_GPIO_ConfiG();来初始化函数。然后在while循环中写一个if语句如果按键检测结果为KEY_ON,则使LED1翻转即LED1_TOGGLE;复制这段代码拷贝一份到下面检测按键2的状态。这就是主函数中的代码接下来我们配置TOGGLE函数以及bsp_led中的函数及代码。
#include stm32f10x.h // 相当于51单片机中的 #include reg51.h
#include bsp_led.h
#include bsp_key.hvoid Delay(uint32_t count)
{for(;count!0;count--);
}int main(void)
{ LED_GPIO_Config();Key_GPIO_Config();while(1) { if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) KEY_ON ){LED1(ON);}if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) KEY_ON ){LED2_TOGGLE;} }
}bsp_led.c以及bsp_led.h文件函数编程 我们先编写宏定义LED连接的GPIO端口RGB。
/* 定义LED连接的GPIO端口, 用户只需要修改下面的代码即可改变控制的LED引脚 */
// R-红色
#define LED1_GPIO_PORT GPIOB /* GPIO端口 */
#define LED1_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define LED1_GPIO_PIN GPIO_Pin_5 /* 连接到SCL时钟线的GPIO */// G-绿色
#define LED2_GPIO_PORT GPIOB
#define LED2_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED2_GPIO_PIN GPIO_Pin_0// B-蓝色
#define LED3_GPIO_PORT GPIOB
#define LED3_GPIO_CLK RCC_APB2Periph_GPIOB
#define LED3_GPIO_PIN GPIO_Pin_1#define ON 1
#define OFF 0 如果我们想实现翻转LED灯可以通过控制寄存器的方法也可以通过控制标准的固件库的方法来控制io口。
使用固件库控制io口 本节课刚开始就介绍了带参宏的定义我们可以通过这个办法来控制
/* 使用标准的固件库控制IO*/
#define LED1(a) if (a) \GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);\else \GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN)#define LED2(a) if (a) \GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);\else \GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN)#define LED3(a) if (a) \GPIO_SetBits(LED3_GPIO_PORT,LED3_GPIO_PIN);\else \GPIO_ResetBits(LED3_GPIO_PORT,LED3_GPIO_PIN)
直接操作寄存器的方法控制IO 在使用这个方法之前我们先介绍一下C语言中的异或二进制运算符^。0^1为11^1为0而0^0为01^0为1然后我们就可以控制io口。我们既需要操作BSRR和BRR寄存器也需要操作ODR寄存器分别输出高电平低电平以及输出反转状态。
/* 直接操作寄存器的方法控制IO */
#define digitalHi(p,i) {p-BSRRi;} //输出为高电平
#define digitalLo(p,i) {p-BRRi;} //输出低电平
#define digitalToggle(p,i) {p-ODR ^i;} //输出反转状态/* 定义控制IO的宏 */
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)#define LED3_TOGGLE digitalToggle(LED3_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_OFF digitalHi(LED3_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_ON digitalLo(LED3_GPIO_PORT,LED3_GPIO_PIN) 然后我们就可以使用三原色来进行混色基本混色
/* 基本混色后面高级用法使用PWM可混出全彩颜色,且效果更好 */
//红
#define LED_RED \LED1_ON;\LED2_OFF\LED3_OFF//绿
#define LED_GREEN \LED1_OFF;\LED2_ON\LED3_OFF//蓝
#define LED_BLUE \LED1_OFF;\LED2_OFF\LED3_ON//黄(红绿)
#define LED_YELLOW \LED1_ON;\LED2_ON\LED3_OFF//紫(红蓝)
#define LED_PURPLE \LED1_ON;\LED2_OFF\LED3_ON//青(绿蓝)
#define LED_CYAN \LED1_OFF;\LED2_ON\LED3_ON//白(红绿蓝)
#define LED_WHITE \LED1_ON;\LED2_ON\LED3_ON//黑(全部关闭)
#define LED_RGBOFF \LED1_OFF;\LED2_OFF\LED3_OFF 在bsp_led.c文件中我们需要配置初始化结构体然后打开时钟有选择性然后紧接着设置模式以及速度。都是前几节课熟知的不在多讲然后就是通过控制3个Pin的值然后初始化GPIO口并附带关闭所有LED灯的代码
void LED_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin LED1_GPIO_PIN;GPIO_Init(LED1_GPIO_PORT, GPIO_InitStructure); //地址即可GPIO_InitStructure.GPIO_Pin LED2_GPIO_PIN;GPIO_Init(LED2_GPIO_PORT, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin LED3_GPIO_PIN;GPIO_Init(LED3_GPIO_PORT, GPIO_InitStructure);/* 关闭所有led灯 */GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN); GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
} 如果断言错误我们执行如下代码
void assert_failed(uint8_t* file, uint32_t line)
{// 断言错误时执行的代码LED1_ON;
}
小结 到这里我们就写完了所有代码以及代码的讲解两种方式控制io口。下节课我们学习位带操作。