一、GPIO(General Purpose Input Output)通用输入输出口
1、可配置为8种输入输出模式
2、引脚电平:0V~3.3V,部分引脚可容忍5V
3、输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
(1)LED:发光二极管,正向通电点亮,反向通电不亮
(2)有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
(3)无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
4、输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
(1)按键:常见的输入设备,按下导通,松手断开
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动
(2)传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出
5、在STM32中,所有的GPIO都是挂载在APB2外设总线上的
二、LED闪烁
1、按照以下接线方式连接,并将STLINK插到电脑上
2、新建一个STM32工程
操作STM32的GPIO总共需要3个步骤
(1)使用RCC开启GPIO的时钟
(2)使用GPIO_Init函数初始化GPIO
(3)使用输出或者输入的函数控制GPIO口
这里总共涉及了RCC和GPIO两个外设
RCC库函数
GPIO库函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
用结构体的参数来初始化GPIO口,先定义一个结构体变量,然后再给结构体赋值,后调用这个函数,这个函数内部就自动读取结构体的值,再自动把外设各个参数配置好
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
GPIO_StructInit函数,这个函数可以把结构体变量赋值一个默认值
3、编写代码
(1)添加延时函数
并将新建的文件夹在keil软件中添加组和文件
配置工程选项
(2)声明头文件
(3)编写LED闪烁代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0; //GPIOA外设的0号引脚
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //输出速度50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure);
//GPIO_ResetBits(GPIOA,GPIO_Pin_0); //低电平 led亮
//GPIO_SetBits(GPIOA,GPIO_Pin_0); //高电平 led灭
//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//led亮
//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); //led灭
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //低电平 led亮
Delay_ms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_0); //高电平 led灭
Delay_ms(500);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//led亮
Delay_ms(100);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); //led灭
Delay_ms(100);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);//led亮 强制类型转换 0类型转换为枚举类型
Delay_ms(500);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1); //led灭 强制类型转换 1类型转换为枚举类型
Delay_ms(500);
}
}
(4)实现效果
LED闪烁
三、LED流水灯
1、按照以下接线方式连接,并将STLINK插到电脑上
2、复制LED闪烁的工程
利用按位或的操作方式,对多个引脚进行同时设置
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ; //GPIOA外设的0~7号引脚
GPIO_Write的使用
3、编写代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ; //GPIOA外设的0~7号引脚
//GPIO_InitStructure.GPIO_Pin= GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //输出速度50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure);
while(1)
{
GPIO_Write(GPIOA,~0X0001); //0000 0000 0000 0001 这16个二进制分别对应PA0到PA15总共16个端口,低电平亮,所以按位取反
Delay_ms(500);
GPIO_Write(GPIOA,~0X0002); //0000 0000 0000 0010
Delay_ms(500);
GPIO_Write(GPIOA,~0X0004); //0000 0000 0000 0100
Delay_ms(500);
GPIO_Write(GPIOA,~0X0008); //0000 0000 0000 1000
Delay_ms(500);
GPIO_Write(GPIOA,~0X0010); //0000 0000 0001 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0X0020); //0000 0000 0010 0000
GPIO_Write(GPIOA,~0X0040); //0000 0000 0100 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0X0080); //0000 0000 1000 0000
Delay_ms(500);
}
}
4、实现效果
LED流水灯
四、蜂鸣器
1、按照以下接线方式连接,并将STLINK插到电脑上
2、复制LED闪烁的工程
编写代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_12; //GPIOB外设的12号引脚
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //输出速度50MHz
GPIO_Init(GPIOB,&GPIO_InitStructure);
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12); //低电平 buzzer响
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12); //高电平 buzzer关
Delay_ms(100);
GPIO_ResetBits(GPIOB,GPIO_Pin_12); //低电平 buzzer响
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12); //高电平 buzzer关
Delay_ms(700);
}
}
实现效果
蜂鸣器
五、按键控制LED
1、按照以下接线方式连接,并将STLINK插到电脑上
2、在工程上完成LED和按键的驱动代码
将驱动代码封装在另外的.c和.h文件里(利用模块化编程的方式)
(1)打开工程文件夹,新建一个Hardware文件夹,用来存放硬件驱动
(2)打开keil,打开工程管理,添加组
(3)配置工程选项
(4)在新建文件夹中添加.c和.h文件
.c文件(用来存放驱动程序的主体代码)
.h文件 (用来存放这个驱动程序对外提供的函数或变量的声明)
(5)写驱动代码
在主函数上面写上LED模块的头文件
(6)用同样的方法把按键封装在驱动函数模块里
3、编写代码
(1)main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "button.h"
uint8_t ButtonNum;
int main(void)
{
LED_Init();
Button_Init();
while(1)
{
ButtonNum=Button_GetNum();
if(ButtonNum==1)
{
LED1_Turn();
}
if(ButtonNum==2)
{
LED2_Turn();
}
}
}
(2)LED.c
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
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);
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 LED1_Turn(void)
{
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1); //高电平 LED1灭
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1); //低电平 LED1亮
}
}
void LED2_ON(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
void LED2_OFF(void)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
void LED2_Turn(void)
{
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2); //高电平 LED2灭
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2); //低电平 LED2亮
}
}
(3)LED.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void);
#endif
(4)button.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Button_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
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);
}
uint8_t Button_GetNum(void)
{
uint8_t ButtonNum =0;
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);
Delay_ms(20);
ButtonNum=1;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);
Delay_ms(20);
ButtonNum=2;
}
return ButtonNum;
}
(5)button.h
#ifndef __BUTTON_H
#define __BUTTON_H
void Button_Init(void);
uint8_t Button_GetNum(void);
#endif
4、实现效果
按键控制LED
六、光敏传感器控制蜂鸣器
1、按照以下接线方式连接,并将STLINK插到电脑上
2、封装蜂鸣器
(1)buzzer.c
#include "stm32f10x.h" // Device header
void Buzzer_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
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);
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(GPIOB,GPIO_Pin_12);
}
}
(2)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
(3)LightSensor.c
#include "stm32f10x.h" // Device header
void LightSensor(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
uint8_t LightSensor_Get(void)
{
return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
}
(4)LihtSensor.h
#ifndef __LIGHT_SENSOR_H
#define __LIGHT_SENSOR_H
void LightSensor(void);
uint8_t LightSensor_Get(void);
#endif
3、编写代码
#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();
}
}
}
4、实现效果
光敏传感器控制蜂鸣器
七、GPIO的使用方法
1、初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE); //x为A、B等
2、定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
3、赋值结构体
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //选择8种输入输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_x; //x为0、1、2等引脚号,可以用按位或选择多个引脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//选择输出速度
4、初始化外设
GPIO_Init(GPIOx,&GPIO_InitStructure); //x为A、B等,将指定的GPIO外设初始化好
5、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);
6、模块化编程
因为自己做产品,外围硬件较多,就要把每个硬件的驱动函数单独提取出来,封装在.c和.h文件里,有利于简化主函数的逻辑