18. PikaStdDevice 标准设备

PikaStdDevice 是一个抽象的设备模型,提供了跨平台的统一外设 API 。

18.1. 安装

  • 在 requestment.txt 中加入 PikaStdDevice 的依赖。
  1. PikaStdDevice==v1.4.3
  • 运行 pikaPackage.exe

18.2. 为什么要有标准设备模块

什么是标准设备模块呢?我们先从其他的脚本技术说起,比如 MicroPython,并没有统一的外设调用 API,这使得用户在使用不同的平台时,都需要重新学习 API,比如下面这个是 MicroPython 在 STM32F4 平台驱动 GPIO 的代码。

_images/1638495380966-02a52d33-9986-401c-a7e1-136ce71ad53e.webp

这个是 ESP8266 的

_images/1638495381179-e6afcca5-7f32-4a2f-a531-10f6b106db15.webp

可以明显看到在选择 pin 的管脚时,一个用的是字符串,而另一个用的是整型数,控制电平时,一个使用 high()low()方法,而另一个使用on()off()方法,总之驱动的API标准很混乱。 有没有什么办法,能够统一外设的 API,使得用户只需要熟悉一套 API,就能够在任意平台通用呢? 方法是有的,就是 PikaStdDevice 标准设备驱动模块。

18.3. 模块结构

_images/1638681382807-901fa254-8323-4a9b-92ef-4e5b6e8ad5f9.png

PikaStdDevice 是一个抽象的设备驱动模块,定义了所有的用户 API,各个平台的驱动模块只要从PikaStdDevice 继承,就能够获得一模一样的用户 API,而 PikaStdDevice 内部会间接调用平台驱动,通过多态特性重写底层的平台驱动,就可以在不同的平台工作了。

18.4. 模块示例

以 GPIO 模块为例,以下是 PikaStdDevice 定义的用户 API

  1. class GPIO(TinyObj):
  2. def __init__(self):
  3. pass
  4. def init(self):
  5. pass
  6. def setPin(self, pinName: str):
  7. pass
  8. def setId(self, id: int):
  9. pass
  10. def getId(self) -> int:
  11. pass
  12. def getPin(self) -> str:
  13. pass
  14. def setMode(self, mode: str):
  15. pass
  16. def getMode(self) -> str:
  17. pass
  18. def setPull(self, pull: str):
  19. pass
  20. def enable(self):
  21. pass
  22. def disable(self):
  23. pass
  24. def high(self):
  25. pass
  26. def low(self):
  27. pass
  28. def read(self) -> int:
  29. pass

以下是 PikaStdDevice 需要重写的平台驱动

  1. # need be overrid
  2. def platformHigh(self):
  3. pass
  4. # need override
  5. def platformLow(self):
  6. pass
  7. # need override
  8. def platformEnable(self):
  9. pass
  10. # need override
  11. def platformDisable(self):
  12. pass
  13. # need override
  14. def platformSetMode(self):
  15. pass
  16. # need override
  17. def platformRead(self):
  18. pass

而我们要制作的 CH32V103 的 GPIO 模块,就从标准驱动模块中继承。

  1. class GPIO(PikaStdDevice.GPIO):
  2. # override
  3. def platformHigh(self):
  4. pass
  5. # override
  6. def platformLow(self):
  7. pass
  8. # override
  9. def platformEnable(self):
  10. pass
  11. # override
  12. def platformDisable(self):
  13. pass
  14. # override
  15. def platformSetMode(self):
  16. pass
  17. # override
  18. def platformRead(self):
  19. pass

通过这个方法,我们就可以让 STM32 的驱动模块、CH32 的驱动模块、ESP32 的驱动模块有着一模一样的用户 API。用户只要熟悉了一套 API,就可以轻松使用支持了 PikaScript 标准驱动模块的所有平台。 下面是部分被注册在驱动模块里面 C 原生驱动函数

  1. void CH32V103_GPIO_platformEnable(PikaObj *self){
  2. char *pin = obj_getStr(self, "pin");
  3. char *mode = obj_getStr(self, "mode");
  4. GPIO_TypeDef *GPIO_group = get_GPIO_group(pin);
  5. uint16_t GPIO_pin = get_GPIO_pin(pin);
  6. GPIOMode_TypeDef GPIO_mode = get_GPIO_mode(mode);
  7. uint32_t GPIO_clock_group = get_GPIO_Clock_group(pin);
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. RCC_APB2PeriphClockCmd(GPIO_clock_group,ENABLE);
  10. GPIO_InitStructure.GPIO_Pin = GPIO_pin;
  11. GPIO_InitStructure.GPIO_Mode = GPIO_mode;
  12. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  13. GPIO_Init(GPIO_group, &GPIO_InitStructure);
  14. }
  15. void CH32V103_GPIO_platformHigh(PikaObj *self){
  16. char *pin = obj_getStr(self, "pin");
  17. GPIO_TypeDef *GPIO_group = get_GPIO_group(pin);
  18. uint16_t GPIO_pin = get_GPIO_pin(pin);
  19. GPIO_WriteBit(GPIO_group, GPIO_pin, Bit_SET);
  20. }