通用目的输入输出口(GPIO)
概述
GPIO(General Purpose Input/Output)是微控制器中最基本的外设,用于与外部设备进行数字信号的输入和输出。STM32F103 的 GPIO 具有丰富的功能,可配置为多种模式,满足不同的应用需求。
GPIO 的主要特性
- 端口多样:STM32F103 提供了 GPIOA 到 GPIOG 共 7 个 GPIO 端口。
- 多种模式:
- 输入模式:浮空输入、上拉输入、下拉输入、模拟输入。
- 输出模式:推挽输出、开漏输出。
- 复用功能模式:用于外设功能引脚。
- 速度可调:输出速度可设置为 2MHz、10MHz、50MHz。
GPIO 的配置步骤
- 使能 GPIO 时钟:在使用 GPIO 之前,必须先使能对应的时钟。
- 配置 GPIO 模式:设置引脚的输入/输出模式、速度、上拉/下拉等属性。
- 读写 GPIO 引脚:
- 输入:读取引脚的电平状态。
- 输出:设置引脚为高电平或低电平。
代码示例
下面的代码演示了如何配置 GPIO 引脚并控制 LED 的亮灭。
// 启用 GPIOC 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// GPIO 配置结构体
GPIO_InitTypeDef GPIO_InitStructure;
// 配置 GPIOC Pin13 为推挽输出,速度为 50MHz
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// 点亮 LED(假设低电平点亮)
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
// 延时
Delay(1000);
// 熄灭 LED
GPIO_SetBits(GPIOC, GPIO_Pin_13);
LED 流水灯与 SYSTICK 定时器
LED 流水灯
LED 流水灯是一种简单的视觉效果,通过依次点亮和熄灭多个 LED,形成灯光“流动”的效果。这通常用于设备状态指示或装饰。
实现思路
- 初始化:配置多个 GPIO 引脚为输出模式,连接到 LED。
- 循环控制:使用循环结构,依次点亮和熄灭 LED。
- 延时控制:通过延时函数控制 LED 亮灭的速度。
SYSTICK 定时器
SYSTICK 是 Cortex-M3 内核提供的一个 24 位递减计数器,可用于产生精确的延时或定时中断。
特点
- 硬件支持:无需额外的外设配置,直接使用内核提供的功能。
- 精确性高:基于系统时钟,延时时间精确稳定。
使用方法
- 配置重装载值:设置定时器的计数初值。
- 启动计数:设置控制寄存器开始计数。
- 检测计数标志:等待计数完成或中断触发。
代码示例
下面的代码演示了如何使用 SYSTICK 定时器实现 LED 流水灯效果。
// 初始化 LED 引脚(假设使用 GPIOA 的 Pin0~Pin7)
void LED_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = 0x00FF; // Pin0~Pin7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 延时函数,单位为毫秒
void Delay_ms(uint32_t ms) {
SysTick->LOAD = ms * 9000 - 1; // 假设系统时钟为 72MHz
SysTick->VAL = 0;
SysTick->CTRL = 0x01; // 开始计数
// 等待计数结束
while (!(SysTick->CTRL & (1 << 16))) {
}
SysTick->CTRL = 0; // 关闭计数器
SysTick->VAL = 0; // 清空计数器
}
int main(void) {
LED_Init();
uint8_t i = 0;
while (1) {
GPIO_Write(GPIOA, ~(1 << i)); // 点亮第 i 个 LED
Delay_ms(200); // 延时 200ms
i = (i + 1) % 8; // 更新索引
}
}
通用数码管显示
数码管的基础知识
数码管是一种用于显示数字和部分字母的显示器件,常见于电子时钟、计数器等设备。根据内部结构,可分为共阴极和共阳极数码管。
工作原理
- 段选控制(a~g,dp):控制数码管的各个发光二极管段。
- 位选控制:选择要点亮的数码管位数。
数码管的驱动方式
- 静态显示:同时控制所有位的显示,适用于位数较少的情况。
- 动态扫描:依次刷新每一位,通过快速切换实现多位显示,节省 I/O 口资源。
代码示例
下面的代码演示了如何使用动态扫描方式控制 4 位共阳极数码管显示数字。
// 段码表(共阳极,0~9)
uint8_t segment_table[10] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// 初始化数码管引脚
void Digit_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 段选(GPIOB Pin0~Pin7)
GPIO_InitStructure.GPIO_Pin = 0x00FF;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 位选(GPIOC Pin0~Pin3)
GPIO_InitStructure.GPIO_Pin = 0x000F;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
// 延时函数
void Delay_us(uint32_t us) {
us *= 9; // 假设系统时钟为 72MHz
while (us--) {
__NOP();
}
}
// 显示函数,digits 为要显示的数字数组
void Display(uint8_t *digits) {
for (uint8_t i = 0; i < 4; i++) {
GPIO_ResetBits(GPIOC, 0x000F); // 关闭所有位选
GPIO_Write(GPIOB, segment_table[digits[i]]); // 输出段码
GPIO_SetBits(GPIOC, 1 << i); // 使能第 i 位
Delay_us(1000); // 延时 1ms
}
}
int main(void) {
Digit_Init();
uint8_t digits[4] = {1, 2, 3, 4};
while (1) {
Display(digits); // 不断刷新显示
}
}
Comments NOTHING