(一)简介
我们可以提供,一个按钮控制板载LED灯,来学习GPIO的输入和输出
板载LED的引脚为PC13,我们选择一个按钮引脚为PA0
(将按钮一段连接PA0,另一端连接GND)
(二)讲解
为了main函数的简洁,同时让操作不用很复杂,我们可以将LED和按钮KEY,创建一个库
然后在main里面调用LED和KEY库,类似于arduino那样的编程方法
我们先复制一个工程模板,然后在Hardware里面添加两个库
LED.c,LED.h
Key.c,Key.h
然后在库文件管理里面添加
LED.C
首先引用一下stm32库
#include "stm32f10x.h"
复制代码初始化PC13,这个在上节课讲过
void LED_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //开启GPIOC的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //将PC13引脚初始化为推挽输出
}
复制代码然后,我们可以定义三个函数,LED的开关
void LED1_ON(void)
{
GPIO_SetBits(GPIOC, GPIO_Pin_13); //设置PC13引脚为高电平
}
void LED1_OFF(void)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); //设置PC13引脚为低电平
}
复制代码还有LED的电平转换
电平转换的就是先检测PC13引脚的状态,然后如果状态为0则设置为1,反之为1设置为0
void LED1_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平
{
GPIO_SetBits(GPIOC, GPIO_Pin_13); //则设置PA1引脚为高电平
}
else //否则,即当前引脚输出高电平
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); //则设置PA1引脚为低电平
}
}
复制代码LEC.H
为了让main的函数能够调用LED库的函数,我们还需要一个.H文件
其中#ifndef __LED_H、#define __LED_H、#endif为固定格式,名称根据.C函数来定义
中间放我们定义的函数名字,格式为 void xxxx(void);
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
#endif
复制代码Key.C
同理,按钮库也是要引用标准库,而且因为要软件消抖,还要一个delay延迟库
#include "stm32f10x.h"
#include "Delay.h"
复制代码初始化,按钮引脚PA0,和设置LED差不多,但是注意模式我们选择了GPIO_Mode_IPU上拉输入模式
void Key_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为上拉输入
}
复制代码声明一个无符号的8位整型变量,意味着这个变量可以输出0-255的整数
代码内定义了一个KeyNum=0,当检测到PA0为1时,即按钮按下时
延时20毫秒消抖然后再次判断,如果还是为1,那就将KeyNum设置为1
然后函数Key_GetNum返回一个1,如果没有进入按钮模式,那就返回0
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0; //定义变量,默认键码值为0
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) //读PA0输入寄存器的状态,如果为1,则代表按键1按下
{
Delay_ms(20); //延时消抖
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1); //等待按键松手
Delay_ms(20); //延时消抖
KeyNum = 1; //置键码为1
}
return KeyNum; //返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}
复制代码Key.H
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
复制代码Main函数
将所需的库全部引用出来
同时定义一个整数型变量KeyNnm,用来储存按钮的状态
#include "stm32f10x.h"
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum; //定义用于接收按键键码的变量
复制代码首先进行灯和按钮引脚的初始化,初始化完成之后进入while循环
KeyNum获取Key库的Key_GetNum()函数
当按钮按下时,Key_GetNum()函数会返回1,否则返回0
当KeyNum接收到1时,执行LED1_Turn函数,将LED电平翻转
int main(void)
{
/*模块初始化*/
LED_Init(); //LED初始化
Key_Init(); //按键初始化
while (1)
{
KeyNum = Key_GetNum(); //获取按键键码
if (KeyNum == 1) //按键1按下
{
LED1_Turn(); //LED1翻转
}
}
}
复制代码(三)程序现象