基于亚博K210开发板——独立按键中断实验
开发板
亚博K210开发板
实验目的
主要实现K210 的独立按键以及中断的功能
实验准备
实验元件
板载的独立按键 BOOT、RGB 灯
元件特性
独立按键 BOOT 按下时 IO 口为低电平,松开为高电平
硬件连接
此K210开发板出厂默认已经焊接好BOOT按键和RGB灯。按键连接的引脚为IO16。RGB 灯 R 连接的是 IO6,G 连接的是 IO7, B 连接的是 IO8
SDK 中对应 API 功能
以plic.h头文件介绍
PLIC 可以将任一外部中断源单独分配到每个 CPU 的外部中断上。这提供了强大的灵活性,能适应不同的应用需求。PLIC 模块可以设置中断回调函数,当触发中断时,会自动运行中断回调函数,并且可以配置中断优先级。
• plic_init:PLIC 初始化外部中断。
• plic_irq_enable:使能外部中断。
• plic_irq_disable:禁用外部中断。
• plic_set_priority:设置中断优先级。
• plic_get_priority:获取中断优先级。
• plic_irq_register:注册外部中断函数。
• plic_irq_deregister:注销外部中断函数。
实验原理
BOOT 按键按下的时候会把电平拉低,松开的时候会把电平拉高,只需要检测BOOT 按键的 IO 口的电平,如果是按下则会产生下降沿,松开会产生上升沿,以此的方式来检测并触发系统的中断,然后控制 RGB 灯亮或者灭。
实验过程
- 首先根据上面的硬件连接引脚图,K210 的硬件引脚和软件功能使用的是FPIOA映射关系。这里要注意的是程序里操作的都是软件引脚,所以需要先把硬件引脚映射成软件 GPIO 功能,操作的时候直接操作软件 GPIO即可。
// 硬件IO口,与原理图对应
#define PIN_RGB_R (6)
#define PIN_RGB_G (7)
#define PIN_RGB_B (8)#define PIN_KEY (16)/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define RGB_R_GPIONUM (0)
#define RGB_G_GPIONUM (1)
#define RGB_B_GPIONUM (2)#define KEY_GPIONUM (3)/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_RGB_R (FUNC_GPIOHS0 + RGB_R_GPIONUM)
#define FUNC_RGB_G (FUNC_GPIOHS0 + RGB_G_GPIONUM)
#define FUNC_RGB_B (FUNC_GPIOHS0 + RGB_B_GPIONUM)#define FUNC_KEY (FUNC_GPIOHS0 + KEY_GPIONUM)
void hardware_init(void)
{// fpioa映射fpioa_set_function(PIN_RGB_R, FUNC_RGB_R);fpioa_set_function(PIN_RGB_G, FUNC_RGB_G);fpioa_set_function(PIN_RGB_B, FUNC_RGB_B);fpioa_set_function(PIN_KEY, FUNC_KEY);
}
- 第二部需要初始化外部中断服务,并且使能全局中断。如果没有这一步操作,系统的中断就不会运行,所以也不会调用中断回调函数。
/* 外部中断初始化 */
plic_init();
/* 使能全局中断 */
sysctl_enable_irq();
- 在使用 RGB 灯前需要初始化,也就是把 RGB 灯的软件 GPIO 设置为输出模式
void init_rgb(void)
{/* 设置RGB灯的GPIO模式为输出 */gpiohs_set_drive_mode(RGB_R_GPIONUM, GPIO_DM_OUTPUT);gpiohs_set_drive_mode(RGB_G_GPIONUM, GPIO_DM_OUTPUT);gpiohs_set_drive_mode(RGB_B_GPIONUM, GPIO_DM_OUTPUT);/* 关闭RGB灯 */rgb_all_off();
}
- 然后关闭 RGB 灯,同样是设置 RGB 灯的 GPIO 为高电平则可以让 RGB 灯熄灭
void rgb_all_off(void)
{gpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_HIGH);gpiohs_set_pin(RGB_G_GPIONUM, GPIO_PV_HIGH);gpiohs_set_pin(RGB_B_GPIONUM, GPIO_PV_HIGH);
}
- 使用 BOOT 按键同样需要初始化,设置 BOOT 键为上拉输入模式,设置按键的 GPIO 电平触发模式为上升沿和下降沿,也可以设置单上升沿或单下降沿等,设置 BOOT 按键的中断回调函数为key_irq_cb,参数为 g_count, g_count 是一个全局 uint32_t 变量,功能是记录电平触发的次数。
uint32_t g_count;
void init_key(void)
{/* 设置按键的GPIO模式为上拉输入 */gpiohs_set_drive_mode(KEY_GPIONUM, GPIO_DM_INPUT_PULL_UP);/* 设置按键的GPIO电平触发模式为上升沿和下降沿 */gpiohs_set_pin_edge(KEY_GPIONUM, GPIO_PE_BOTH);/* 设置按键GPIO口的中断回调 */gpiohs_irq_register(KEY_GPIONUM, 1, key_irq_cb, &g_count);
}
- 每次 BOOT 按下或者松开都会触发中断函数 key_irq_cb,在中断里先读取当前按键的状态,保存到 key_state 中,并且通过串口打印出当前按键的状态,这里只是为了调试才在中断中打印信息的,在后续的开发中不建议这样操作。由于 ctx 为 void 型指针,void 型指针表示不指定指针类型,所以我们需要新建一个 uint32_t 类型的指针 tmp 指向它,然后每次进中断 tmp 所指向的值自动加 1,也就是 g_count 的值加 1。最后是判断按键的状态,当按键为按下时,点亮红灯,当按键为松开时,闭红灯。
int key_irq_cb(void* ctx)
{gpio_pin_value_t key_state = gpiohs_get_pin(KEY_GPIONUM);/* 这里只是为了测试才在中断回调打印数据,正常情况下是不建议这么做的。*/printf("IRQ The PIN is %d\n", key_state);uint32_t *tmp = (uint32_t *)(ctx);printf("count is %d\n", (*tmp)++);if (!key_state)gpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_LOW);elsegpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_HIGH);return 0;
}
- 最后是一个 while(1)循环,这个是必须的,否则系统就会退出,不再运行。
int main(void)
{// 硬件引脚初始化hardware_init();/* 外部中断初始化 */plic_init();/* 使能全局中断 */sysctl_enable_irq();// 初始化RGB灯init_rgb();// 初始化按键keyinit_key();while (1);return 0;
}
- 编译调试,烧录运行
进入自己项目 build目录,运行以下命令编译。
cmake .. -DPROJ=watchdog -G "MinGW Makefiles"
make
编译完成后,在 build 文件夹下会生成 watchdog.bin 文件。使用type-C 数据线连接电脑与 K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到 K210 开发板上。
实验现象
烧录完成固件后,系统会弹出一个终端界面,如果没有弹出终端界面的可以打开串口助手显示调试内容。打开电脑的串口助手,选择对应的 K210 开发板对应的串口号,波特率设置为 115200,然后击打开串口助手。注意还需要设置一下串口助手的 DTR 和 RTS。在串口助手底部此时的 4.DTR 和 7.RTS 默认是红色的,点击 4.DTR 和 7.RTS,都设置为绿色,然后按一下 K210 开发板的复位键。
按下 BOOT 按键不松开,可以看到 RGB 亮红灯,并且串口助手上显示 IRQ The PIN is 0 count is 0,松开的时候会显示 IRQ The PIN is 1 count is 1,每次按下或松开 count 的值都自动加 1。
实验总结
- BOOT 按键与 RGB 同样适用 GPIOHS 的函数,只是按键使用输入模式,RGB使用输出模式。
- 使用外部中断前需要先初始化 PLIC 以及使能全局中断服务。
- 在中断回调函数中可以传入一个参数,参数类型可以传入自己需要的类型。