stm32-GPIO使用

预计阅读时间: 6 分钟 2150 次阅读 1237 字 最后更新于 2024-11-17 硬件


通用目的输入输出口(GPIO)

概述

GPIO(General Purpose Input/Output)是微控制器中最基本的外设,用于与外部设备进行数字信号的输入和输出。STM32F103 的 GPIO 具有丰富的功能,可配置为多种模式,满足不同的应用需求。

GPIO 的主要特性

  • 端口多样:STM32F103 提供了 GPIOA 到 GPIOG 共 7 个 GPIO 端口。
  • 多种模式
    • 输入模式:浮空输入、上拉输入、下拉输入、模拟输入。
    • 输出模式:推挽输出、开漏输出。
    • 复用功能模式:用于外设功能引脚。
  • 速度可调:输出速度可设置为 2MHz、10MHz、50MHz。

GPIO 的配置步骤

  1. 使能 GPIO 时钟:在使用 GPIO 之前,必须先使能对应的时钟。
  2. 配置 GPIO 模式:设置引脚的输入/输出模式、速度、上拉/下拉等属性。
  3. 读写 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 位递减计数器,可用于产生精确的延时或定时中断。

特点

  • 硬件支持:无需额外的外设配置,直接使用内核提供的功能。
  • 精确性高:基于系统时钟,延时时间精确稳定。

使用方法

  1. 配置重装载值:设置定时器的计数初值。
  2. 启动计数:设置控制寄存器开始计数。
  3. 检测计数标志:等待计数完成或中断触发。

代码示例

下面的代码演示了如何使用 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);  // 不断刷新显示
    }
}
  • alipay_img
  • wechat_img
最后更新于 2024-11-17