12下一页
返回列表 发新帖我要提问本帖赏金: 30.00元(功能说明)

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

[复制链接]
741|24
wangqy_ic 发表于 2025-12-28 21:05 | 显示全部楼层 |阅读模式
本帖最后由 wangqy_ic 于 2026-1-22 16:59 编辑

#申请原创#

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

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

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

再次运行包管理器 pikaPackage.exe,完成后也是会追加合适的版本信息,内容为:
  1. pikascript-core==v1.13.4
  2. PikaStdLib==v1.13.4
  3. PikaStdDevice==v2.4.6
  4. time==v0.2.2
这4个包是点灯必须的。下面将会增加针对 APM32F427 的自定义包。

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

  2. from PikaObj import *
  3. import PikaStdDevice

  4. class GPIO(PikaStdDevice.GPIO):
  5.     ...
  6. class UART(PikaStdDevice.UART):
  7.     ...

这是声明了两个类:GPIO 和 UART。
稍后编写 py 脚本的时候,是可以直接使用 apm32f4_pika.GPIO 实例化相应的类。

修改 pikapython\requestment.txt,把 apm32f4_pika 追加到文件末尾:
  1. pikascript-core==v1.13.4
  2. PikaStdLib==v1.13.4
  3. PikaStdDevice==v2.4.6
  4. time==v0.2.2
  5. apm32f4_pika

运行 rust-msc-latest-win10.exe,生成必要的内容,可以看到程序的输出类似:
3181695128d169b9e.png
红色框出可以看到有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 这个源文件里:
  1. #include "BaseObj.h"
  2. #include "dataStrs.h"
  3. #include "pika_hal.h"
  4. #include "board.h"

  5. #include "apm32f427xx.h"

  6. #include <stdint.h>
  7. #include <string.h>

  8. struct platform_data_GPIO
  9. {
  10.     int port;
  11.     int pin;
  12. };

  13. static GPIO_T *const gpios[] = {
  14.     GPIOA,
  15.     GPIOB,
  16.     GPIOC,
  17.     GPIOD,
  18.     GPIOE,
  19.     GPIOF,
  20.     GPIOG,
  21.     GPIOH,
  22. };

  23. // 把字符串类型的 Pin 脚名称解析为 port/pin 编号
  24. static int get_io_port_and_pin(const char *name, int *port, int *pin)
  25. {
  26.     char ch = 0;

  27.     if (name[0] != 'P' && name[0] != 'p')
  28.     {
  29.         return -1;
  30.     }

  31.     int res = sscanf(name + 1, "%c%d", &ch, pin);

  32.     if (res != 2)
  33.     {
  34.         return -1;
  35.     }

  36.     if (ch >= 'A' && ch <= 'Z')
  37.     {
  38.         *port = ch - 'A';
  39.     }
  40.     else if (ch >= 'a' && ch <= 'z')
  41.     {
  42.         *port = ch - 'a';
  43.     }
  44.     else
  45.     {
  46.         return -1;
  47.     }

  48.     if (*port < 0 || *port > 7 || *pin < 0 || *pin > 15)
  49.     {
  50.         return -1;
  51.     }

  52.     return 0;
  53. }

  54. // 打开 GPIO 设备
  55. int pika_hal_platform_GPIO_open(pika_dev *dev, char *name)
  56. {
  57.     int port, pin;

  58.     int res = get_io_port_and_pin(name, &port, &pin);
  59.     if (res != 0)
  60.     {
  61.         return -1;
  62.     }

  63.         // 申请一个 GPIO 数据结构体
  64.     struct platform_data_GPIO *data = pikaMalloc(sizeof(struct platform_data_GPIO));

  65.     data->pin = pin;
  66.     data->port = port;
  67.     // 驱动数据指向生成的 GPIO 数据结构体
  68.     dev->platform_data = data;

  69.     return 0;
  70. }

  71. // 关闭 GPIO 设备
  72. int pika_hal_platform_GPIO_close(pika_dev *dev)
  73. {
  74.     if (NULL != dev->platform_data)
  75.     {
  76.         pikaFree(dev->platform_data, sizeof(struct platform_data_GPIO));
  77.         dev->platform_data = NULL;
  78.     }

  79.     return 0;
  80. }

  81. // 读取 GPIO
  82. int pika_hal_platform_GPIO_read(pika_dev *dev, void *buf, size_t count)
  83. {
  84.     struct platform_data_GPIO *gpio_data = dev->platform_data;
  85.     uint32_t level = (gpios[gpio_data->port]->IDATA >> gpio_data->pin) & 1;

  86.     memcpy(buf, &level, count);

  87.     return 0;
  88. }

  89. // 设置 GPIO
  90. int pika_hal_platform_GPIO_write(pika_dev *dev, void *buf, size_t count)
  91. {
  92.     struct platform_data_GPIO *gpio_data = dev->platform_data;
  93.     uint32_t level = 0;

  94.     memcpy(&level, buf, count);

  95.     if (level == 0)
  96.     {
  97.         gpios[gpio_data->port]->BSCL |= (1 << gpio_data->pin);
  98.     }
  99.     else
  100.     {
  101.         gpios[gpio_data->port]->BSCH |= (1 << gpio_data->pin);
  102.     }

  103.     return 0;
  104. }

  105. // 使能 GPIO 设备,暂时保持空
  106. int pika_hal_platform_GPIO_ioctl_enable(pika_dev *dev)
  107. {
  108.     (void)dev;
  109.     return 0;
  110. }

  111. // 禁用 GPIO 设备,暂时保持空
  112. int pika_hal_platform_GPIO_ioctl_disable(pika_dev *dev)
  113. {
  114.     (void)dev;
  115.     return 0;
  116. }

  117. // 配置 GPIO 设备
  118. int pika_hal_platform_GPIO_ioctl_config(pika_dev *dev,
  119.                                         pika_hal_GPIO_config *cfg)
  120. {
  121.     struct platform_data_GPIO *gpio_data = dev->platform_data;

  122.     if (cfg->dir == PIKA_HAL_GPIO_DIR_OUT)
  123.     {
  124.             // 配置为 输出
  125.         gpios[gpio_data->port]->MODE = (gpios[gpio_data->port]->MODE & (~(3 << (gpio_data->pin * 2)))) | (1 << (gpio_data->pin * 2));
  126.     }
  127.     else
  128.     {
  129.             // 否则为 输出
  130.         gpios[gpio_data->port]->MODE = gpios[gpio_data->port]->MODE & (~(3 << (gpio_data->pin * 2)));
  131.     }

  132.     gpios[gpio_data->port]->PUPD = gpios[gpio_data->port]->PUPD & (~(3 << (gpio_data->pin * 2)));

  133.     switch (cfg->pull)
  134.     {
  135.     case PIKA_HAL_GPIO_PULL_UP: // 上拉
  136.         gpios[gpio_data->port]->PUPD |= (1 << (gpio_data->pin * 2));
  137.         break;
  138.         case PIKA_HAL_GPIO_PULL_DOWN: // 下拉
  139.         gpios[gpio_data->port]->PUPD |= (2 << (gpio_data->pin * 2));
  140.         break;
  141.         
  142.     default:
  143.         break;
  144.     }

  145.     return 0;
  146. }

  147. // 提供 ms 延时
  148. void pika_platform_sleep_ms(uint32_t ms)
  149. {
  150.     ms_delay(ms);
  151. }

