• [openmv]添加用户micropython底层硬件接口


    添加python的C接口

    参考地址
    src/micropython/examples/usercmodule/cexample中有添加示例,但是在src/omv中也是可以添加自己的module,这里的omv表示openmv缩写。
    根据在src/omv/modules下的micropython.mk凡是只要在src/omv/modules的*.c文件都会被编译成模块。那么接下来添加自己的模块:
    在改文件夹创建px.c

    // 包含python得API
    #include "py/runtime.h"
    
    // 这个函数会被python调用作为cexample.add_ints(a, b).
    STATIC mp_obj_t px_sub_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
    		// 提取出ints数据重python micropython 输入 对象.
        int a = mp_obj_get_int(a_obj);
        int b = mp_obj_get_int(b_obj);
    
    		// 计算加法并且传给MicroPython 对象
        return mp_obj_new_int(a - b);
    }
    
    // 定义一个python参考到上面的函数
    STATIC MP_DEFINE_CONST_FUN_OBJ_2(px_sub_ints_obj, px_sub_ints);
    
    // 定义所有的模块属性
    // 表条目是属性名称
    // 和 MicroPython 对象引用的键/值对。
    // 所有的定义和字符串通过编译器被写成MP_QSTR_xxx和被优化成字宽长度的整数
    STATIC const mp_rom_map_elem_t px_module_globals_table[] = {
        { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_px) },
        { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&px_sub_ints_obj) },
    };
    STATIC MP_DEFINE_CONST_DICT(px_module_globals, px_module_globals_table);
    
    // 定义模块对象
    const mp_obj_module_t px_cmodule = {
        .base = { &mp_type_module },
        .globals = (mp_obj_dict_t *)&px_module_globals,
    };
    
    // 注册模块使其可在python中使用。
    // 注:在第三个参数中的"1"表示的是这个模块会常开
    // 这个"1"也可以使用预编译的宏定义比如:MODULE_CEXAMPLE_ENABLED来替代,它能够变得有条件的使用改模块
    MP_REGISTER_MODULE(MP_QSTR_px, px_cmodule, 1);
    

    ​ 这样一个python的模块接口节完成了。执行make -j$(nproc) TARGET=OPENMV4 -C src编译一遍,没有问题,且生成了px.o文件。使用方法如下:

    import px   #根据MP_REGISTER_MODULE(MP_QSTR_px, px_cmodule, 1);中MP_QSTR_px中"MP_QSTR_"后面
    print(px.sub_ints(1, 3))#根据STATIC MP_DEFINE_CONST_FUN_OBJ_2(px_sub_ints_obj, px_sub_ints);中px_sub_ints中除掉module名剩余的函数名。
    

    ​ 那么如何为STM32或者其他芯片添加一个调用底层硬件的接口?在src/omv/modules/micropython.mk中有如下:SRC_USERMOD += $(wildcard $(OMV_PORT_MOD_DIR)/*.c)OMV_PORT_MOD_DIR为:OMV_PORT_MOD_DIR := $(OMV_MOD_DIR)/../ports/$(PORT)/modules也就是说在src/omv/ports/stm32/modules中也是被编译器搜索module的目录。(这里ports表示一类板子的意思,且ports目录下stm32仅仅是作为示例)。根据原有的代码,这里我给出自己的一些示例代码如下led模块与digital_iput模块。编写流程可参考:https://www.jianshu.com/p/1b2915bb570d

    函数声明宏源代码(如MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN)可在src/micropython/py/obj.h中看到。其意义和用法如下(从源码src/micropython/py/obj.h函数fun_builtin_1_call可以推断):

    宏名 意义 用法
    MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) 声明一个函数不带参数的 obj_name=对象名。
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) 声明一个函数带1个参数的 obj_name=对象名。
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) 声明一个函数带2个参数的 obj_name=对象名。
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) 声明一个函数带3个参数的 obj_name=对象名。
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) 声明一个函数带变参且无关键字,参数个数下限可设置,上限为无限制(实际上是0xffff) obj_name=对象名。
    n_args_min=参数最少个数
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) 声明一个函数带变参且无关键字,参数个数下限可设置,上限也可设置 obj_name=对象名。
    n_args_min=参数最少个数
    n_args_max=参数最大个数
    func_name=函数名。
    MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) 声明一个函数带变参带关键字,参数个数下限可设置,上限为无限制(实际上是0xffff) obj_name=对象名。
    n_args_min=参数最少个数
    func_name=函数名。

    这里带关键字还没了解清楚。

    而MP_DEFINE_CONST_DICT这个的表,例如:

    static const mp_rom_map_elem_t globals_dict_table[] = {
        { MP_ROM_QSTR(MP_QSTR___name__),        MP_ROM_QSTR(MP_QSTR_led) },//类名
        { MP_ROM_QSTR(MP_QSTR_status),   		MP_ROM_INT(is_en) },//成员数据
        { MP_ROM_QSTR(MP_QSTR_setup),           MP_ROM_PTR(&py_led_setup_obj) },//成员函数
        { MP_ROM_QSTR(MP_QSTR_en),            	MP_ROM_PTR(&py_led_en_obj) }
    };
    //MP_ROM_QSTR向python中声明一个成员。函数用MP_ROM_PTR,数据用MP_ROM_INT或其他。
    

    使用真机验证

    ​ 无板子。

    其他

    整个工程的main

    用我比较熟悉的STM32:

    ​ 位置应该在:src\omv\ports\stm32\main.c

    示例代码

    请放在openmv\src\omv\ports\stm32\modules下。

    LED.C

    /*
     * This file is part of the OpenMV project.
     *
     * Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
     * Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
     *
     * This work is licensed under the MIT license, see the file LICENSE for details.
     *
     * Buzzer Python module.
     */
    #include "py/obj.h"
    
    #include "omv_boardconfig.h"
    #include STM32_HAL_H
    
    static GPIO_TypeDef *led_port = 0;
    static int led_pin = 0;
    static int led_act_low = 0;
    static int is_en = 0;
    
    typedef struct gpio_map{
    	char gpio_name;
    	GPIO_TypeDef *port;
    }gpio_map;
    
    static gpio_map  GPIO_MAPs[6] = {
    	{'A', GPIOA},
    	{'B', GPIOB},
    	{'C', GPIOC},
    	{'D', GPIOD},
    	{'E', GPIOE},
    	{'H', GPIOH},
    };
    
    static int led_setup( char gpio_port, int gpio_pin, int arctive_low)
    {
    	if( gpio_port != 'H')
    	{
    		led_port = GPIO_MAPs[5].port;
    	}
    	else if( gpio_port <= 'E' && gpio_port >= 'A')
    	{
    		led_port = GPIO_MAPs[(gpio_port-'A')].port;
    	}
    	else
    		return -1;
    	led_pin = gpio_pin;
    	led_act_low = arctive_low;
    	is_en = 0;
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.Pull = led_act_low?GPIO_PULLUP:GPIO_PULLDOWN;
    	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
    	GPIO_InitStructure.Pin = led_pin;
    	HAL_GPIO_Init(led_port, &GPIO_InitStructure);
    	return 1;
    }
    
    STATIC mp_obj_t py_led_setup(mp_obj_t gpio_port, mp_obj_t gpio_pin, mp_obj_t arctive_low) 
    {
    	const char *port = mp_obj_str_get_str( gpio_port);
    	int32_t pin = mp_obj_get_int( gpio_pin);
    	int32_t act_low = mp_obj_get_int( arctive_low);
    	int res = led_setup( port[0], pin, act_low);
    	return mp_obj_new_int( res);
    }
    //声明成员函数,这里是需要不同的参数那么只能使用变参,且有3个参数需要设置。
    STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_led_setup_obj, py_led_setup);
    
    
    STATIC mp_obj_t py_led_en(mp_obj_t en_obj)
    {
      if( led_port)
    		return mp_obj_new_bool(0);
    	int32_t en = mp_obj_get_int( en_obj);
    	is_en = en;
    	en = led_act_low?!en:en;
    	HAL_GPIO_WritePin( led_port, (unsigned short)led_pin, en);
    	return mp_obj_new_bool(1);
    }
    //声明成员函数,且有1个参数需要设置。
    STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_led_en_obj, py_led_en);
    
    STATIC mp_obj_t py_led_status()
    {
    	return mp_obj_new_bool(is_en);
    }
    //声明成员函数,且有1个参数需要设置。
    STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_led_status_obj, py_led_status);
    
    static const mp_rom_map_elem_t globals_dict_table[] = {
        { MP_ROM_QSTR(MP_QSTR___name__),        MP_ROM_QSTR(MP_QSTR_led) },
        { MP_ROM_QSTR(MP_QSTR_status),   				MP_ROM_PTR(&py_led_status_obj) },
        { MP_ROM_QSTR(MP_QSTR_setup),           MP_ROM_PTR(&py_led_setup_obj) },
        { MP_ROM_QSTR(MP_QSTR_en),            	MP_ROM_PTR(&py_led_en_obj) }
    };
    //MP_ROM_QSTR向python中声明一个成员。函数用MP_ROM_PTR,数据用MP_ROM_INT或其他。
    STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);
    
    const mp_obj_module_t led_module = {
        .base = { &mp_type_module },
        .globals = (mp_obj_t) &globals_dict,
    };
    MP_REGISTER_MODULE(MP_QSTR_led, led_module, MICROPY_PY_LED);
    

    digital_iput.C

    未实现C
    
  • 相关阅读:
    蓝牙学习(5) -- sockets
    蓝牙学习(4) -- L2CAP
    蓝牙学习(3) Linux kernel部分Bluetooth HCI分析
    蓝牙学习(2)USB Adapter
    蓝牙bluez学习(1) Stack Architecture
    Release Python Program as exe
    蓝牙stack bluez学习(1)Stack Architecture
    树莓派
    树莓派
    关于Reflow回流
  • 原文地址:https://www.cnblogs.com/inkhearts/p/16100066.html
Copyright © 2020-2023  润新知