GPIO输入及两个应用案例
GPIO输入及两个应用案例
文章目录
- GPIO输入及两个应用案例
- 1.关键字与c语言的差异
- 2.常用的四个GPIO库函数
- 3.按键控制LED
- 3.1接线图
- 3.2分类存放(硬件代码)
- 3.4代码实现
- 3.4.1主函数(main的实现)
- 3.4.2LED函数实现(开/关,状态转换)
- 函数的定义(LED.c)
- 函数的声明(LED.h)
- 3.4.3开关函数实现(检测按键状态)
- 开关函数的定义(key.c)
- 开关函数声明(key.h)
- 3.4.4头文件的拓展部分
- 4.光敏传感器控制蜂鸣器
- 4.1接线图
- 4.2代码实现
- 4.2.1主函数的实现(main.c)
- 4.2.2蜂鸣器模块的定义(Buzzer.c)
- 4.2.3蜂鸣器的声明(Buzzer.h)
- 4.2.4光敏传感器的定义(LightSensor.c)
- 4.2.5光敏传感器部分的声明(LightSensor.h)
- 5.总结GPIO的使用方法
1.关键字与c语言的差异
关键字 | 位数 | 表示范围 | stdint****关键字 | ST****关键字 |
---|---|---|---|---|
char | 8 | -128 ~ 127 | int8_t | s8 |
unsigned char | 8 | 0 ~ 255 | uint8_t | u8 |
short | 16 | -32768 ~ 32767 | int16_t | s16 |
unsigned short | 16 | 0 ~ 65535 | uint16_t | u16 |
int | 32 | -2147483648 ~ 2147483647 | int32_t | s32 |
unsigned int | 32 | 0 ~ 4294967295 | uint32_t | u32 |
long | 32 | -2147483648 ~ 2147483647 | ||
unsigned long | 32 | 0 ~ 4294967295 | ||
long long | 64 | -(2^64)/2 ~ (2^64)/2-1 | int64_t | |
unsigned long long | 64 | 0 ~ (2^64)-1 | uint64_t | |
float | 32 | -3.4e38 ~ 3.4e38 | ||
double | 64 | -1.7e308 ~ 1.7e308 |
关键字部分表示C语言时的名称,stdint表示现在库函数里面的名称,st关键字表示以前库函数的名称都是一个意思。
现在的库函数依然支持以前库函数的写法,因为内部有重新声明(为了兼容老版本)
2.常用的四个GPIO库函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
- uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);用来读取输入数据寄存器某一个端口的输入值。他的参数是GPIOx和GPIO_Pin,用来指定某一个端口,返回值是uint8_t指的是高低电平。
- uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);比上一个函数少了个bit,是用来读取整个输入数据寄存器的,参数只有一个GPIOx来指定外设,返回值是一个uint16_t,是一个16位的数据,每一位代表一个端口值。
- uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);用来读取输出数据寄存器的某一个位。所以原则上说,它不是用来读取端口的输入数据的,一般用于输出模式下,用来看自己到底输出了什么。
- uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);比上一个函数少了个bit,是用来读取整个输出寄存器的
3.按键控制LED
本实验任务:实现,按键PB1控PA1的亮灭,按键PB11控制PA2的亮灭
3.1接线图
3.2分类存放(硬件代码)
这里我们开始分层管理所以新建一个Hardware用来存放硬件
在hardware处新建c文件
.c的文件中插入stm32的头文件
.h的头文件中加入下列代码以防止重复定义
#ifndef __LED_H//判断是否重复定义if not define
#define __LED_H//如果没有重复就定义
#endif//结束,对应开头的判断
3.4代码实现
3.4.1主函数(main的实现)
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
//设置变量来接受返回值
uint8_t KeyNum;
int main(void){
LED_Init();
Key_Init();
while(1){
KeyNum = Key_getNum();
if(KeyNum == 1){
//LED1_on();
LED1_turn();
}
if(KeyNum == 2){
//LED1_off();
LED2_turn();
}
}
}
3.4.2LED函数实现(开/关,状态转换)
函数的定义(LED.c)
#include "stm32f10x.h" // Device header
//该.c文件用于定义函数
//定义LED初始化函数
void LED_Init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//定义一个结构体
GPIO_InitTypeDef GPIO_Structure;
GPIO_Structure.GPIO_Mode = GPIO_Mode_Out_PP;
//打开0口和1口
GPIO_Structure.GPIO_Pin = GPIO_Pin_1 |GPIO_Pin_2;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Structure);
GPIO_SetBits(GPIOA,GPIO_Pin_1 |GPIO_Pin_2);
}
//灯亮
void LED1_on(void){
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
//灯灭
void LED1_off(void){
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
//灯亮
void LED2_on(void){
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
//灯灭
void LED2_off(void){
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
//LED1取反操作
void LED1_turn(void){
//读取当前LED的输出状态
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)==0){
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}else{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
//LED2取反操作
void LED2_turn(void){
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2)==0){
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}else{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
}
函数的声明(LED.h)
#ifndef __LED_H
#define __LED_H
//该.h文件用于函数的声明
void LED_Init(void);
void LED1_on(void);
void LED1_off(void);
void LED2_on(void);
void LED2_off(void);
void LED1_turn(void);
void LED2_turn(void);
#endif
3.4.3开关函数实现(检测按键状态)
开关函数的定义(key.c)
#include "stm32f10x.h" // Device header
#include "Delay.h"
//初始化按键
void Key_Init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_Structure;
//这里需要读取按键所以使用GPIO_Pin_IPU(上拉输入)
GPIO_Structure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Structure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
//输入模式下这个参数其实是没用的
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Structure);
}
//获取按键的信息(按键的检测)
uint8_t Key_getNum(void){
uint8_t KeyNum = 0;
//读取到0则表示按键按下
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0){
//延时消除抖动
Delay_ms(20);
//按键一般是松手之后才会有动作的,等于0就表示一直按着
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0){
Delay_ms(20);
KeyNum = 1;
}
}
//判断Pin11的状态
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0){
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0){
Delay_ms(20);
KeyNum = 2;
}
}
return KeyNum;
}
开关函数声明(key.h)
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_getNum(void);
#endif
3.4.4头文件的拓展部分
#ifndef __KEY_H,#define __KEY_H,#endif宏保护的解释:
- #ifndef __KEY_H:这是一个预处理器指令,用于检查是否尚未定义宏 __KEY_H。ifndef 是 “if not defined” 的缩写。如果 __KEY_H 尚未被定义,那么预处理器将继续处理后续的代码。
- #define __KEY_H:如果 __KEY_H 尚未被定义,那么这条指令将定义 __KEY_H 宏。这样做的目的是防止头文件被重复包含。如果没有这种保护机制,可能会导致重复定义错误。
- #endif:结束 #ifndef 条件判断。
- 上述用于防止头文件的重复包含,而 __KEY_H 的具体名称可以根据自己的项目需要进行修改,但要保证唯一性和遵循一定的命名规则。
4.光敏传感器控制蜂鸣器
光敏传感器:遮住光线输出指示灯灭,代表输出高电平;松手时输出指示灯亮,代表输出低电平(光敏传感器的电位器可以调节高低电平的判断阈值,可以自行调节)
本实验任务:遮住光敏传感器,蜂鸣器鸣叫;未遮住光敏传感器,蜂鸣器不鸣叫。
4.1接线图
4.2代码实现
4.2.1主函数的实现(main.c)
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
int main(void){
//初始化蜂鸣器
Buzzer_Init();
//初始化传感器
LightSensor_Init();
while(1){
//光线不好蜂鸣器叫
if(LightSensor_Get()==1){
Buzzer_on();
}else{
Buzzer_off();
}
//测试蜂鸣器模块
/*Buzzer_on();
Delay_ms(500);
Buzzer_off();
Delay_ms(500);
Buzzer_turn();
Delay_ms(500);
Buzzer_turn();
Delay_ms(500);*/
}
}
4.2.2蜂鸣器模块的定义(Buzzer.c)
#include "stm32f10x.h" // Device header
//初始化蜂鸣器
void Buzzer_Init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//定义一个结构体
GPIO_InitTypeDef GPIO_Structure;
GPIO_Structure.GPIO_Mode = GPIO_Mode_Out_PP;
//打开0口和1口
GPIO_Structure.GPIO_Pin = GPIO_Pin_12;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Structure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
//蜂鸣
void Buzzer_on(void){
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}
//蜂不鸣
void Buzzer_off(void){
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
//对换蜂鸣器状态
void Buzzer_turn(void){
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12)==0){
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}else{
GPIO_ResetBits(GPIOA,GPIO_Pin_12);
}
}
4.2.3蜂鸣器的声明(Buzzer.h)
#ifndef __BUZZER_H
#define __BUZZER_H
//蜂鸣器初始化
void Buzzer_Init(void);
//蜂鸣器低电平
void Buzzer_on(void);
//蜂鸣器高电平
void Buzzer_off(void);
//蜂鸣器取反操作
void Buzzer_turn(void);
#endif
4.2.4光敏传感器的定义(LightSensor.c)
#include "stm32f10x.h" // Device header
void LightSensor_Init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//定义一个结构体
GPIO_InitTypeDef GPIO_Structure;
//可以选择上拉输入,也可以选择浮空输入(如果始终接在端口上),只要保证引脚不会悬空即可
GPIO_Structure.GPIO_Mode = GPIO_Mode_IPU;
//打开0口和1口
GPIO_Structure.GPIO_Pin = GPIO_Pin_13;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Structure);
GPIO_SetBits(GPIOB,GPIO_Pin_13);
}
uint8_t LightSensor_Get(void){
//直接获取传感器的输入数据
return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
}
4.2.5光敏传感器部分的声明(LightSensor.h)
#ifndef __LIGHT_SENSOR_H
#define __LIGHT_SENSOR_H
//传感器初始化
void LightSensor_Init(void);
//传感器输入的返回数据(高/低电平)
uint8_t LightSensor_Get(void);
#endif
5.总结GPIO的使用方法
首先,初始化时钟,定义结构体,赋值结构体(mode(模式有8种),Pin(可通过逻辑或”|“来多选),Speed要求不高(50MHz就好)),最后使用GPIO_Init来初始化GPIO外设.
读取输入输出主要使用前面讲过的(GPIO输入和GPIO输出笔记)8个输入输出函数来实现
**模块化设计。**外围硬件较多就要把每个硬件的驱动函数分别分装起来(.c和.h)用于简化主函数的逻辑