驱动写完了,把它加入 keil 工程。
需要注意的是,pikascript-lib 目录下因为我们新增的两个包 PikaStdDevice 和 time 都自动生成了相应的源文件,也都需要加入到 keil 工程一起编译。

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

为了测试新增的包,编写一个测试程序,让 LED2 闪烁 50 次:
  1. import PikaStdLib
  2. import PikaStdDevice
  3. import apm32f4_pika
  4. import time

  5. mem = PikaStdLib.MemChecker()

  6. print('mem.max :')
  7. mem.max()
  8. print('mem.now :')
  9. mem.now()

  10. led2 = apm32f4_pika.GPIO()
  11. led2.setPin('PF0')
  12. led2.setMode('out')
  13. led2.enable()
  14. led2.low()

  15. for i in range(0,50):
  16.     print(i)

  17.     led2.low()
  18.     time.sleep_ms(500)
  19.     led2.high()
  20.     time.sleep_ms(500)
  21.    
  22. print('over')

因为目前的工程尚未集成文件系统,所以我们不能直接运行这个脚本。好在 PikaPython 项目提供了 pikaStudio 这个工具,可以通过串口发送并执行脚本。下载连接:https://gitee.com/Lyon1998/pikapython/attach_files/1285327/download

下载并执行这个程序:
705106951297943d13.png

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

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

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

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

小结

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

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


@21小跑堂
apm32f427_pikapython_led.gif

打赏榜单

21小跑堂 打赏了 30.00 元 2026-01-28
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论

书接上文,在搭建完PikaPython移植到APM32F427 的基础上,教你如何实现点灯功能。  发表于 2026-1-28 10:32
Gfan 发表于 2025-12-30 15:29 | 显示全部楼层
喜闻乐见的点灯环节~~~~///(^v^)\\\~~~
updownq 发表于 2026-1-2 10:41 | 显示全部楼层
MicroPython 环境部署
jtracy3 发表于 2026-1-2 12:14 | 显示全部楼层
Python点灯代码实现              
primojones 发表于 2026-1-2 13:04 | 显示全部楼层
已被MicroPython官方支持
vivilyly 发表于 2026-1-2 14:15 | 显示全部楼层
基础 blinky 示例              
deliahouse887 发表于 2026-1-3 22:33 | 显示全部楼层
可以部署TinyML模型,实现手势识别控灯等智能功能?
sesefadou 发表于 2026-1-4 11:40 | 显示全部楼层
专为微控制器设计的 Python 子集
chenci2013 发表于 2026-1-4 13:51 | 显示全部楼层
APM32F427 仅有 512KB SRAM,避免动态分配大块内存。
olivem55arlowe 发表于 2026-1-4 15:59 | 显示全部楼层
MicroPython 固件?
maqianqu 发表于 2026-1-4 18:29 | 显示全部楼层
需要获取官方固件或交叉编译吧               
OceanGaze 发表于 2026-1-4 18:40 | 显示全部楼层
现在的MCU都已经进化到可以轻松支持Python了吗?
everyrobin 发表于 2026-1-4 20:20 | 显示全部楼层
运行 MicroPython 非常简单
cashrwood 发表于 2026-1-7 17:09 | 显示全部楼层
针对微控制器裁剪的 Python 3
wangshujun 发表于 2026-1-9 11:15 | 显示全部楼层
updownq 发表于 2026-1-2 10:41
MicroPython 环境部署

这个在哪里找到,有存储库吗
中国英茂科工 发表于 2026-1-15 09:27 | 显示全部楼层
 楼主| wangqy_ic 发表于 2026-1-16 16:52 | 显示全部楼层
 楼主| wangqy_ic 发表于 2026-1-16 16:56 | 显示全部楼层
@21小跑堂
lvyunhua 发表于 2026-1-17 15:50 | 显示全部楼层
路过学习了
 楼主| wangqy_ic 发表于 2026-1-17 22:08 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:感恩的心对人。

27

主题

147

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部
0