7. 用寄存器点亮LED
7.1 GPIO简介
GPIO是通用输入输出端口的简称,简单来说就是STM32可控制的引脚。通过将STM32芯片的GPIO引脚与外部设备连接,可以实现外部通信、控制以及数据采集的功能。STM32芯片的GPIO被分成很多组,每组有16个引脚。例如,STM32F103VET6的芯片有GPIOA至GPIOE共5组GPIO,100个引脚中GPIO占了一大部分。所有的GPIO引脚都有基本的输入输出功能。
最基本的输出功能是由STM32控制引脚输出高、低电平,实现开关控制。比如把GPIO引脚接入LED灯,就可以控制LED灯的亮灭;引脚接入继电器或三极管,就可以通过继电器或三极管控制外部大功率电路的通断。最基本的输入功能是检测外部输入电平,比如把GPIO引脚连接到按键,通过电平高低区分按键是否被按下。
7.2 GPIO框图剖析
通过GPIO硬件结构框图,可以从整体上深入了解GPIO外设及其各种应用模式。下面我们按图7-1中的编号对GPIO端口的结构部件进行说明。
7.2.1 基本结构分析
-
保护二极管及上、下拉电阻:
- 引脚的两个保护二极管可以防止引脚外部过高或过低的电压输入。当引脚电压高于VDD时,上方的二极管导通;当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁。尽管有这样的保护,并不意味着STM32的引脚能直接外接大功率驱动器件,如直接驱动电机。
-
P-MOS管和N-MOS管:
- GPIO引脚线路经过两个保护二极管后,向上流向“输入模式”结构,向下流向“输出模式”结构。推挽输出模式由P-MOS和N-MOS管组成的单元电路实现。推挽输出的等效电路见图7-2。开漏输出模式时,上方的P-MOS管完全不工作。等效电路见图7-3。
- 推挽输出模式一般应用在输出电平为0和3.3V且需要高速切换的场合。开漏输出一般应用在I2C、SMBUS通信等需要“线与”功能的总线电路中。
-
输出数据寄存器:
- 双MOS管结构的输入信号由GPIO输出数据寄存器GPIOx_ODR提供。通过修改输出数据寄存器的值,可以修改GPIO引脚的输出电平。
-
复用功能输出:
- 复用功能输出中的“复用”是指STM32的其他片上外设对GPIO引脚进行控制。比如使用USART串口通信时,可将GPIO引脚配置成USART串口复用功能。
-
输入数据寄存器:
- GPIO引脚经过内部的上、下拉电阻,可以配置成上/下拉输入,然后连接到肖特基触发器,信号经过触发器后转化为0、1的数字信号,存储在输入数据寄存器GPIOx_IDR中。
-
复用功能输入:
- 在复用功能输入模式时,GPIO引脚的信号传输到STM32的其他片上外设,由该外设读取引脚状态。
-
模拟输入输出:
- 当GPIO引脚用于ADC采集电压的输入通道时,用作模拟输入功能。类似地,当GPIO引脚用于DAC作为模拟电压输出通道时,作为模拟输出功能。
7.2.2 GPIO工作模式
GPIO可以配置成以下模式:
-
输入模式(模拟/浮空/上拉/下拉):
- 在输入模式时,肖特基触发器打开,输出被禁止。输入模式可设置为上拉、下拉、浮空和模拟4种。
-
输出模式(推挽/开漏):
- 在输出模式中,推挽模式时双MOS管轮流工作。开漏模式时,只有N-MOS管工作。输出速度可配置,有2MHz、10MHz、50MHz几种选项。
-
复用功能(推挽/开漏):
- 在复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,输出信号源于其他外设。
通过对GPIO寄存器写入不同的参数,可以改变GPIO的工作模式。具体寄存器说明查阅《STM32F10X-中文参考手册》。
7.3 实验:使用寄存器点亮LED
7.3.1 硬件连接
在本书中STM32芯片与LED的连接如下图所示。这个RGB灯由红蓝绿3个小灯构成,使用PWM控制时可以混合成256种不同的颜色。
目标是将GPIO的引脚设置成推挽输出模式,并且默认下拉,输出低电平,使LED亮起来。
7.3.2 启动文件
启动文件startup_stm32f10x_hd.s
用汇编语言写好了基本程序,当STM32芯片上电启动时,首先会执行汇编程序,建立起C语言的运行环境。该文件可以从ST固件库找到,并添加到工程中。
启动文件的主要功能如下:
- 初始化堆栈指针SP。
- 初始化程序计数器指针PC。
- 设置堆、栈的大小。
- 初始化中断向量表。
- 配置外部SRAM作为数据存储器(由用户配置)。
- 调用SystemInit()函数配置STM32的系统时钟。
- 设置C库的分支入口“__main”。
7.3.3 stm32f10x.h文件
定义寄存器映射代码在stm32f10x.h
文件中,见代码清单7-5。
#define GPIOB_BASE (0x40010C00)
#define RCC_BASE (0x40021000)
#define GPIOB_CRL (*((volatile unsigned long *)(GPIOB_BASE + 0x00)))
#define GPIOB_CRH (*((volatile unsigned long *)(GPIOB_BASE + 0x04)))
#define GPIOB_IDR (*((volatile unsigned long *)(GPIOB_BASE + 0x08)))
#define GPIOB_ODR (*((volatile unsigned long *)(GPIOB_BASE + 0x0C)))
#define GPIOB_BSRR (*((volatile unsigned long *)(GPIOB_BASE + 0x10)))
#define GPIOB_BRR (*((volatile unsigned long *)(GPIOB_BASE + 0x14)))
#define RCC_APB2ENR (*((volatile unsigned long *)(RCC_BASE + 0x18)))
7.3.4 main文件
在main文件中编写一个main函数,先定义一个空的SystemInit函数。
void SystemInit(void) {
// 配置STM32的系统时钟
}
int main(void) {
// 主程序
return 0;
}
1. GPIO模式
将连接到LED的GPIO引脚PB0配置成输出模式,具体见代码清单7-7。
// 清除GPIOB0位的配置
GPIOB_CRL &= ~(0xF << 0);
// 设置GPIOB0为推挽输出,10MHz速度
GPIOB_CRL |= (0x1 << 0);
2. 控制引脚输出电平
操作ODR寄存器控制GPIO的电平,见代码清单7-8。
// 设置GPIOB0输出低电平
GPIOB_ODR &= ~(0x1 << 0);
// 设置GPIOB0输出高电平
GPIOB_ODR |= (0x1 << 0);
3. 开启外设时钟
所有GPIO都挂载到APB2总线上,具体时钟由APB2外设时钟使能寄存器(RCC_APB2ENR)控制,见代码清单7-9。
// 使能GPIOB的时钟
RCC_APB2ENR |= (1 << 3);
4. 完整代码
完整的程序代码如下:
#include "stm32f10x.h"
// 初始化系统时钟
void SystemInit(void) {
// 配置STM32的系统时钟
}
int main(void) {
// 使能GPIOB的时钟
RCC_APB2ENR |= (1 << 3);
// 清除GPIOB0位的配置
GPIOB_CRL &= ~(0xF << 0);
// 设置GPIOB0为推挽输出,10MHz速度
GPIOB_CRL |= (0x1 << 0);
// 设置GPIOB0输出低电平
GPIOB_ODR &= ~(0x1 << 0);
while (1) {
// 循环点亮LED
}
return 0;
}
7.3.5 下载验证
把编译好的程序下载到开发板并复位,可以看到板子上的LED被点亮。
至此,通过寄存器控制点亮LED的实验成功完成。
标签:输出,LED,引脚,点亮,STM32,GPIOB,寄存器,GPIO From: https://blog.csdn.net/weixin_43905308/article/details/140633742