Hi3861的Micropython移植之Pin

Hi3861的Micropython移植之Pin

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

​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) },

Hi3861的Micropython移植之Pin

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 = %drn",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 = %drn",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("%srn","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 = %drn",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 Haoqixingrn")
key_0.irq(handler=func,trigger=Pin.IRQ_RISING)

5、总结

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

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

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

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

Hi3861的Micropython移植之Pin

文章版权声明

 1 原创文章作者:7739,如若转载,请注明出处: https://www.52hwl.com/94706.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年1月16日 下午10:20
下一篇 2024年1月16日 下午10:20