本期我们来遵循其他单片机的学习路线开始去做一位点灯大师—点亮一个LED。那么第一步还是先知道K210里面的硬件电路是怎么连接的,需要查看上一节的文档,看看开发板原理图到底是哪个LED跟哪个IO连在一起。
一、硬件电路
根据之前官方提供的assembly drawing资料我们能看到实际的LED的位置,一共有四个
LED,那么我们再来检查一下原理图里的这些灯到底是怎么连接的。
DS1很明显没有连接任何IO,所以它是不可控的,就是电源指示灯,只要数据线连接到PC,DS1就会被点亮。DS2和DS则分别被CH552_TX0和ISP_TX两个IO端口控制。
而LED1从命名来看就是自成一派,从原理图分析来看,这是一个RGB的三色灯,原理图写的已经非常详细了,里面核心是三个灯封装在一个器件里,分别被LED_R, LED_G, LED_B三个IO控制。
通过检查K210本身的IO我们看到,LED_R, LED_G, LED_B分别连接到CPU的IO_13, IO_12和IO_14,那么我们可以学习相关的IO编程方法来控制LED灯的亮灭了。
K210比较强大的功能是可以通过内部映射让外部引脚实现不同的功能,我们要学习如何让指定的IO干它能干的事。那么我们就需要学习实现这种映射关系的方法。这个与一般的单片机的学习稍有不同。
二、GPIO的配置
那么我们如何来理解K210的这种引脚映射的[内部功能]呢?K210 芯片上的 外部引脚 和 内部功能 是彼此独立的,引脚是指从芯片上引出的许多金属触点,也就是我们俗称的功能引脚,它可以是 GPIO / PWM / ADC / I2C 等内部功能引脚,传统的认知是引脚对应的内部功能是不可改变的,但可以复用的,而 K210 是可以通过映射来改变引脚功能的,看如下示意图理解具体的映射功能。
首先可以将 I2C 的 SCL/SDA 映射(MAP)到 IO6/IO7 引脚,从而在此引脚上进行 I2C 的读写操作。
+------------------------------+
| |
| +---+ |
<-----+ <-----+ |I2C| |
IO6| +---+ |
| | |
| | +----+ |
<-----+ <-------+ |UART| |
IO7| +----+ |
| |
| +---+ |
<-----+ |SPI| |
IO8| +---+ |
| |
| +---+ |
<-----+ |I2S| |
IO9| +---+ |
| |
| |
+------------------------------+
接着还可以将 SPI 的 SCLK/MOSI/MISO/CS 映射(MAP)到 IO6/IO7/IO8/IO9 引脚,也就可以在此引脚上进行 SPI 的读写操作。
+------------------------------+
| |
| +---+ |
<------<-------<-- |I2C| |
IO6| | +---+ |
| | |
| | +----+ |
<------<------+ | |UART| |
IO7| | | +----+ |
| +--+-+ |
| |SPI| |
<------<--------+--+ |
IO8| | |
| | |
| | +---+ |
<------<--------+ |I2S| |
IO9| +---+ |
| |
| |
+------------------------------+
调用 register 函数将 pin 引脚与具体的硬件功能(GPIO/I2C/UART/I2S/SPI)绑定起来,在不使用的时候调用 unregister 释放引脚所绑定的硬件功能(或称 function ),这不同于传统单片机的理解, K210 可以将一定范围内的引脚映射到具体的硬件功能。
如下代码所示:
from fpioa_manager import fm
fm.register(11, fm.fpioa.GPIO0, force=True)
fm.register(12, fm.fpioa.GPIOHS0, force=True)
fm.register(13, fm.fpioa.UART2_TX)
fm.register(14, fm.fpioa.UART2_RX)
其中上段程序中的register函数,调用方法如下:
register (pin, func, force=True)#
pin: 功能映射引脚
function : 芯片功能
force: 强制分配,如果为True,则可以多次对同一个引脚注册;False则不允许同一引脚多次注册。默认为True是为了方便IDE多次运行程序使用
设置引脚(pin)对应的外设功能(func),默认启用强制绑定参数(force=True),它将强制更换指定的引脚功能,如果发现存在上一个绑定的引脚,则会发出一个警告,但不影响代码继续执行。
如果设置 force=False ,则会在 register 发现硬件功能已经被使用了,此时就会弹出异常,方便深度开发的时候不清楚 GPIO/HS 的分配情况,常见于运行某个代码的按键在访问某些功能的时候不能使用了的场合。
使用方法:
from fpioa_manager import fm
fm.register(16, fm.fpioa.GPIO2)
fm.register(13, fm.fpioa.GPIO2)
fm.register(12, fm.fpioa.GPIO2, force=False)
此时会出现提示:
[Warning] function is used by fm.fpioa.GPIO2(pin:16)
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
File "fpioa_manager.py", line 20, in register
Exception: [Warning] function is used by fm.fpioa.GPIO2(pin:13)
可见提示了 fm.fpioa.GPIO2(pin:16) 和 fm.fpioa.GPIO2(pin:13) 的占用情况。
注意:
以下 GPIOHS 默认已经被使用, 程序中如非必要尽量不要使用,以下引脚已经在 MaxiPy 开机启动时注册,请注意。
GPIOHS | 功能 |
GPIOHS31 | LCD_DC |
GPIOHS30 | LCD_RST |
GPIOHS29 | SD_CS |
GPIOHS28 | MIC_LED_CLK |
GPIOHS27 | MIC_LED_DATA |
三、程序开发实战
上一节的例程比较好的配合LCD的使用,如果是没有采购LCD的同学可以尝试学习本节提供的例程—点亮LED。再次强调一下,可能你曾经用过一些单片机,在手册上都规定了引脚和片上外设功能(就是芯片内部集成的外设,比如 GPIO、I2C、SPI 等)的绑定,或者重映射。比如规定了 I2C 只能用 Pin9 和 Pin10,启动了重映射功能后,只能用Pin11和Pin12
但是 MaixPy 所使用的硬件 K210 的片上外设对应的引脚(硬件引脚)是可以任意映射的,相比之下 K210 硬件设计和软件设计的自由度更大。 比如 I2C 可以使用 Pin11 和 Pin12,也可以改成其它任意引脚。注意要区分 GPIO 和 IO的区别, IO也可以叫Pin 也就是引脚,是芯片引出来的硬件引脚, 而GPIO是一种外设,可以控制这些Pin/IO 的外设。两者可以有一种方法映射,就像一道桥一样连接他们。因为有了这个强大的映射功能, 所以在使用引脚时,需要增加一步映射的步骤:
from fpioa_manager import fm # 导入库
fm.register(28, fm.fpioa.GPIO0)
这里我们将引脚 28 映射为了 GPIO0 的功能, 执行了这句命令后,引脚28和GPIO0就映射(绑定)好了,要取消映射(解绑),则需要调用fm.unregister函数,如fm.unregister(28)可取消引脚28的绑定。
另外,Pin 和 外设只能唯一对应, 不能一对多,需要对同一个外设或者引脚重复映射,否则程序可能产生难以发现的错误(BUG)
接下来我们就要开始控制 LED 需要使用到 GPIO。board_info 与板卡相关,不同板卡配置不同,使用前需要手动配置。
程序如下:
from fpioa_manager import fm
from Maix import GPIO
io_led_red = 13
fm.register(io_led_red, fm.fpioa.GPIO0)
led_r=GPIO(GPIO.GPIO0, GPIO.OUT)
led_r.value(0)
按照前面运行代码的方法在终端里面运行代码, 会发现 LED 灯的红色被点亮了!
接下来我们分析代码:
从 fpioa_manager 包导入fm 对象,主要用于引脚和外设的映射
从包 Maix 导入了 GPIO 这个类, GPIO 外设相关操作
定义一个变量io_led_red,值为13,即Pin13/IO13, 具体 LED 的引脚连接到了芯片的哪个引脚,请在前面的硬件介绍中看原理图
使用fm(fpioa manager 的缩写)这个内置的对象来注册芯片的外设和引脚的对应关系, 这里 fm.fpioa.GPIO0 是K210的一个 GPIO 外设(注意区分 GPIO(外设) 和引脚(实实在在的硬件引脚)的区别 ),所以把 fm.fpioa.GPIO0 注册到了引脚 IO13;
然后定义一个 GPIO 对象led_r,使用 led_r.value(1) 或者 led_r.value(0) 来设置高低电平即可, 因为这里设置了低电平,根据上面的原理图可知低电平导通,LED灯亮。到这里已经可以点灯了,现在可以自己尝试用 for 循环来实现 LED 闪烁或者流水灯~做出不同的变换效果。