GPIO输入模式下的硬件和电路
以下为不同类型传感器电路图
硬件电路讲解
上面两种接线方式表示按键按下时是低电平,下面两种接线方式表示按键按下时引脚是高电平默认使用上面两种方式比较多。
C语言知识回顾
不同的数据类型 : char short int long longlong float double
所占的字节数为:1 2 4 4 8 4 8
c语言宏定义语法:使用#define关键字完成c语言的宏定义
typedef关键字给一个较长的变量起别名
结构体变量的引用方式
c语言知识补充详解
结构体定义
结构体引用使用点的方式
c语言的枚举使用enum关键字
//读取输入数据寄存器某一个端口的输入值参数是GPIOX和GPIO_pin用于指定某一个端口返回值是uint8_tuint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取整个输入数据寄存器参数用于指定外设,返回值是uint16_t表示16位的数据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);
接线图使用按键控制led灯
main功能代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"uint8_t KeyNum; //定义用于接收按键键码的变量int main(void)
{/*模块初始化*/LED_Init(); //LED初始化Key_Init(); //按键初始化while (1){KeyNum = Key_GetNum(); //获取按键键码if (KeyNum == 1) //按键1按下{LED1_Turn(); //LED1翻转}if (KeyNum == 2) //按键2按下{LED2_Turn(); //LED2翻转}}
}
delay.h代码
delay.c代码
#include "stm32f10x.h"/*** @brief 微秒级延时* @param xus 延时时长,范围:0~233015* @retval 无*/
void Delay_us(uint32_t xus)
{SysTick->LOAD = 72 * xus; //设置定时器重装值SysTick->VAL = 0x00; //清空当前计数值SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器while(!(SysTick->CTRL & 0x00010000)); //等待计数到0SysTick->CTRL = 0x00000004; //关闭定时器
}/*** @brief 毫秒级延时* @param xms 延时时长,范围:0~4294967295* @retval 无*/
void Delay_ms(uint32_t xms)
{while(xms--){Delay_us(1000);}
}/*** @brief 秒级延时* @param xs 延时时长,范围:0~4294967295* @retval 无*/
void Delay_s(uint32_t xs)
{while(xs--){Delay_ms(1000);}
}
LED.C代码
#include "stm32f10x.h" // Device header/*** 函 数:LED初始化* 参 数:无* 返 回 值:无*/
void LED_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA1和PA2引脚初始化为推挽输出/*设置GPIO初始化后的默认电平*/GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //设置PA1和PA2引脚为高电平
}/*** 函 数:LED1开启* 参 数:无* 返 回 值:无*/
void LED1_ON(void)
{GPIO_ResetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为低电平
}/*** 函 数:LED1关闭* 参 数:无* 返 回 值:无*/
void LED1_OFF(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1引脚为高电平
}/*** 函 数:LED1状态翻转* 参 数:无* 返 回 值:无*/
void LED1_Turn(void)
{if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平{GPIO_SetBits(GPIOA, GPIO_Pin_1); //则设置PA1引脚为高电平}else //否则,即当前引脚输出高电平{GPIO_ResetBits(GPIOA, GPIO_Pin_1); //则设置PA1引脚为低电平}
}/*** 函 数:LED2开启* 参 数:无* 返 回 值:无*/
void LED2_ON(void)
{GPIO_ResetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为低电平
}/*** 函 数:LED2关闭* 参 数:无* 返 回 值:无*/
void LED2_OFF(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2引脚为高电平
}/*** 函 数:LED2状态翻转* 参 数:无* 返 回 值:无*/
void LED2_Turn(void)
{if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平{ GPIO_SetBits(GPIOA, GPIO_Pin_2); //则设置PA2引脚为高电平} else //否则,即当前引脚输出高电平{ GPIO_ResetBits(GPIOA, GPIO_Pin_2); //则设置PA2引脚为低电平}
}
LED.H头文件
key.c功能代码
#include "stm32f10x.h" // Device header
#include "Delay.h"/*** 函 数:按键初始化* 参 数:无* 返 回 值:无*/
void Key_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); //将PB1和PB11引脚初始化为上拉输入
}/*** 函 数:按键获取键码* 参 数:无* 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下* 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手*/
uint8_t Key_GetNum(void)
{uint8_t KeyNum = 0; //定义变量,默认键码值为0if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) //读PB1输入寄存器的状态,如果为0,则代表按键1按下{Delay_ms(20); //延时消抖while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); //等待按键松手Delay_ms(20); //延时消抖KeyNum = 1; //置键码为1}if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) //读PB11输入寄存器的状态,如果为0,则代表按键2按下{Delay_ms(20); //延时消抖while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); //等待按键松手Delay_ms(20); //延时消抖KeyNum = 2; //置键码为2}return KeyNum; //返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}
项目工程中添加以下部分代码:以下为项目工程目录
程序接线图
添加模块化代码Buzzer和Buzzer头文件
#include "stm32f10x.h" // Device header
void Buzzer_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); //将PA1和PA2引脚初始化为推挽输出/*设置GPIO初始化后的默认电平*/GPIO_SetBits(GPIOB, GPIO_Pin_12); //设置PA1和PA2引脚为高电平
}void Buzzer_ON(void)
{GPIO_ResetBits(GPIOB, GPIO_Pin_12); //设置PA1引脚为低电平
}void Buzzer_OFF(void)
{GPIO_SetBits(GPIOB, GPIO_Pin_12); //设置PA1引脚为高电平
}void Buzzer_Turn(void)
{if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0) //获取输出寄存器的状态,如果当前引脚输出低电平{GPIO_SetBits(GPIOB, GPIO_Pin_12); //则设置PA1引脚为高电平}else //否则,即当前引脚输出高电平{GPIO_ResetBits(GPIOB, GPIO_Pin_12); //则设置PA1引脚为低电平}
}
添加LightSensor模块化代码以及头文件
使用ST-Link现在烧录后得到程序的运行结果
GPIO使用方法总结
// 初始化时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 定义结构体GPIO_InitTypeDef GPIO_InitStructure;// 赋值结构体GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // GPIO_Mode选择8种输入输出模式// GPIO_Pin 选择引脚,可以使用按位或的方式同时选中多个引 脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //GPIO_Speed 选择输出的速度GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;// GPIO_Init 初始化指定的GPIO外设 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_13); // stm32中8个读取和写入的函数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);void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);注意模块化的封装和注释的使用