这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【雅特力|Zephyr】6、AT32F423Zephyr之GPIO按键中断移植指

共1条 1/1 1 跳转至

【雅特力|Zephyr】6、AT32F423Zephyr之GPIO按键中断移植指南

高工
2026-03-01 21:41:08     打赏
 一、移植背景
本文档记录将 AT32F423 的 GPIO 按键中断功能移植到 Zephyr RTOS 的完整过程。移植完成后,按键使用 Zephyr 标准 GPIO 中断 API,支持按下和松开两种中断触发方式。二、硬件连接
开发板: AT32F423-START按键: PA0(Wakeup 按键)

电路特性: 外部下拉电阻到地,按下时 PA0 为高电平

image.png


三、移植过程3.1 设备树修复问题: 设备树中 GPIO 地址不正确根据 AT32 官方头文件 `at32f423.h`,GPIO 实际地址为:
- GPIOA: 0x40020000
- GPIOB: 0x40020400
- GPIOC: 0x40020800
- GPIOD: 0x40020C0
修复文件: `zephyr/dts/arm/at32/at32f423.dtsi`
- gpio_a: gpio@40021000 {
-     reg = <0x40021000 0x400>;
+ gpio_a: gpio@40020000 {
+     reg = <0x40020000 0x400>;
 3.2 GPIO 驱动完善问题: AT32 GPIO 驱动缺少中断配置功能需要实现以下函数:- `gpio_at32_pin_interrupt_configure()` - 配置 GPIO 引脚中断- EXTI 中断处理函数- EXTI 源选择配置
修复文件: `zephyr/drivers/gpio/gpio_at32.c`
 3.2.1 添加 EXTI 寄存器定义
#define EXINT_BASE     0x40013C00
#define EXINT_INTEN    (*(volatile uint32_t *)(EXINT_BASE + 0x00))
#define EXINT_EVTEN    (*(volatile uint32_t *)(EXINT_BASE + 0x04))
#define EXINT_POLCFG1  (*(volatile uint32_t *)(EXINT_BASE + 0x08))
#define EXINT_POLCFG2  (*(volatile uint32_t *)(EXINT_BASE + 0x0C))
#define EXINT_INTSTS   (*(volatile uint32_t *)(EXINT_BASE + 0x14))
3.2.2 实现引脚中断配置
static int gpio_at32_pin_interrupt_configure(const struct device *port,
                       gpio_pin_t pin,
                       enum gpio_int_mode mode,
                       enum gpio_int_trig trig)
{
    // 1. 获取端口索引
    // 2. 配置 EXTI 源选择(类似 STM32 的 AFIO)
    // 3. 配置触发边沿
    // 4. 使能 EXTI 中断
    // 5. 使能 NVIC 中断
}
3.2.3 添加 EXTI 中断处理
ISR_DIRECT_DECLARE(gpio_exti0_isr)
{
    gpio_at32_exti_isr(0);
    ISR_DIRECT_PM();
    return 0;
}
3.3 应用层代码
文件: `test_at32/main.c`
/* 定义按键引脚 */
#define BUTTON_PIN  0
/* 按键回调函数 */
static struct gpio_callback button_cb_data;
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    int pressed = gpio_pin_get(gpioa_port, BUTTON_PIN);
    if (pressed > 0) {
        printk("BUTTON: PRESSED\n");
    } else {
        printk("BUTTON: RELEASED\n");
    }
}
int main(void)
{
    // 配置按键为输入
    ret = gpio_pin_configure(gpioa_port, BUTTON_PIN, GPIO_INPUT);
    // 配置双边沿中断
    ret = gpio_pin_interrupt_configure(gpioa_port, BUTTON_PIN,
                                        GPIO_INT_EDGE_BOTH);
    // 初始化并注册回调
    gpio_init_callback(&button_cb_data, button_pressed, BIT(BUTTON_PIN));
    gpio_add_callback(gpioa_port, &button_cb_data);
    while (1) {
        k_sleep(K_FOREVER);
    }
}
四、关键问题与解决
 问题 1: GPIO 地址错误
现象: `gpio_pin_get()` 始终返回 0原因: 设备树中 GPIO 基地址错误解决: 修正为 0x40020000(根据 AT32 官方头文件) 问题 2: 回调未触发现象: EXTI 中断触发,但回调函数未执行原因:1. EXTI 源选择未配置2. ISR 中无法通过 `device_get_binding()` 获取设备解决:1. 添加 EXTI_EXINTx 寄存器配置2. 使用全局数组存储设备指针
 问题 3: 按键状态读取错误现象: 中断触发后读取的状态不正确原因: 中断清除后读取的 IDT 值已被清除解决: 在清除中断标志前先读取 GPIO 状态 五、使用方法5.1 Shell 命令
# 查询按键状态
uart:~$ button
Button (PA0): RELEASED
# 控制 LED
uart:~$ led on 2
LED2 ON
uart:~$ led off 2
LED2 OFF
uart:~$ led toggle 3
uart:~$ led status
5.2 中断触发
按下按键: 打印 `BUTTON: PRESSED`松开按键: 打印 `BUTTON: RELEASED`
 六、代码修改汇总
文件修改内容
zephyr/dts/arm/at32/at32f423.dtsi修复 GPIO 地址
zephyr/drivers/gpio/gpio_at32.c实现 `pin_interrupt_configure`、EXTI 中断处理
test_at32/main.c按键初始化和回调处理

七、总结
本次移植成功实现了 AT32F423 的 GPIO 按键中断功能,完全使用 Zephyr 标准 API:- `gpio_pin_configure()` - 配置 GPIO- `gpio_pin_interrupt_configure()` - 配置中断- `gpio_pin_get()` - 读取引脚状态- `gpio_init_callback()` / `gpio_add_callback()` - 管理回调
这使得应用层代码具有良好的可移植性,与其他 Zephyr 支持的芯片保持一致。





关键词: Zephyr     AT32F423     按键     中断    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]