STM32 入门 2
GPIO 简介
GPIO(General Purpose Input Output)通用输入输出口
可配置8种输入输出模式
引脚电平 0~3.3V,部分可以容忍 5V
输出模式可以控制端口输出高低电平,用来驱动 LED、蜂鸣器和模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
GPIO 基本结构
STM32 所有 GPIO 都是挂载在 APB2 外设总线上的,GPIO 外设名称按照 GPIOA,GPIOB,GPIOC... 来命名
每个 GPIO 外设有16个引脚,编号0~15,GPIOA 第0号引脚称为 PA0,以此类推
每个 GPIO 外设内包括寄存器和驱动器,寄存器每一位对应一个引脚,0 低电平,1 高电平
由于 STM32 是 32 位的,寄存器只有低 16 位有端口,高 16 位没用
GPIO 模式
改变端口配置寄存器的值,可以配置8种模式
- 浮空输入 悬空不确定,因此使用时需要接上连续的驱动源
- 上拉输入 悬空默认高电平
- 下拉输入 悬空默认低电平
- 模拟输入 GPIO 无效,引脚直接接入 ADC(只有该模式会关闭数字输入功能)
- 开漏输出 高电平位高阻态,无驱动能力
- 推挽输出 高电平接 VDD,低电平接 VSS
- 复用开漏输出 由片上外设控制
- 复用推挽输出 由片上外设控制
LED 和蜂鸣器
LED:小的一瓣是正极,大的一瓣是负极
有源蜂鸣器:内部自带震荡源,正负极接上直流电压即可持续发声,频率固定
无源蜂鸣器:内部不带震荡源,需要控制器提供震荡脉冲才可发声,调整提供震荡脉冲的频率,可发出不同频率的声音
GPIO 输出
启用APB2上的GPIOA外设时钟
GPIO 初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
输出函数
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // 指定端口设置为高电平
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // 指定端口设置为低电平
GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); // 根据 BitVal 设置指定端口
// 这里 BitVal 可以是 Bit_SET 和 Bit_RESET,分别对应高低电平
GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); // 可以同时对16个端口写入操作
LED 闪烁
`
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //clock
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
//GPIO_SetBits(GPIOA,GPIO_Pin_0);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
while(1){
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
}
}
Delay.h 手动添加,在 System 文件夹下面,需要添加组和头文件包含路径
现在 LED 是低电平点亮方式
如果是高电平点亮,推挽输出有驱动能力,开漏输出没有驱动能力
LED 流水灯
初始化多个引脚
因为每个端口相当于对应了一位,或可以拼装这些引脚
另外还有 GPIO_Pin_All 可以控制所有引脚(0~15)
除了 GPIO 引脚可以用或运算,时钟控制的位置也可以用或运算选择多个外设(因为定义中每一位对应一个外设)
GPIO_SetBits() 函数设置引脚的时候同理可以用或运算拼接
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //clock
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//GPIO_ResetBits(GPIOA, GPIO_Pin_0);
//GPIO_SetBits(GPIOA,GPIO_Pin_0);
//GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
int controller = 0x0001;
while(1){
for(int i=1;i<=8;i++)
{
GPIO_Write(GPIOA, ~controller); // 这里的 controller 每一位对应一个引脚的高低电平,从最低位(最右)到最高位依次对应0~15,取反是因为低电平驱动
Delay_ms(500);
controller *= 2;
}
controller = 0x0001;
}
}
控制蜂鸣器
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //clock
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_ResetBits(GPIOA, GPIO_Pin_0);
//GPIO_SetBits(GPIOA,GPIO_Pin_0);
//GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
while(1){
GPIO_WriteBit(GPIOB, GPIO_Pin_12,Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET);
Delay_ms(500);
}
}