开发者学堂课程【HaaS 物联网应用开发课程:3_5_系统中断和 GPIO 操作】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/801/detail/13830
3_5_系统中断和 GPIO 操作
内容介绍
一、中断
二、按键中断实例
三、GPIO 操作
一、中断
中断程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,CPU 暂停当前程序的运行,自动转入预先设定好的中断服务程序,处理完后,再返回原来的程序继续运行,这整个过程称为中断。
中断分类:
(1)硬件中断:实际硬件在需要通知 CPU 有特殊事件产生时候发出的信号,Timer、UART、GPIO 等硬件均可以发出硬件中断
(2)软件中断:软件(一条 CPU 指令)触发的一个信号,在各种操作系统中,系统调用的实现一般是通过触发软件中断的方式实现的。
(3)可屏蔽中断:可由程序控制是否发出中断信号的中断称为可屏蔽中断。
(4)不可屏蔽中断:不能由程序控制其屏蔽状态的中断,只要产生该中断,CPU 就一定要立即处理。
不可屏蔽中断,主要用于断电、电源故障等必须要进行立即处理的情况。中断的用途有很多,应用场景如下:
(1)系统调用;
(2)系统的时钟 tick 则是以 Timer 中断为基准进行计算;
(3)设置 UART 的配置,使其在接收数据时硬件缓存的数据量到达一定的门限值之后发出中断,串行口在接收到一定数量的数据时,也可以发出中断芯片;
(4)芯片外部模块的中断一般是通过连接到 CPU 上具有中断功能的 IO 口进行中断事件上报的;
以下 API 是阿里 OS things gpio 中断相关 API:
hal_gpio_init
初始化指定 GPIO 管脚到 IRQ 模式
hal_gpio_enable_irq
使能指定 GPIO 的中断模式,挂载中断服务函数
hal_gpio_disable_irq
清除指定 GPIO 的中断状态
hal_gpio_clear_irq
清除指定 GPIO 的中断状态
二、按键中断实例
1.代码
行为设计:将 HaaS EDU 上面的 K1按键设置为中断模式,在按下按键之后的150ms 内打印"k1 is pressed"日志。
代码如下:
#include< aos/hal/gpio.h>
Hal gpio 相关声明都存在于 gpio 点 H 中,所以需要对其进行声明。
#define EDK_BOARD_KEY1 HAL_IOMUX_PIN_P2_7
定义以上代码,连接按键:
/* define dev */
gpio_dev_t k1;
/*pressed flag */*K1按健按下的标志位*/int k1_pressed = 0;
/*中断处理程序中将 k1_pressed 设置为1,代表检测到 K1按下的事件*/
以下为中断处理函数,中断处理函数中将变量设置为1:
void k1_handler(void *arg)
{
k1_pressed = 1;
}
在程序当中呼叫 Hal gpio init,将 Gpio P2.7将其设置为中断模式:
int application_start(int argc,char *argv[]){
int ret = -1;
/*IRQ pin config*/
/*中断 GPIO 配置*/
k1.port = EDK_BOARD_KEY1;
/* set as interrupt mode */
/*设置为中断模式*/
k1.config = IRQ_MODE;
/*configure GPIO with the given settings*/
/*呼叫hal_gpio_init对K1进行初始化*/
ret = hal_gpio_init(&k1);
if (ret != 0) {
printf("k1 init error !in");
}
/* enable interrupt on K1*/
/*开启K1对应的中断*/
中断触发条件为上升沿或下降沿有效。
ret = hal_gpio_enable_irq(&k1,IRO_TRIGGER_BOTH_EDGES,
k1_handler, NULL);
if ( ret != 0) {
printf("gpio irq enable error !in"");
}
/* if k1 is pressed,print “k1 is pressed !"*/
/*检测到k1_pressed 标志位1,打印"k1 is pressed !"*/
首先判断变量是否为1,如果为1就打印相应信息,将其清零。
while(1) {
if (k1_pressed == 1){
k1_pressed = ;
printf("k1 is pressed !n"");
}
/* sleep 100ms,must be shorter than 150ms according to experiment's target */
/*休眠100ms,必须要短于158ms,确保在k1_pressed在中断处理程序中被设置成1后能够在150ms 内检测到此K1被按下的事件*/
aos_msleep( 100);
};
}
按照如上逻辑,在K1按下之后,最晚100毫秒之内一定能检测到K1变量为一。
2.演示
以 new comp 为例,先进入到其中。将中断相关的代码放入 gpio 中,入口函数是 new comp gpio test init。首先设置为中断模式,其次呼叫初始化,开启中断,然后检测标志位是否为1。如果为1将其变为0,然后打印信息,最后休眠100毫秒。在中断处理函数中,只需要设置 k1 presds=1。
按照如上代码,在按下 K1之后,就会执行 K1 pressed=1,在100毫秒之内,检测到变量为1,进入中断。将gpio test.C,放入 new comp 的 make file 中。
在 new comp Gpio init 中,呼叫 new comment gpio test init。在 Hello World.C 的 application Start中,调用new comp init,所以可以直接编译 Hello World 应用程序。烧录之后,系统启动会自动将中断注册。
烧录完成之后,查看行为,打开串口,按下按键,结果如下:
三、GPIO 操作
1.简介
GPIO 是 General-purpose input/output 的缩写,通用输入输出功能。计算机系统和外部元件进行通信除了使用USB等各种总线外,最重要的通讯方式之一就是通过 gpio。
输入功能,通过 GPIO 可以读取外部设备的状态信号处于高电平还是低电平。输出功能,通过 GPIO 可以输出高低电平信号控制外部设备的行为。芯片有40个 gpio,分为P0 P1 P2 P3 P4五组,每组8个,所有 gpio 都是功能复用,每个 gpio 有四到六种不同功能使用。以下为 AliOS Things GPIO 相关 API:
hal_gpio_init
初始化指定 GPIO 管脚
hal_gpio_output_high
使指定 GPIO 输出高电平
hal_gpio_output_low
使指定 GPIO 输出低电平
hal_gpio_output_toggle
使指定 GPIO 输出翻转,如果此时是高电平状态,将其翻转为低电平。如果此时是低电平状态,将其翻转为高电平。
hal_gpio_input_get
获取指定 GPIO 管脚的输入值
hal_gpio_finalize
关闭指定 GPIO0
2.案例
实验设计:利用 GPIO HAL API 去控制 GPIO 间歇性反转输出极性,从而控制 GPIO 口所接 LED 进行闪烁。代码如下:
include <aos/hal/gpio.h>
#define GPIO_LED_I0 36
//对应 Haas108e 的 P4_4,连接到 HaaS EDU 的 L1指示灯
/* define dev */
gpio_dev_t led;
int application_start(int argc, char *argv [])
int ret = -1;
/* gpio port config*/
led.port = GPIO_LED_I0;
/* set as output mode*/
led.config = OUTPUT_PUSH_PULL;
//开启 GPIO push 功能
/* configure GPIO with the given settings*/
ret = hal_gpio_init(&led) ;
//初始化 GPIO36
if (ret != 0) {
printf("gpio init error !in");
/* output high */
hal_gpio_output_high(&led);
//拉高 GPIO36
/* output low */
hal_gpio_output_low(&led);
//拉低 GPIO36
/*toggle the LED every 1s */
while(1) {
/*toggle output */
hal_gpio_output_toggle(&led);
//控制 GPIO36输出极性进行反转
/* sleep 1000ms*/
aos_msleep( 1000) ;
//等待1秒钟
};
}
3.演示
使用 new comp 组件,测试代码放入 gpio test.C 中。 函数入口是 new comp gpio LED test init。进入函数之后,会先配置 gpio36呼叫 gpio36。
在最后 while 循环中,每隔1秒钟控制 gplo36极性反转。在 new comment init 中,呼叫 gpio LED test 函数。编译完成之后,执行 upload 进行烧录。实验结果是,红灯周期闪烁,每隔1秒闪烁一次。