本帖最后由 小恶魔owo 于 2024-12-3 22:21 编辑

(一)简介
我们可以提供,一个按钮控制板载LED灯,来学习GPIO的输入和输出
板载LED的引脚为PC13,我们选择一个按钮引脚为PA0
(将按钮一段连接PA0,另一端连接GND)

(二)讲解
为了main函数的简洁,同时让操作不用很复杂,我们可以将LED和按钮KEY,创建一个库
然后在main里面调用LED和KEY库,类似于arduino那样的编程方法
image.png

我们先复制一个工程模板,然后在Hardware里面添加两个库
LED.c,LED.h
Key.c,Key.h
image.png

然后在库文件管理里面添加
image.png
image.png

LED.C
首先引用一下stm32库
  1. #include "stm32f10x.h"   

初始化PC13,这个在上节课讲过
  1. void LED_Init(void)
  2. {
  3.         /*开启时钟*/
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);                //开启GPIOC的时钟
  5.         
  6.         /*GPIO初始化*/
  7.         GPIO_InitTypeDef GPIO_InitStructure;
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.         GPIO_Init(GPIOC, &GPIO_InitStructure);                                                //将PC13引脚初始化为推挽输出
  12.         

  13. }

然后,我们可以定义三个函数,LED的开关
  1. void LED1_ON(void)
  2. {
  3.         GPIO_SetBits(GPIOC, GPIO_Pin_13);                //设置PC13引脚为高电平
  4. }

  5. void LED1_OFF(void)
  6. {
  7.         GPIO_ResetBits(GPIOC, GPIO_Pin_13);                //设置PC13引脚为低电平
  8. }

还有LED的电平转换
电平转换的就是先检测PC13引脚的状态,然后如果状态为0则设置为1,反之为1设置为0
  1. void LED1_Turn(void)
  2. {
  3.         if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13) == 0)                //获取输出寄存器的状态,如果当前引脚输出低电平
  4.         {
  5.                 GPIO_SetBits(GPIOC, GPIO_Pin_13);                                        //则设置PA1引脚为高电平
  6.         }
  7.         else                                                                                                        //否则,即当前引脚输出高电平
  8.         {
  9.                 GPIO_ResetBits(GPIOC, GPIO_Pin_13);                                        //则设置PA1引脚为低电平
  10.         }
  11. }


LEC.H
为了让main的函数能够调用LED库的函数,我们还需要一个.H文件
其中#ifndef __LED_H、#define __LED_H、#endif为固定格式,名称根据.C函数来定义
中间放我们定义的函数名字,格式为 void xxxx(void);
  1. #ifndef __LED_H
  2. #define __LED_H

  3. void LED_Init(void);
  4. void LED1_ON(void);
  5. void LED1_OFF(void);
  6. void LED1_Turn(void);


  7. #endif


Key.C
同理,按钮库也是要引用标准库,而且因为要软件消抖,还要一个delay延迟库
  1. #include "stm32f10x.h"
  2. #include "Delay.h"

初始化,按钮引脚PA0,和设置LED差不多,但是注意模式我们选择了GPIO_Mode_IPU上拉输入模式
  1. void Key_Init(void)
  2. {
  3.         /*开启时钟*/
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                //开启GPIOA的时钟
  5.         
  6.         /*GPIO初始化*/
  7.         GPIO_InitTypeDef GPIO_InitStructure;
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                //将PA0引脚初始化为上拉输入
  12. }

声明一个无符号的8位整型变量,意味着这个变量可以输出0-255的整数
代码内定义了一个KeyNum=0,当检测到PA0为1时,即按钮按下时
延时20毫秒消抖然后再次判断,如果还是为1,那就将KeyNum设置为1
然后函数Key_GetNum返回一个1,如果没有进入按钮模式,那就返回0
  1. uint8_t Key_GetNum(void)
  2. {
  3.         uint8_t KeyNum = 0;                //定义变量,默认键码值为0
  4.         
  5.         if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1)                        //读PA0输入寄存器的状态,如果为1,则代表按键1按下
  6.         {
  7.                 Delay_ms(20);                                                                                        //延时消抖
  8.                 while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1);        //等待按键松手
  9.                 Delay_ms(20);                                                                                        //延时消抖
  10.                 KeyNum = 1;                                                                                                //置键码为1
  11.         }
  12.         

  13.         
  14.         return KeyNum;                        //返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
  15. }

Key.H

  1. #ifndef __KEY_H
  2. #define __KEY_H

  3. void Key_Init(void);
  4. uint8_t Key_GetNum(void);

  5. #endif


Main函数
将所需的库全部引用出来
同时定义一个整数型变量KeyNnm,用来储存按钮的状态
  1. #include "stm32f10x.h"
  2. #include "Delay.h"
  3. #include "LED.h"
  4. #include "Key.h"
  5. uint8_t KeyNum;  //定义用于接收按键键码的变量

首先进行灯和按钮引脚的初始化,初始化完成之后进入while循环
KeyNum获取Key库的Key_GetNum()函数
当按钮按下时,Key_GetNum()函数会返回1,否则返回0
当KeyNum接收到1时,执行LED1_Turn函数,将LED电平翻转
  1. int main(void)
  2. {
  3.         /*模块初始化*/
  4.         LED_Init();                //LED初始化
  5.         Key_Init();                //按键初始化
  6.        
  7.         while (1)
  8.         {
  9.                 KeyNum = Key_GetNum();                //获取按键键码
  10.                
  11.                 if (KeyNum == 1)                        //按键1按下
  12.                 {
  13.                         LED1_Turn();                        //LED1翻转
  14.                 }

  15.         }
  16. }


(三)程序现象

eacd143316237a24a92f -small-original.gif