STM32 固件库初应用--点灯(输出)、按键(输入)

目录

一、用固件库点亮LED灯——输出

(1)点亮灯

(2)移植到其他板子

二、按键检测——输入

关于固件库的应用,我们从输入和输出两个角度来进行练习,外设都以常见的GPIO口为例。

一、用固件库点亮LED灯——输出

(1)点亮灯

我们在USER文件夹中,每用到一个模块,就建立一个相关模块的文件夹。建立led文件夹,在该文件夹中添加.c和.h文件,同时,别忘了给新的.h文件添加编译路径(前面文章介绍过)。

为防止该文件被多个文件引用而产生重定义的情况,我们在每个.h文件的开头都加上条件编译的宏。

#ifndef __BSP_LED_H
#define __BSP_LED_H


#endif /*__BSP_LED_H*/

1.观察外设(GPIO)端口结构体的成员:引脚、速度、输出/入方式,我们把常用到的端口、引脚这些宏定义(与硬件相关的)用我们熟悉的、好理解的名字在bsp_led.h文件里面重新define宏定义一下。

#define LED1_GPIO_CLK         RCC_APB2Periph_GPIOC//时钟
#define LED1_GPIO_PORT        GPIOC               //端口
#define LED1_GPIO_PIN         GPIO_Pin_2//pin 引脚

#define LED2_GPIO_CLK         RCC_APB2Periph_GPIOC//时钟
#define LED2_GPIO_PORT        GPIOC               //端口
#define LED2_GPIO_PIN         GPIO_Pin_3//pin

2.在新建立的led文件夹中,添加控制led的.c文件:bsp_led.c,在里面添加关于led的函数:初始化两个灯的程序(两个led灯用到两个不同的端口,所以要分别配置两个不同的初始化函数)。根据前面文章介绍的初始化I/O口的步骤

   1、打开外设(GPIO)的时钟

   2、选定I/O口

   3、配置输入还是输出(配置CRL/CRH寄存器)

   4、如果是输出,配置输出速率(也是在CRL/CRH寄存器)

   5、调用外设(GPIO)初始化函数,把配置好的结构体成员写到寄存器里面

void LED_GPIO_Config(void)//初始化相关的GPIO 第2个灯
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/*第一步:打开外设的时钟(RCC寄存器控制)*/
	RCC_APB2PeriphClockCmd(LED1_GPIO_CLK|LED2_GPIO_CLK,ENABLE);
	
	/*第二步:配置外设初始化结构体*/
	GPIO_InitStruct.GPIO_Pin = LED1_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	
	/*第三步:调用外设初始化函数,把配置好的结构体成员写到寄存器里面*/
	GPIO_Init(LED1_GPIO_PORT,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = LED2_GPIO_PIN;
	GPIO_Init(LED2_GPIO_PORT,&GPIO_InitStruct);
}

初始化函数放在主函数while循环之前,并且写一个软件延时更好的判断实验现象。

void delay(uint32_t count);

int main(void)
{
	/*在程序来到main函数这里的时候,系统时钟已经配置成72M*/
	
	LED_GPIO_Config();//初始化函数
	while(1)
	{
		GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
		delay(0xfffff);
		GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
		delay(0xfffff);
		GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
		delay(0xfffff);
		GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
		delay(0xfffff);
	}
}

void delay(uint32_t count)
{
	for(;count!=0;count--);
}

(2)移植到其他板子

如果我们把代码移植到其他板子上时,寄存器会发生改变,如果将代码通过宏来进行控制,将会做到与硬件无关,只需修改简单的宏,增加可移植性。

在led的.h文件里里面:添加板子的宏定义,增加if判断语句。

#define YHMINI    1
#define YHIOT     0

#if  YHMINI 
#define LED1_GPIO_CLK         RCC_APB2Periph_GPIOC//时钟
#define LED1_GPIO_PORT        GPIOC               //端口
#define LED1_GPIO_PIN         GPIO_Pin_2//pin 引脚

#define LED2_GPIO_CLK         RCC_APB2Periph_GPIOC//时钟
#define LED2_GPIO_PORT        GPIOC               //端口
#define LED2_GPIO_PIN         GPIO_Pin_3//pin

#elif  YHIOT 
#define LED1_GPIO_CLK         RCC_APB2Periph_GPIOB//时钟
#define LED1_GPIO_PORT        GPIOB               //端口
#define LED1_GPIO_PIN         GPIO_Pin_0//pin

#define LED2_GPIO_CLK         RCC_APB2Periph_GPIOB//时钟
#define LED2_GPIO_PORT        GPIOB               //端口
#define LED2_GPIO_PIN         GPIO_Pin_1//pin

#endif

二、按键检测——输入

  

用到GPIOA、C端口,并且需要配置输入数据寄存器(IDR)高16位不动,只配置低16位(第0位和第13位)

1.按键检测函数:

与51不同的是,这里采取的是按下按键返回数据的方式,按下且松手之后返回按下的指令,没按下返回未被按下的指令。且按键按下之后是高电平,松手是低电平。我们只需要自己写一个按键检测函数即可,且这个函数是要带返回值的。

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);//松手检测
		//如果while循环的条件为真,也就说明按键一直被按下,先不返回指令
		return KEY_ON;//松手之后,才返回按键被按下的指令
	}
	
	else return KEY_OFF;//按下没被按下,返回按键未被按下的指令
}
//要求:按键按下不出现反应,当按键按下且松手之后再出现指令

2.宏定义闪烁:按键按下一次:灯亮;再按下一次:灯灭。如此循环,相关解释如下:

//按键按下一次:灯亮;再按下一次:灯灭。如此循环
//两个数^ :若两数相同为0,不同为1
#define digitalTOGGLE(p,i)   {p->ODR ^= i;}
#define LED1_TOGGLE          digitalTOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2_TOGGLE          digitalTOGGLE(LED2_GPIO_PORT,LED2_GPIO_PIN)
/*   p->ODR ^= i  : p->ODR = p->ODR  ^  i
0000 0000 0000 0000 ^ 0000 0000 0000 0010 = 0000 0000 0000 0010
0000 0000 0000 0010 ^ 0000 0000 0000 0010 = 0000 0000 0000 0000
0000 0000 0000 0000 ^ 0000 0000 0000 0010 = 0000 0000 0000 0010
......*/

这样在main函数里面就会写的非常简单:

int main(void)
{
	LED_GPIO_Config();
	KEY_GPIO_Config();
	
	while(1)
	{
		if(KEY_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
		{
			/*如果检测到按键1被按下,LED1闪烁一次*/
			LED1_TOGGLE;
		}
		
		if(KEY_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON)
		{
			/*如果检测到按键2被按下,LED2闪烁一次*/
			LED2_TOGGLE;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值