有关GPIO的输入输出原理请看我的文章STM32ZET6—寄存器编程(自写固件库)-优快云博客
有关工程建立的操作请看我的文章STM32F103ZE—STM32标准库及工程文件的建立-优快云博客
GPIO的输出—点亮LED小灯
原理图

我们以第一个LED小灯R为例。
从电路图上看,小灯是共阳极的,为了使电流流通,当PB5为低电平的时候,R小灯导通,所以,我们需要控制PB5输出一个低电平。
编程
但我们建立好工程文件后,我们在USER文件夹下建立新文件夹并命名为led,在这个文件夹里新建bsp_led.h,bsp_led.c(名字可以随便取)两个文件。在keil5的工程目录USER里添加bsp_led.c文件。


我们在bsp_led.c里写如下代码:
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
//定义GPIO初始化结构体
GPIO_InitTypeDef GPIO_InitStruct;
//在GPIO结构体中添加引脚口
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
//定义输出模式,这里是通用推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
//定义输出的速度,50MHz
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//调用GPIO初始化函数,将要初始化的GPIOB和GPIOB的结构体配置传入GPIO初始化函数
GPIO_Init(GPIOB, &GPIO_InitStruct);
//开启GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}
这里面的函数,结构体在“stm32f10x_gpio.h”和时钟“stm32f10x_rcc.h”当中寻找,大家可以按照函数名,函数注释了解功能。例如:打开“stm32f10x_gpio.h”,滑动鼠标滑轮到文件底部。

我们根据GPIO_Init(.....)的函数名可以知道,这个是GPIO初始化函数,鼠标右击函数

跳转到GPIO_Init(....)函数的定义处,依据函数处的说明来使用

配置完GPIO的初始化后,记得还要开启对应GPIOB时钟时钟。
在stm32中我们配置一些功能时大致分为
1,初始化函数
2,开启时钟
3,特殊功能特殊配置
写完bsp_led.c在bsp_led.h里面做一些声明和引用。
#ifndef _BSP_LED_H
#define _BSP_LED_H
#include "stm32f10x.h"
#define ON 0
#define OFF 1
#define LED_R(a) if(a)\
GPIO_SetBits(GPIOB, GPIO_Pin_5); \
else \
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
void LED_GPIO_Config(void);
#endif /* _BSP_LED_H */
#ifndef _BSP_LED_H
#define _BSP_LED_H
.....................................
#endif /* _BSP_LED_H */
这三段内容是为了防止在多文件调用过程中出现的重复包含和定义,其逻辑是这样的。
如果没有定义“bsp_led.h” == #ifndef _BSP_LED_H
那就定义"bsp_led.h" == #define _BSP_LED_H
结束了,注释一下/*bsp_led.h*/ == #endif /* _BSP_LED_H */
这样的宏定义后,在程序中ON就是1,OFF就是0(这样做的目的是为了增加可读性,ON和OFF比1和0容易理解)
宏定义 ON 1
宏定义 OFF 0
这是宏定义的一种用法,其逻辑是,定义了LED_R(a),如果a是真值(真值就是1),就执行GPIO_SetBits(GPIOB, GPIO_Pin_5);。如果a是假值(假值就是0),就执行 GPIO_ResetBits(GPIOB, GPIO_Pin_5);。
\是C语言的一种用法,用来连接上下代码的。
GPIO_SetBits(GPIOB, GPIO_Pin_5);和GPIO_ResetBits(GPIOB, GPIO_Pin_5);用法在“stm32f10x_gpio.h”里。
#define LED_R(a) if(a)\
GPIO_SetBits(GPIOB, GPIO_Pin_5); \
else \
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
主函数main()里面写。
#include "stm32f10x.h"
#include "bsp_led.h"
int main(void)
{
LED_GPIO_Config();
LED_R(ON);
}
小灯点亮
GPIO的输入—按键检测
按下K2点亮R小灯。
原理图

硬件消抖原理
当K2没有被按下时,PC13与GND相连,为低电平。
当K2被按下时,1,3导通,首先C61电容充电,当C61充电完成,电流会通过电阻接GND,此时,PC13检测C61电容为高电平。
这里我们不需要软件消抖,因为加了一个C61电容实现硬件消抖。
原理如下:K2被按下时,如果存在抖动,K2这个按键上的1,3在短时间内是不断地接通断开。
当1,3接通时,因为GND有一个R65的电阻存在,电路会优先给C61充电,因为当前是抖动状态,C61是不会充满电的。
当1,3断开时,C61存储的电流会通过R65电阻流入GND(因为R65的阻值比单片机要小,所以是不会流入PC13进而流入单片机的),所以,C61放电完成。这样就可以实现消抖。
如果不是抖动,1,3导通,首先C61电容充电,当C61充电完成,电流会通过电阻接GND,此时,PC13检测C61电容为高电平。
编程
但我们建立好工程文件后,我们在USER文件夹下建立新文件夹并命名为key,在这个文件夹里新建key.h,key.c(名字可以随便取)两个文件。在keil5的工程目录USER里添加key.c文件。
我们在key.c里写如下代码:
#include "key.h"
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*开启按键端口的时钟*/
RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
//选择按键的引脚
GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
// 设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//使用结构体初始化按键
GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
//选择按键的引脚
GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
//设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//使用结构体初始化按键
GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 函数名:Key_Scan
* 描述 :检测是否有按键按下
* 输入 :GPIOx:x 可以是 A,B,C,D或者 E
* GPIO_Pin:待读取的端口位
* 输出 :KEY_OFF(没按下按键)、KEY_ON(按下按键)
*/
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;
}
else
return KEY_OFF;
}
key.h写如下代码:
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
// 引脚定义
#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
/** 按键按下标置宏
* 按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
* 若按键按下为低电平,把宏设置成KEY_ON=0 ,KEY_OFF=1 即可
*/
#define KEY_ON 1
#define KEY_OFF 0
void Key_GPIO_Config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
#endif /* __KEY_H */
同时我们在配置好LED小灯。
#include "stm32f10x.h"
#include "bsp_led.h"
#include "key.h"
int main(void)
{
LED_GPIO_Config();
Key1_Config();
LED_B(OFF);
while(1)
{
if(KeyScan(GPIOC, GPIO_Pin_13)==Key_ON)
{
LED_B(ON);
}
}
}
因本人水平有限,不足之处在所难免,敬请各位网友指正
467

被折叠的 条评论
为什么被折叠?



