Hi3861的Micropython移植之Pin

系统 OpenHarmony
本文介绍Micropython中的Pin接口使用,也就是GPIO接口的使用。

​想了解更多内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://ost.51cto.com​

1、打开Pin的编译

需要将MICROPY_PY_PIN配置成1,参加编译。在modmachine.c文件中的machine_module_globals_table数据中会包含。

{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },

2、移植Pin的接口函数

需要包含openharmony中的gpio的头文件,其中包含了GPIO的操作函数。

#include "hi_gpio.h"

定义可以被引用的GPIO的名字。

typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
int pin;
int ble_ex;
mp_obj_t pin_isr_cb;
} machine_pin_obj_t;
STATIC machine_pin_obj_t machine_pin_obj[] = {
{{&machine_pin_type},1,1,MP_OBJ_NULL},
{{&machine_pin_type},2,1,MP_OBJ_NULL},
{{&machine_pin_type},3,1,MP_OBJ_NULL},
{{&machine_pin_type},4,1,MP_OBJ_NULL},
{{&machine_pin_type},101,1,MP_OBJ_NULL},
{{&machine_pin_type},102,1,MP_OBJ_NULL},
};

然后移植初始化定义函数mp_pin_make_new。

mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
int wanted_pin = mp_obj_get_int(args[0]);
const machine_pin_obj_t *self = NULL;
/*
if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) {
self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin];
}*/
for(int i=0;i< MP_ARRAY_SIZE(machine_pin_obj);i++)
{
if(wanted_pin == machine_pin_obj[i].pin)
{
self = (machine_pin_obj_t *)&machine_pin_obj[i];
}
}
if (self == NULL || self->base.type == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
}
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return MP_OBJ_FROM_PTR(self);
}
// pin.init(mode, pull=None, *, value)
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_mode, ARG_pull, ARG_value };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get io mode
uint mode = args[ARG_mode].u_int;
switch(mode) {
case GPIO_MODE_IN: {
mode = IOT_GPIO_DIR_IN;
break;
}
case GPIO_MODE_OUT: {
mode = IOT_GPIO_DIR_OUT;
break;
}
default:{
mode = IOT_GPIO_DIR_OUT;
break;
}
}
if(self->ble_ex == 0)
{
IoTGpioInit(self->pin);
IoTGpioSetDir(self->pin, mode);
hi_io_set_pull(self->pin,1);
hi_io_set_func(self->pin,0);//设置IO口模式
}
else
{
set_io_attribute(self->pin,mode);
}
return mp_const_none;
}

定义完Pin之后,需要获取IO的状态或者设置IO的状态。

// pin.value([value])
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);

在micropython的函数定义中,MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN关键词用于定义函数可以接受的参数的范围。根据定义,如果该函数中参数为空,则为获取参数,参数有数值,则为设置IO的高低。

// fast method for getting/setting pin value
STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
machine_pin_obj_t *self = self_in;
//printf("machine_pin_call n_args = %d\r\n",n_args);
if (n_args == 0) {
if(self->ble_ex == 0)
{
hi_gpio_value gpio_val = HI_GPIO_VALUE1;
IoTGpioGetInputVal(self->pin,&gpio_val);
return mp_obj_new_bool(gpio_val);
}
else
{
int val = 0;
get_io_value(self->pin,&val);
return mp_obj_new_bool(val);
}
} else {
if(self->ble_ex == 0)
{
IoTGpioSetOutputVal(self->pin, mp_obj_is_true(args[0]));
}
else
{
set_io_value(self->pin, mp_obj_is_true(args[0]));
}
return mp_const_none;
}
}

3、中断模式

想要获取IO的高低电平,轮训模式是其中一种,但是必然离不开IO口的中断模式。micropython也是支持中断模式的。

STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {    
enum { ARG_handler, ARG_trigger};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = PIN_IRQ_MODE_RISING} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
printf("machine_pin_irq self int = %d\r\n",self->pin);
if (n_args > 1 || kw_args->used != 0) {
// configure irq
mp_obj_t handler = args[ARG_handler].u_obj;
if (handler != mp_const_none)
{
self->pin_isr_cb = handler;
}
else
{
printf("%s\r\n","handler = mp_const_none.");
}
uint32_t trigger = args[ARG_trigger].u_int;
IoTGpioRegisterIsrFunc(self->pin,1,trigger,machine_pin_isr_handler,(void*)self);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);

machine_pin_irq用于设置中断回调函数以及中断触发的条件,当IO中触发中断之后,会调用注册的函数machine_pin_isr_handler。

STATIC void machine_pin_isr_handler(void *arg) {
machine_pin_obj_t *self = arg;
printf("machine_pin_isr_handler = %d\r\n",self->pin);
mp_sched_schedule(self->pin_isr_cb, MP_OBJ_FROM_PTR(self));
}

然后调用mp_sched_schedule(self->pin_isr_cb, MP_OBJ_FROM_PTR(self));来实现回调函数的引用。后续会专门介绍mp_sched_schedule是如何工作的。

4、python编程驱动IO

(1)实现LED灯闪烁。

import time
from machine import Pin
led = Pin(12, Pin.OUT)
while True:
led.value(0) # turn off
time.sleep(0.5)
led.value(1) # turn on
time.sleep(0.5)

(2)IO的电平获取。

from machine import Pin
p_in = Pin(1,Pin.IN)
print(p_in.value()) # get value, 0 or 1

(3)IO的中断。

from machine import Pin
key_0 = Pin(12, Pin.IN)
def func(v):
print("Hello Haoqixing\r\n")
key_0.irq(handler=func,trigger=Pin.IRQ_RISING)

5、总结

IO口的使用是我们学习一款单片机的开始,通过python来驱动IO,使得我们学习的成本进一步降低。移植micropython到hi3861的过程,也是学习C和Python的一个过程。后续会持续的更新这方便的内容。

​想了解更多内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://ost.51cto.com​

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2020-10-16 09:50:37

Hi3861WiFi热点

2023-05-26 16:07:14

Hi3861Wifi模块

2021-09-09 10:06:09

鸿蒙HarmonyOS应用

2022-03-07 15:05:58

HTTPHi3861数据解析

2020-10-14 09:41:02

Hi3861GPIO点灯

2020-12-02 11:48:05

TFTP

2022-05-30 15:21:27

Hi3861TCP通信

2020-11-02 12:07:11

鸿蒙 GPIO

2022-05-09 14:22:40

Hello WorlMNIST鸿蒙

2020-12-17 10:02:16

鸿蒙Hi3861开发板

2021-06-18 10:02:10

鸿蒙HarmonyOS应用

2020-10-12 09:36:04

鸿蒙

2020-10-28 10:03:43

Hi3861 GPIO点灯按键

2022-03-04 15:51:43

TTS功能Hi3861科大讯飞

2022-04-12 11:07:11

Hi3861鸿蒙操作系统

2021-02-02 15:52:17

鸿蒙HarmonyOS应用开发

2021-06-10 09:25:39

鸿蒙HarmonyOS应用

2021-06-03 14:21:44

鸿蒙HarmonyOS应用

2021-10-08 10:23:07

鸿蒙HarmonyOS应用

2020-11-06 10:15:16

HiBurn
点赞
收藏

51CTO技术栈公众号