目录
创建工程:
代码分析:
1.头文件包含:
2.宏定义:
3.中断服务程序(ISR):
清除中断标志:
处理 LED 状态切换:
处理用户按键状态:
处理其他情况:
4.void test_gpio_input_interrupt(void):
打印提示信息:
初始化 LED GPIO:
配置 GPIO 引脚为输入模式:
配置中断触发类型:
启用 GPIO 中断:
设置中断优先级:
进入低功耗模式:
5.void test_gpio_toggle_output(void):
打印提示信息:
初始化 LED GPIO:
循环切换 LED 状态:
打印测试完成信息:
6.int main(void)
初始化板级硬件:
测试 GPIO 输出状态切换:
测试 GPIO 输入中断:
进入无限循环:
运行现象:
创建工程:
首先还是在HPM SDK里面创建工程选项如下图:
代码分析:
/*
* Copyright (c) 2021 HPMicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "board.h"
#include "hpm_gpio_drv.h"
#define GPIO_TOGGLE_COUNT 5
void isr_gpio(void)
{
gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
BOARD_APP_GPIO_PIN);
#ifdef BOARD_LED_GPIO_CTRL
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN);
printf("toggle led pin output\n");
#else
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
if (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == false) {
printf("user key pressed\n");
} else {
printf("user key released\n");
}
#else
printf("user key pressed\n");
#endif
#endif
}
SDK_DECLARE_EXT_ISR_M(BOARD_APP_GPIO_IRQ, isr_gpio)
void test_gpio_input_interrupt(void)
{
gpio_interrupt_trigger_t trigger;
printf("input interrupt\n");
#ifdef BOARD_LED_GPIO_CTRL
printf("user led will be switched on off based on user switch\n");
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN);
#endif
gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
BOARD_APP_GPIO_PIN);
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
trigger = gpio_interrupt_trigger_edge_both;
#else
trigger = gpio_interrupt_trigger_edge_falling;
#endif
gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
BOARD_APP_GPIO_PIN, trigger);
gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX,
BOARD_APP_GPIO_PIN);
intc_m_enable_irq_with_priority(BOARD_APP_GPIO_IRQ, 1);
while (1) {
__asm("wfi");
}
}
#ifdef BOARD_LED_GPIO_CTRL
void test_gpio_toggle_output(void)
{
printf("toggling led %u times in total\n", GPIO_TOGGLE_COUNT);
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN);
gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN, board_get_led_gpio_off_level());
for (uint32_t i = 0; i < GPIO_TOGGLE_COUNT; i++) {
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN);
board_delay_ms(500);
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX,
BOARD_LED_GPIO_PIN);
board_delay_ms(500);
printf("toggling led %u/%u times\n", i + 1, GPIO_TOGGLE_COUNT);
}
}
#endif
int main(void)
{
board_init();
board_init_gpio_pins();
printf("gpio \n");
#ifdef BOARD_LED_GPIO_CTRL
test_gpio_toggle_output();
#endif
test_gpio_input_interrupt();
while (1);
return 0;
}
1.头文件包含:
#include "board.h"
#include "hpm_gpio_drv.h"
这里包含了与嵌入式系统板级支持和GPIO驱动相关的头文件。
2.宏定义:
#define GPIO_TOGGLE_COUNT 5
这个宏定义表示在测试中要切换LED状态的次数。
3.中断服务程序(ISR):
void isr_gpio(void) {
// 处理GPIO中断
}
SDK_DECLARE_EXT_ISR_M(BOARD_APP_GPIO_IRQ, isr_gpio)
这定义了一个GPIO中断服务程序(ISR),当GPIO中断发生时执行。在中断服务程序中,通过 gpio_clear_pin_interrupt_flag
函数清除中断标志,然后根据硬件配置,切换LED状态或输出用户按键的状态。
清除中断标志:
gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);
处理 LED 状态切换:
#ifdef BOARD_LED_GPIO_CTRL
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
printf("toggle led pin output\n");
处理用户按键状态:
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
if (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == false) {
printf("user key pressed\n");
} else {
printf("user key released\n");
}
如果硬件支持双边沿触发的中断(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT
宏被定义且等于 1),则通过 gpio_read_pin
函数检查用户按键的状态。如果按键被按下,则打印 "user key pressed";如果按键被释放,则打印 "user key released"。
处理其他情况:
#else
printf("user key pressed\n");
#endif
如果没有硬件支持双边沿触发的中断,直接打印 "user key pressed"。
4.void test_gpio_input_interrupt(void):
void test_gpio_input_interrupt(void) {
// 测试GPIO输入中断
}
打印提示信息:
printf("input interrupt\n");
打印一条提示消息,指示该函数用于测试 GPIO 的输入中断功能。
初始化 LED GPIO:
#ifdef BOARD_LED_GPIO_CTRL
printf("user led will be switched on off based on user switch\n");
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
#endif
定义了 BOARD_LED_GPIO_CTRL
宏,表示存在 LED 的 GPIO 控制器,那么打印一条消息提示 LED 的状态将会根据用户开关的状态进行切换,并通过 gpio_set_pin_output
函数将 LED 的 GPIO 引脚设置为输出模式。
配置 GPIO 引脚为输入模式:
gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);
通过调用 gpio_set_pin_input
函数将指定的 GPIO 引脚配置为输入模式。
配置中断触发类型:
#if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
trigger = gpio_interrupt_trigger_edge_both;
#else
trigger = gpio_interrupt_trigger_edge_falling;
#endif
gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN, trigger);
根据硬件支持的中断触发类型,配置 GPIO 引脚的中断触发类型。如果支持双边沿触发中断,则设置 trigger
为 gpio_interrupt_trigger_edge_both
,否则设置为 gpio_interrupt_trigger_edge_falling
。
启用 GPIO 中断:
gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN);
通过调用 gpio_enable_pin_interrupt
函数启用 GPIO 引脚的中断。
设置中断优先级:
intc_m_enable_irq_with_priority(BOARD_APP_GPIO_IRQ, 1);
通过调用 intc_m_enable_irq_with_priority
函数,设置与 GPIO 中断相关的中断优先级。
进入低功耗模式:
while (1) {
__asm("wfi");
}
进入一个无限循环,并在循环中调用 __asm("wfi");
进入等待中断(WFI)指令,使处理器进入低功耗模式,等待 GPIO 中断的发生。
在这个测试函数中,主要目的是配置和启用 GPIO 的输入中断,并在进入低功耗模式后等待中断的发生。当 GPIO 中断触发时,与中断相关的处理函数 isr_gpio
将被调用。这个测试函数用于验证嵌入式系统中 GPIO 输入中断的正常工作。
5.void test_gpio_toggle_output(void):
打印提示信息:
printf("toggling led %u times in total\n", GPIO_TOGGLE_COUNT);
打印一条消息,指示该函数将会切换 LED 总共 GPIO_TOGGLE_COUNT
次。
初始化 LED GPIO:
gpio_set_pin_output(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, board_get_led_gpio_off_level());
使用 gpio_set_pin_output
函数将 LED 的 GPIO 引脚设置为输出模式,并使用 gpio_write_pin
函数设置 LED 的初始状态,根据板级支持的函
printf("toggling led test completed\n");
数 board_get_led_gpio_off_level
来确定 LED 的初始状态。
循环切换 LED 状态:
for (uint32_t i = 0; i < GPIO_TOGGLE_COUNT; i++) {
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
board_delay_ms(500);
gpio_toggle_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN);
board_delay_ms(500);
printf("toggling led %u/%u times\n", i + 1, GPIO_TOGGLE_COUNT);
}
在一个循环中,使用 gpio_toggle_pin
函数切换 LED 的输出状态,然后通过 board_delay_ms
函数延迟 500 毫秒,再次切换状态,以模拟 LED 的开关操作。在每次切换之后,打印一条消息,显示切换的次数。
打印测试完成信息:
printf("toggling led test completed\n");
总体而言,test_gpio_toggle_output
函数用于测试嵌入式系统中 GPIO 输出状态切换的功能。通过在循环中切换 LED 的状态,它模拟了 LED 的开关操作,并通过打印相关信息,显示切换的次数和测试完成的消息。
6.int main(void)
int main(void)
函数是嵌入式系统中的主函数,它是程序的入口点。以下是 main
函数的主要步骤的解释:
初始化板级硬件:
board_init();
board_init_gpio_pins();
调用 board_init
函数和 board_init_gpio_pins
函数,用于初始化板级硬件,包括系统时钟、GPIO 等。
测试 GPIO 输出状态切换:
#ifdef BOARD_LED_GPIO_CTRL
test_gpio_toggle_output();
#endif
定义了 BOARD_LED_GPIO_CTRL
宏,表示存在 LED 的 GPIO 控制器,那么调用 test_gpio_toggle_output
函数,测试 GPIO 输出状态切换功能。
测试 GPIO 输入中断:
调用 test_gpio_input_interrupt
函数,测试 GPIO 输入中断功能。
进入无限循环:
main
函数的主要作用是初始化嵌入式系统的硬件环境,然后进行 GPIO 功能的测试。具体测试的内容包括 GPIO 输出状态切换和 GPIO 输入中断。在这个例子中,通过宏的定义来判断是否存在 LED 的 GPIO 控制器,以确定是否执行 GPIO 输出状态切换的测试。无论是否进行 GPIO 输出状态切换测试,都会执行 GPIO 输入中断的测试。程序最终进入一个无限循环,保持运行状态。
运行现象:
-
支持双沿触发模式的芯片,工程配置的是双沿触发模式,每次按键按下和释放都会翻转一次LED状态,并打印两次LED切换输出。
-
当工程正确运行后,可以观察到LED闪烁5次,之后按下GPIO按键(请确认具体开发板 按键 部分描述)可以翻转LED的状态,串口终端会输出如下信息:
toggling led 5 times in total toggling led 1/5 times toggling led 2/5 times toggling led 3/5 times toggling led 4/5 times toggling led 5/5 times input interrupt user led will be switched on off based on user switch toggle led pin output toggle led pin output