欢迎光临
我们一直在努力

[APM32F4] 在 APM32F427 上运行 Python - 点灯

《在 APM32F427 上运行 Python》https://bbs.21ic.com/icview-3501089-1-1.html
介绍了移植 PikaPython 到 APM32F427 的基础功能,本文介绍 GPIO 驱动移植,目标:点灯。

引入新的必要的包
上一篇文章中,我们在 pikapython\\requestment.txt 加入了当时必须的两个包(或者称之为”模块“)。在运行包管理器后,内容被追加了版本信息,变成:

复制

  • pikascript-core==v1.13.4
  • PikaStdLib==v1.13.4
  • 为了实现点灯,我们增加两个新的包: PikaStdDevice 和 time,内容变更为:

    复制

  • pikascript-core==v1.13.4
  • PikaStdLib==v1.13.4
  • PikaStdDevice
  • time
  • 再次运行包管理器 pikaPackage.exe,完成后也是会追加合适的版本信息,内容为:

    复制

  • pikascript-core==v1.13.4
  • PikaStdLib==v1.13.4
  • PikaStdDevice==v2.4.6
  • time==v0.2.2
  • 这4个包是点灯必须的。下面将会增加针对 APM32F427 的自定义包。

    加入针对 APM32F427 的模块
    新建文本文件 pikapython\\apm32f4_pika.pyi,内容:

    复制

  • # apm32f4_pika.pyi
  • from PikaObj import *
  • import PikaStdDevice
  • class GPIO(PikaStdDevice.GPIO):
  •     …
  • class UART(PikaStdDevice.UART):
  •     …
  • 这是声明了两个类:GPIO 和 UART。
    稍后编写 py 脚本的时候,是可以直接使用 apm32f4_pika.GPIO 实例化相应的类。

    修改 pikapython\\requestment.txt,把 apm32f4_pika 追加到文件末尾:

    复制

  • pikascript-core==v1.13.4
  • PikaStdLib==v1.13.4
  • PikaStdDevice==v2.4.6
  • time==v0.2.2
  • apm32f4_pika
  • 运行 rust-msc-latest-win10.exe,生成必要的内容,可以看到程序的输出类似:
     

    红色框出可以看到有5个包,与 requestment.txt 的内容一一对应。

    在 pikascript-api 文件夹下新增了3个文件:

    • apm32f4_pika.h
    • apm32f4_pika_GPIO.h
    • apm32f4_pika_UART.h

    这几个文件的内容不用关系,它们是自动生成的,也不需要编辑修改。下面开始编写驱动。

    编写驱动
    在 pikascript-lib 文件夹下,创建 apm32f4_pika 文件夹,GPIO/UART 的驱动就放在这个文件夹下。简单起见,我们先把全部驱动的代码放在 pikapython\\pikascript-lib\\apm32f4_pika\\apm32f4_pika.c 这个源文件里:

    复制

  • #include "BaseObj.h"
  • #include "dataStrs.h"
  • #include "pika_hal.h"
  • #include "board.h"
  • #include "apm32f427xx.h"
  • #include <stdint.h>
  • #include <string.h>
  • struct platform_data_GPIO
  • {
  •     int port;
  •     int pin;
  • };
  • static GPIO_T *const gpios[] = {
  •     GPIOA,
  •     GPIOB,
  •     GPIOC,
  •     GPIOD,
  •     GPIOE,
  •     GPIOF,
  •     GPIOG,
  •     GPIOH,
  • };
  • // 把字符串类型的 Pin 脚名称解析为 port/pin 编号
  • static int get_io_port_and_pin(const char *name, int *port, int *pin)
  • {
  •     char ch = 0;
  •     if (name[0] != 'P' && name[0] != 'p')
  •     {
  •         return -1;
  •     }
  •     int res = sscanf(name + 1, "%c%d", &ch, pin);
  •     if (res != 2)
  •     {
  •         return -1;
  •     }
  •     if (ch >= 'A' && ch <= 'Z')
  •     {
  •         *port = ch – 'A';
  •     }
  •     else if (ch >= 'a' && ch <= 'z')
  •     {
  •         *port = ch – 'a';
  •     }
  •     else
  •     {
  •         return -1;
  •     }
  •     if (*port < 0 || *port > 7 || *pin < 0 || *pin > 15)
  •     {
  •         return -1;
  •     }
  •     return 0;
  • }
  • // 打开 GPIO 设备
  • int pika_hal_platform_GPIO_open(pika_dev *dev, char *name)
  • {
  •     int port, pin;
  •     int res = get_io_port_and_pin(name, &port, &pin);
  •     if (res != 0)
  •     {
  •         return -1;
  •     }
  •         // 申请一个 GPIO 数据结构体
  •     struct platform_data_GPIO *data = pikaMalloc(sizeof(struct platform_data_GPIO));
  •     data->pin = pin;
  •     data->port = port;
  •     // 驱动数据指向生成的 GPIO 数据结构体
  •     dev->platform_data = data;
  •     return 0;
  • }
  • // 关闭 GPIO 设备
  • int pika_hal_platform_GPIO_close(pika_dev *dev)
  • {
  •     if (NULL != dev->platform_data)
  •     {
  •         pikaFree(dev->platform_data, sizeof(struct platform_data_GPIO));
  •         dev->platform_data = NULL;
  •     }
  •     return 0;
  • }
  • // 读取 GPIO
  • int pika_hal_platform_GPIO_read(pika_dev *dev, void *buf, size_t count)
  • {
  •     struct platform_data_GPIO *gpio_data = dev->platform_data;
  •     uint32_t level = (gpios[gpio_data->port]->IDATA >> gpio_data->pin) & 1;
  •     memcpy(buf, &level, count);
  •     return 0;
  • }
  • // 设置 GPIO
  • int pika_hal_platform_GPIO_write(pika_dev *dev, void *buf, size_t count)
  • {
  •     struct platform_data_GPIO *gpio_data = dev->platform_data;
  •     uint32_t level = 0;
  •     memcpy(&level, buf, count);
  •     if (level == 0)
  •     {
  •         gpios[gpio_data->port]->BSCL |= (1 << gpio_data->pin);
  •     }
  •     else
  •     {
  •         gpios[gpio_data->port]->BSCH |= (1 << gpio_data->pin);
  •     }
  •     return 0;
  • }
  • // 使能 GPIO 设备,暂时保持空
  • int pika_hal_platform_GPIO_ioctl_enable(pika_dev *dev)
  • {
  •     (void)dev;
  •     return 0;
  • }
  • // 禁用 GPIO 设备,暂时保持空
  • int pika_hal_platform_GPIO_ioctl_disable(pika_dev *dev)
  • {
  •     (void)dev;
  •     return 0;
  • }
  • // 配置 GPIO 设备
  • int pika_hal_platform_GPIO_ioctl_config(pika_dev *dev,
  •                                         pika_hal_GPIO_config *cfg)
  • {
  •     struct platform_data_GPIO *gpio_data = dev->platform_data;
  •     if (cfg->dir == PIKA_HAL_GPIO_DIR_OUT)
  •     {
  •             // 配置为 输出
  •         gpios[gpio_data->port]->MODE = (gpios[gpio_data->port]->MODE & (~(3 << (gpio_data->pin * 2)))) | (1 << (gpio_data->pin * 2));
  •     }
  •     else
  •     {
  •             // 否则为 输出
  •         gpios[gpio_data->port]->MODE = gpios[gpio_data->port]->MODE & (~(3 << (gpio_data->pin * 2)));
  •     }
  •     gpios[gpio_data->port]->PUPD = gpios[gpio_data->port]->PUPD & (~(3 << (gpio_data->pin * 2)));
  •     switch (cfg->pull)
  •     {
  •     case PIKA_HAL_GPIO_PULL_UP: // 上拉
  •         gpios[gpio_data->port]->PUPD |= (1 << (gpio_data->pin * 2));
  •         break;
  •         case PIKA_HAL_GPIO_PULL_DOWN: // 下拉
  •         gpios[gpio_data->port]->PUPD |= (2 << (gpio_data->pin * 2));
  •         break;
  •         
  •     default:
  •         break;
  •     }
  •     return 0;
  • }
  • // 提供 ms 延时
  • void pika_platform_sleep_ms(uint32_t ms)
  • {
  •     ms_delay(ms);
  • }
  • 驱动写完了,把它加入 keil 工程。
    需要注意的是,pikascript-lib 目录下因为我们新增的两个包 PikaStdDevice 和 time 都自动生成了相应的源文件,也都需要加入到 keil 工程一起编译。

    运行
    编译成功,下载程序到开发板。

    为了测试新增的包,编写一个测试程序,让 LED2 闪烁 50 次:

    复制

  • import PikaStdLib
  • import PikaStdDevice
  • import apm32f4_pika
  • import time
  • mem = PikaStdLib.MemChecker()
  • print('mem.max :')
  • mem.max()
  • print('mem.now :')
  • mem.now()
  • led2 = apm32f4_pika.GPIO()
  • led2.setPin('PF0')
  • led2.setMode('out')
  • led2.enable()
  • led2.low()
  • for i in range(0,50):
  •     print(i)
  •     led2.low()
  •     time.sleep_ms(500)
  •     led2.high()
  •     time.sleep_ms(500)
  •    
  • print('over')
  • 因为目前的工程尚未集成文件系统,所以我们不能直接运行这个脚本。好在 PikaPython 项目提供了 pikaStudio 这个工具,可以通过串口发送并执行脚本。下载连接:https://gitee.com/Lyon1998/pikapython/attach_files/1285327/download

    下载并执行这个程序:
     

    在红色框处选择串口,波特率并打开。复位一次设备,就能在终端看到串口输出的内容:
     

    勾选红色框处的复选框,把刚才准备好的 py 脚本拖进去~

    从图可以看到执行期间串口输出的计数值。下面放一个视频,看看闪灯的效果:

    https://bbs.21ic.com/forum.php?mod=attachment&aid=MjQ1NDY4OHxkMGQyYmYxY3wxNzcyMjQ3NzE4fDB8

    小结

    PikaPython 提供了统一的驱动模式,只需要在 .pyi 文件声明支持的类,运行 **rust-msc-latest-win10.exe** 后就可以生成相应的程序框架。开发工程师就只需要完成具体的驱动开发就可以达成目标。总体来说还是很方便的。

    APM32F427 大存储、高主频的特性,也给 PikaPython 提供了一个非常合适的运行平台, 大家快来试试呀~

    @21小跑堂

    ———————
    作者:wangqy_ic
    链接:https://bbs.21ic.com/icview-3501181-1-1.html
    来源:21ic.com
    此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

    赞(0)
    未经允许不得转载:171主机测评 » [APM32F4] 在 APM32F427 上运行 Python - 点灯
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址