概述
参考3. GLB — BL602/604 参考手册(Confidential) 文档
一、使用函数操作IO口
1、IO口的操作,常用以下几个函数
//设管脚为输出模式
int bl_gpio_enable_output(uint8_t pin, uint8_t pullup, uint8_t pulldown)
//设置管脚为输入模式
int bl_gpio_enable_input(uint8_t pin, uint8_t pullup, uint8_t pulldown)
//设置管脚电平(输出模式使用)
int bl_gpio_output_set(uint8_t pin, uint8_t value)
//获取管脚电平(输入模式使用)
int bl_gpio_input_get_value(uint8_t pin)
这些函数属于hal_drv模块,因此我们需要把工程路径下的Makefile文件中的INCLUDE_COMPONENTS字段添加hal_drv
2、在aos_loop_proc函数中调用user_gpio_init,一般放在aos_loop_run()之前
这里我们创建一个GPIO的任务,间隔1秒执行LED管脚电平取反,并打印KEY管脚的电平状态
#define R_LED_PIN GLB_GPIO_PIN_17
#define G_LED_PIN GLB_GPIO_PIN_14
#define B_LED_PIN GLB_GPIO_PIN_11
#define KEY_PIN GLB_GPIO_PIN_1
/********************************************************************
*@brief GPIO任务
*@input
*@return
********************************************************************/
static void user_gpio_task(void *arg)
{
bl_gpio_enable_output(R_LED_PIN,0,0); //配置管脚为输出,不打开上下拉电阻
bl_gpio_enable_input(KEY_PIN,1,0); //配置管脚为输入,打开上拉电阻
bool flag = 0;
while(1)
{
vTaskDelay(1000/portTICK_RATE_MS);
if(flag)
{
flag = 0;
bl_gpio_output_set(R_LED_PIN,0);
}
else
{
flag = 1;
bl_gpio_output_set(R_LED_PIN,1);
}
printf("bl_gpio_input_get_value %drn",bl_gpio_input_get_value(KEY_PIN));
}
vTaskDelete(NULL);
}
/********************************************************************
*@brief GPIO初始化
*@input
*@return
********************************************************************/
void user_gpio_init()
{
xTaskCreate(user_gpio_task, "", 512, NULL, 2, NULL);
}
注意:函数bl_gpio_input_get_value只能作为输入模式时读取的才是管脚电平,如果是输出模式,则读取的都是0。
如果想在输出模式获取管脚状态时,可以获取设置寄存器的值,代码如下
uint32_t bl_gpio_output_get_value(GLB_GPIO_Type gpioPin)
{
uint32_t *p=(uint32_t *)(GLB_BASE+GLB_GPIO_OUTPUT_OFFSET+((gpioPin>>5)<<2));
uint32_t pos=gpioPin%32;
if((*p)&(1<<pos)){
return 1;
}else{
return 0;
}
}
3、GPIO中断的使用
static void gpio_irq_callback(gpio_ctx_t *pstnode)
{
//重新打开中断
bl_gpio_intmask(pstnode->gpioPin,0);
printf("gpio_irq_callbackrn");
}
/********************************************************************
*@brief GPIO任务
*@input
*@return
********************************************************************/
static void user_gpio_task(void *arg)
{
gpio_ctx_t pstnode;
pstnode.gpioPin = KEY_PIN;
pstnode.intCtrlMod = GLB_GPIO_INT_CONTROL_SYNC;
pstnode.intTrgMod = GLB_GPIO_INT_TRIG_NEG_PULSE; //下降沿中断
pstnode.gpio_handler = (void *)&gpio_irq_callback;
pstnode.arg = NULL;
pstnode.next = NULL;
bl_gpio_enable_input(pstnode.gpioPin,1,0); //配置管脚为输入,打开上拉电阻
bl_gpio_register(&pstnode); //注册中断
while(1)
{
vTaskDelay(1000/portTICK_RATE_MS);
}
vTaskDelete(NULL);
}
二、设备树使用
1、LED输出实验
1.1在aos_loop_proc函数中添加loopset_led_hook_on_looprt
1.2在aos_loop_proc函数中添加hal_gpio_init_from_dts
if (0 == get_dts_addr("gpio", &fdt, &offset)) {
hal_gpio_init_from_dts(fdt, offset);
}
1.3打开烧录工具中的bl_factory_params_IoTKitA_40M.dts,文件路径如下
添加如下代码
gpio {
#address-cells = <1>;
#size-cells = <1>;
max_num = <31>;
gpio0 {
status = "okay"; //okay or disable
pin = <11>;
feature = "led"; //led
active = "Lo"; //Hi or Lo
mode = "blink"; //blink or heartbeat or onoff
time = <500>; //duration for this mode
};
gpio1 {
status = "okay"; //okay or disable
pin = <17>;
feature = "led"; //led
active = "Lo"; //Hi or Lo
mode = "heartbeat"; //blink or heartbeat or onoff
time = <1000>; //duration for this mode
};
gpio2 {
status = "okay"; //okay or disable
pin = <14>;
feature = "led"; //led
active = "Lo"; //Hi or Lo
mode = "onoff"; //blink or heartbeat or onoff
time = <1500>; //duration for this mode
};
};
我们在上面定义了3个gpio管脚,分别是11、17、14管脚。功能是这三个管脚分别500ms、1000ms、1500ms闪烁
2、按键实验
2.1在aos_loop_proc函数中添加以下代码
if (0 == get_dts_addr("gpio", &fdt, &offset)) {
fdt_button_module_init((const void *)fdt, (int)offset);
}
2.2打开烧录工具中的bl_factory_params_IoTKitA_40M.dts,文件路径如下
添加如下代码
gpio {
#address-cells = <1>;
#size-cells = <1>;
max_num = <31>;
gpio3 {
status = "okay";
pin = <1>;
feature = "button";
active = "Lo";
mode = "multipress";
button {
debounce = <10>;
short_press_ms {
start = <100>;
end = <3000>;
kevent = <2>;
};
long_press_ms {
start = <6000>;
end = <10000>;
kevent = <3>;
};
longlong_press_ms {
start = <15000>;
kevent = <4>;
};
trig_level = "Lo";
};
hbn_use = "disable";
};
};
上面定义了IO1为按键管脚,100~3000ms是为短按,6000~10000ms是为长按,大于15000ms时为长长按
我们还需要注册按键事件,在user_gpio_init初始化时调用aos_register_event_filter注册按键事件
static void event_cb_key_event(input_event_t *event, void *private_data)
{
switch (event->code) {
case KEY_1:
{
printf("[KEY_1] [EVT] INIT DONE %lldrn", aos_now_ms());
printf("short press rn");
}
break;
case KEY_2:
{
printf("[KEY_2] [EVT] INIT DONE %lldrn", aos_now_ms());
printf("long press rn");
}
break;
case KEY_3:
{
printf("[KEY_3] [EVT] INIT DONE %lldrn", aos_now_ms());
printf("longlong press rn");
}
break;
default:
{
printf("[KEY] [EVT] Unknown code %u, %lldrn", event->code, aos_now_ms());
/*nothing*/
}
}
}
/********************************************************************
*@brief GPIO初始化
*@input
*@return
********************************************************************/
void user_gpio_init()
{
aos_register_event_filter(EV_KEY, event_cb_key_event, NULL);
}
LOG打印如下
最后
以上就是粗犷纸飞机为你收集整理的BL602 GPIO的使用的全部内容,希望文章能够帮你解决BL602 GPIO的使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复