跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python

APM32F427 上移植 PikaPython 实现 GPIO 点灯控制

如何在 APM32F427 MCU 上移植 PikaPython 并实现 GPIO 点灯功能。主要步骤包括:更新依赖包(PikaStdDevice, time),创建针对 APM32F427 的模块声明文件,编写 C 语言 GPIO 驱动程序以支持引脚读写和配置,最后通过串口工具运行 Python 脚本测试 LED 闪烁。该方案利用 PikaPython 的统一驱动模式简化了嵌入式开发流程。

月亮邮递员发布于 2026/3/30更新于 2026/7/2857 浏览
APM32F427 上移植 PikaPython 实现 GPIO 点灯控制

APM32F427 上移植 PikaPython 实现 GPIO 点灯控制

本文介绍在 APM32F427 上运行 Python(PikaPython)的基础功能,重点介绍 GPIO 驱动移植,目标为点灯。

引入必要的包

在之前的基础上,我们在 pikapython/requirements.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,内容如下:

// apm32f4_pika.pyi

fromPikaObj import *
import PikaStdDevice

class GPIO(PikaStdDevice.GPIO):
    ...
class UART(PikaStdDevice.UART):
    ...

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

修改 pikapython/requirements.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 个包,与 requirements.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;
    }
    struct platform_data_GPIO *data = pikaMalloc(sizeof(struct platform_data_GPIO));
    data->pin = pin;
    data->port = port;
    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 这个工具,可以通过串口发送并执行脚本。

下载并执行这个程序,在红色框处选择串口,波特率并打开。复位一次设备,就能在终端看到串口输出的内容。

勾选复选框,把刚才准备好的 py 脚本拖进去。从图可以看到执行期间串口输出的计数值。

小结

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

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

目录

  1. APM32F427 上移植 PikaPython 实现 GPIO 点灯控制
  2. 引入必要的包
  3. 加入针对 APM32F427 的模块
  4. 编写驱动
  5. 运行测试
  6. 小结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • SBUS 协议详解:从原理、硬件接口到代码实现
  • C++ 类与对象核心知识点总结
  • DeepSeek-R1 大模型基于 MS-Swift 框架的部署、推理与微调实践
  • Whisper v0.2 本地语音转文字工具安装与使用指南
  • Xilinx PCIe IP 核详解、FPGA 实现及仿真流程(Virtex-7 Gen3)
  • Stable Diffusion 3.5 WebUI Forge 与 SwarmUI 实战指南
  • Python 爬虫实战:爬取汽车之家车型与报价数据
  • Java AI 编程实测:从自然语言生成完整工程,初中级开发者效率分析
  • 2026 AI智能图+AI视频终极工具箱:10个必备神器合集
  • Claude Code 中 CLAUDE.md 的加载时机与书写最佳实践
  • Linux 进程间通信:命名管道(FIFO)实战指南
  • AgentScope Java 与 Spring AI Alibaba Workflow 集成指南
  • VR 多相电源架构与设计详解
  • 判断一个需求值不值得做:产品经理的评估思路
  • 正版 Adobe PS 与 LRC AI 填充功能无法使用解决方案
  • OpenCode 安装 oh-my-opencode 插件教程:AI 辅助自动安装
  • Z-Image-Turbo 孙珍妮模型使用指南
  • OpenClaw web_search 与 web_fetch 最佳实践速查
  • 深入理解飞书 Webhook 签名验证:一次踩坑到填坑的完整记录
  • 知网 AIGC 检测价格对比与省钱策略

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online