(一)简介
我们可以提供,一个按钮控制板载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翻转
- }
- }
- }
(三)程序现象