MaixDuino 雖然長的跟 Arduino 很像, 不過除非你是用 Arduino IDE 寫程式, 否則就得瞭解一下它的結構, 不然在使用 MaixPy 寫程式時, 可能會連如何點亮 LED 都做不到, 以下就一步步介紹相關的知識吧。
MaixDuino 使用 K210 晶片, K210 晶片外部有 48 個 IO 腳位, 編號從 IO0~IO47, 這些腳位有一些已經被相機、LCD 等用掉, 實際上在 MaixDuino 上接出來的腳位可參考以下的接腳圖或是對照表:
Arduino 腳位 | K210 IO 腳編號 | board_info 中的名稱 |
---|---|---|
RX←0 | IO4 | K210_RX |
TX→1 | IO5 | K210_TX |
2 | IO21 | |
3 | IO22 | |
4 | IO23 | |
5 | IO24 | |
6 | IO32 | |
7 | IO15 | |
8 | IO14 | LED_G |
9 | IO13 | LED_R |
10 | IO12 | LED_B |
11 | IO11 | |
12 | IO10 | |
13 | IO3 | JTAG_TDO |
A0 | IO33 | ADC1_CH5 |
A1 | IO32 | ADC1_CH4 |
A2 | IO35 | ADC1_CH7 |
A3 | IO34 | ADC1_CH6 |
A4 | IO39 | ADC1_CH3 |
A5 | IO36 | ADC1_CH0 |
SCL | IO30 | I2C_SCL |
SDA | IO31 | I2C_SDA |
K210 的這些 IO 腳位並不是固定功能, 每一個腳位都可以透過程式設定成不同的功用, 例如 I2C 就可以任意選用你喜歡的腳位, 而不一定要固定使用特定的腳位。
在 MaixPy 中, 要使用這些腳位, 必須要先幫 IO 腳位註冊功能, 才能使用, 例如:
請注意, 這裡講的腳位編號都是 K210 晶片的 IO 腳位編號, 不是 MaixDuino 板子上的腳位編號。像是上面例子中的 14 就是指 IO14, 如果你查一下上面的腳位對應圖或是表格, 就可以知道這個腳位實際上就是 MaixDuino 板子上的 8 號腳位。
fpioa_manager
是 MaixPy 中管理 IO 腳位功能的模組, 內含 fm
與 board_info
兩個物件, 其中:
fm 就是實際管理 IO 腳位功能的物件, 透過 register
方法為特定腳位依據 fm.fpioa
中定義的功能名稱來註冊, 例如 fm.fpioa.GPIO0
就是第 0 個 GPIO 功能, 可用的名稱清單可參考官方文件, 我也在文末的附錄列出來。
board_info 是與特定控制板相關的資訊, 例如對於 MaixDuino 控制板來說, 就定義了 board_info.LED_G 為 14, 實際上這個腳位並沒有接 LED 燈, 但是寫程式時你可以用 14 或是 board_info.LED_G 來代表 IO14 這個腳位。
瞭解腳位的可程式化功能後, 我們就可以嘗試使用數位輸出了。剛剛註冊腳位的只是功能的類別, 例如剛剛只說要用 IO14 當 GPIO, 但沒有說明到底是輸出還是輸入, 實際使用時還要建立 GPIO 物件, 並註明輸出還是輸入, 例如:
請注意, 在建立 GPIO 物件時, 不是用 IO 腳位編號, 而是用註冊時的功能名稱, 以 GPIO 來說, 可以用的功能名稱有:
HS
是 High Speed 的意思, 與 GPIO0~7 的功能有些差異, 有需要時會再說明。建立好 GPIO 物件, 就可以用該物件進行數位輸出了, 例如, 以下就是常見的閃爍 LED 燈的程式:
value()
是使用 1 和 0 代表高電位和低電位。
接著我們就可以嘗試數位輸入了, 例如:
這裡我們使用 IO16 腳, 如果查看前面的腳位對照圖, 在右下角會看到控制板上的 BOOT 鈕有一腳是接到 IO16, 而根據電路圖, BOOT 鈕的另外一隻腳是接地的, 因此我們在建立 GPIO 物件時, 指定 PULL_UP 模式, 可用的模式還有 PULL_NONE
及 PULL_DOWN
。
除了像是上例輪詢方式查看輸入狀態外, 也可以透過中斷的方式, 在輸入狀態變化的時候引發中斷, 例如:
第 5 列先定義中斷處理函式, 中斷處理函式的參數只有 1 個, 就是引發中斷的 GPIO 物件本身。然後就可以使用 GPIO 的 irq 方法設定中斷。
官方文件中說中斷處理函式有 2 個參數, 1 個是 GPIO 物件, 第 2 個是 IO 腳位編號, 但實際跑起來, 會發生錯誤, 錯誤訊息說只有 1 個參數:
要特別注意的是只有 GPIOHS 的功能提供中斷功能, 所以這個範例使用的是 GPIOHS0, 而不是沿用前一個範例的 GPIO0。
MaixDuino 是透過 ESP32 讀取 ADC, 可參考官方的範例檔。不過目前測試似乎有問題, 都會得到以下錯誤:
根據論壇的說明, 這似乎是 ESP32 上的韌體有問題, 以後再測試看看。
如果使用特定版本的 MaixPy 及 ESP32 韌體, 就可正常運作。請使用 kflash 工具燒錄下載後解開的 mainxpy.bin:
接著再使用 flash_download_tools 將下載解開的 NINA_W102-1.3.1.bin 燒錄到 MaixDuino 上的 ESP32:
請記得 ESP32 是另一個序列埠。完成後, 就可以使用以下程式測試 ADC (MaixDuino 上的 K210 晶片和 ESP32 之間使用 SPI 傳輸資料, 相關接腳可參考電路圖):
adc() 會以 tuple 形式傳回 6 個 ADC 接腳的值:
K210 的 PWM 輸出是依附在計時器下, 因此要使用 PWM 必須先建立計時器物件:
搭配 PWM 用的計時器, 模式一定要設定為 Timer.MODE_PWM。接著就可以建立 PWM 物件:
其中 IO 腳位並不需要像是數位輸出一樣要先設定功能。完整的使用 PWM 來做呼吸燈的程式如下:
實際測試頻率最大可設到 416000016, 但是超過 30000000 以上呼吸燈就會變得呆滯, 漸變的效果就不明顯。
MaixDuino 有些資源不好找, 特別整理如下:
功能名稱 | 簡述 |
---|---|
JTAG_TCLK | JTAG Test Clock |
JTAG_TDI | JTAG Test Data In |
JTAG_TMS | JTAG Test Mode Select |
JTAG_TDO | JTAG Test Data Out |
SPI0_D0 | SPI0 Data 0 |
SPI0_D1 | SPI0 Data 1 |
SPI0_D2 | SPI0 Data 2 |
SPI0_D3 | SPI0 Data 3 |
SPI0_D4 | SPI0 Data 4 |
SPI0_D5 | SPI0 Data 5 |
SPI0_D6 | SPI0 Data 6 |
SPI0_D7 | SPI0 Data 7 |
SPI0_SS0 | SPI0 Chip Select 0 |
SPI0_SS1 | SPI0 Chip Select 1 |
SPI0_SS2 | SPI0 Chip Select 2 |
SPI0_SS3 | SPI0 Chip Select 3 |
SPI0_ARB | SPI0 Arbitration |
SPI0_SCLK | SPI0 Serial Clock |
UARTHS_RX | UART High speed Receiver |
UARTHS_TX | UART High speed Transmitter |
RESV6 | Reserved function |
RESV7 | Reserved function |
CLK_SPI1 | Clock SPI1 |
CLK_I2C1 | Clock I2C1 |
GPIOHS0 | GPIO High speed 0 |
GPIOHS1 | GPIO High speed 1 |
GPIOHS2 | GPIO High speed 2 |
GPIOHS3 | GPIO High speed 3 |
GPIOHS4 | GPIO High speed 4 |
GPIOHS5 | GPIO High speed 5 |
GPIOHS6 | GPIO High speed 6 |
GPIOHS7 | GPIO High speed 7 |
GPIOHS8 | GPIO High speed 8 |
GPIOHS9 | GPIO High speed 9 |
GPIOHS10 | GPIO High speed 10 |
GPIOHS11 | GPIO High speed 11 |
GPIOHS12 | GPIO High speed 12 |
GPIOHS13 | GPIO High speed 13 |
GPIOHS14 | GPIO High speed 14 |
GPIOHS15 | GPIO High speed 15 |
GPIOHS16 | GPIO High speed 16 |
GPIOHS17 | GPIO High speed 17 |
GPIOHS18 | GPIO High speed 18 |
GPIOHS19 | GPIO High speed 19 |
GPIOHS20 | GPIO High speed 20 |
GPIOHS21 | GPIO High speed 21 |
GPIOHS22 | GPIO High speed 22 |
GPIOHS23 | GPIO High speed 23 |
GPIOHS24 | GPIO High speed 24 |
GPIOHS25 | GPIO High speed 25 |
GPIOHS26 | GPIO High speed 26 |
GPIOHS27 | GPIO High speed 27 |
GPIOHS28 | GPIO High speed 28 |
GPIOHS29 | GPIO High speed 29 |
GPIOHS30 | GPIO High speed 30 |
GPIOHS31 | GPIO High speed 31 |
GPIO0 | GPIO pin 0 |
GPIO1 | GPIO pin 1 |
GPIO2 | GPIO pin 2 |
GPIO3 | GPIO pin 3 |
GPIO4 | GPIO pin 4 |
GPIO5 | GPIO pin 5 |
GPIO6 | GPIO pin 6 |
GPIO7 | GPIO pin 7 |
UART1_RX | UART1 Receiver |
UART1_TX | UART1 Transmitter |
UART2_RX | UART2 Receiver |
UART2_TX | UART2 Transmitter |
UART3_RX | UART3 Receiver |
UART3_TX | UART3 Transmitter |
SPI1_D0 | SPI1 Data 0 |
SPI1_D1 | SPI1 Data 1 |
SPI1_D2 | SPI1 Data 2 |
SPI1_D3 | SPI1 Data 3 |
SPI1_D4 | SPI1 Data 4 |
SPI1_D5 | SPI1 Data 5 |
SPI1_D6 | SPI1 Data 6 |
SPI1_D7 | SPI1 Data 7 |
SPI1_SS0 | SPI1 Chip Select 0 |
SPI1_SS1 | SPI1 Chip Select 1 |
SPI1_SS2 | SPI1 Chip Select 2 |
SPI1_SS3 | SPI1 Chip Select 3 |
SPI1_ARB | SPI1 Arbitration |
SPI1_SCLK | SPI1 Serial Clock |
SPI_SLAVE_D0 | SPI Slave Data 0 |
SPI_SLAVE_SS | SPI Slave Select |
SPI_SLAVE_SCLK | SPI Slave Serial Clock |
I2S0_MCLK | I2S0 Master Clock |
I2S0_SCLK | I2S0 Serial Clock(BCLK) |
I2S0_WS | I2S0 Word Select(LRCLK) |
I2S0_IN_D0 | I2S0 Serial Data Input 0 |
I2S0_IN_D1 | I2S0 Serial Data Input 1 |
I2S0_IN_D2 | I2S0 Serial Data Input 2 |
I2S0_IN_D3 | I2S0 Serial Data Input 3 |
I2S0_OUT_D0 | I2S0 Serial Data Output 0 |
I2S0_OUT_D1 | I2S0 Serial Data Output 1 |
I2S0_OUT_D2 | I2S0 Serial Data Output 2 |
I2S0_OUT_D3 | I2S0 Serial Data Output 3 |
I2S1_MCLK | I2S1 Master Clock |
I2S1_SCLK | I2S1 Serial Clock(BCLK) |
I2S1_WS | I2S1 Word Select(LRCLK) |
I2S1_IN_D0 | I2S1 Serial Data Input 0 |
I2S1_IN_D1 | I2S1 Serial Data Input 1 |
I2S1_IN_D2 | I2S1 Serial Data Input 2 |
I2S1_IN_D3 | I2S1 Serial Data Input 3 |
I2S1_OUT_D0 | I2S1 Serial Data Output 0 |
I2S1_OUT_D1 | I2S1 Serial Data Output 1 |
I2S1_OUT_D2 | I2S1 Serial Data Output 2 |
I2S1_OUT_D3 | I2S1 Serial Data Output 3 |
I2S2_MCLK | I2S2 Master Clock |
I2S2_SCLK | I2S2 Serial Clock(BCLK) |
I2S2_WS | I2S2 Word Select(LRCLK) |
I2S2_IN_D0 | I2S2 Serial Data Input 0 |
I2S2_IN_D1 | I2S2 Serial Data Input 1 |
I2S2_IN_D2 | I2S2 Serial Data Input 2 |
I2S2_IN_D3 | I2S2 Serial Data Input 3 |
I2S2_OUT_D0 | I2S2 Serial Data Output 0 |
I2S2_OUT_D1 | I2S2 Serial Data Output 1 |
I2S2_OUT_D2 | I2S2 Serial Data Output 2 |
I2S2_OUT_D3 | I2S2 Serial Data Output 3 |
RESV0 | Reserved function |
RESV1 | Reserved function |
RESV2 | Reserved function |
RESV3 | Reserved function |
RESV4 | Reserved function |
RESV5 | Reserved function |
I2C0_SCLK | I2C0 Serial Clock |
I2C0_SDA | I2C0 Serial Data |
I2C1_SCLK | I2C1 Serial Clock |
I2C1_SDA | I2C1 Serial Data |
I2C2_SCLK | I2C2 Serial Clock |
I2C2_SDA | I2C2 Serial Data |
CMOS_XCLK | DVP System Clock |
CMOS_RST | DVP System Reset |
CMOS_PWDN | DVP Power Down Mode |
CMOS_VSYNC | DVP Vertical Sync |
CMOS_HREF | DVP Horizontal Reference output |
CMOS_PCLK | Pixel Clock |
CMOS_D0 | Data Bit 0 |
CMOS_D1 | Data Bit 1 |
CMOS_D2 | Data Bit 2 |
CMOS_D3 | Data Bit 3 |
CMOS_D4 | Data Bit 4 |
CMOS_D5 | Data Bit 5 |
CMOS_D6 | Data Bit 6 |
CMOS_D7 | Data Bit 7 |
SCCB_SCLK | SCCB Serial Clock |
SCCB_SDA | SCCB Serial Data |
UART1_CTS | UART1 Clear To Send |
UART1_DSR | UART1 Data Set Ready |
UART1_DCD | UART1 Data Carrier Detect |
UART1_RI | UART1 Ring Indicator |
UART1_SIR_IN | UART1 Serial Infrared Input |
UART1_DTR | UART1 Data Terminal Ready |
UART1_RTS | UART1 Request To Send |
UART1_OUT2 | UART1 User-designated Output 2 |
UART1_OUT1 | UART1 User-designated Output 1 |
UART1_SIR_OUT | UART1 Serial Infrared Output |
UART1_BAUD | UART1 Transmit Clock Output |
UART1_RE | UART1 Receiver Output Enable |
UART1_DE | UART1 Driver Output Enable |
UART1_RS485_EN | UART1 RS485 Enable |
UART2_CTS | UART2 Clear To Send |
UART2_DSR | UART2 Data Set Ready |
UART2_DCD | UART2 Data Carrier Detect |
UART2_RI | UART2 Ring Indicator |
UART2_SIR_IN | UART2 Serial Infrared Input |
UART2_DTR | UART2 Data Terminal Ready |
UART2_RTS | UART2 Request To Send |
UART2_OUT2 | UART2 User-designated Output 2 |
UART2_OUT1 | UART2 User-designated Output 1 |
UART2_SIR_OUT | UART2 Serial Infrared Output |
UART2_BAUD | UART2 Transmit Clock Output |
UART2_RE | UART2 Receiver Output Enable |
UART2_DE | UART2 Driver Output Enable |
UART2_RS485_EN | UART2 RS485 Enable |
UART3_CTS | UART3 Clear To Send |
UART3_DSR | UART3 Data Set Ready |
UART3_DCD | UART3 Data Carrier Detect |
UART3_RI | UART3 Ring Indicator |
UART3_SIR_IN | UART3 Serial Infrared Input |
UART3_DTR | UART3 Data Terminal Ready |
UART3_RTS | UART3 Request To Send |
UART3_OUT2 | UART3 User-designated Output 2 |
UART3_OUT1 | UART3 User-designated Output 1 |
UART3_SIR_OUT | UART3 Serial Infrared Output |
UART3_BAUD | UART3 Transmit Clock Output |
UART3_RE | UART3 Receiver Output Enable |
UART3_DE | UART3 Driver Output Enable |
UART3_RS485_EN | UART3 RS485 Enable |
TIMER0_TOGGLE1 | TIMER0 Toggle Output 1 |
TIMER0_TOGGLE2 | TIMER0 Toggle Output 2 |
TIMER0_TOGGLE3 | TIMER0 Toggle Output 3 |
TIMER0_TOGGLE4 | TIMER0 Toggle Output 4 |
TIMER1_TOGGLE1 | TIMER1 Toggle Output 1 |
TIMER1_TOGGLE2 | TIMER1 Toggle Output 2 |
TIMER1_TOGGLE3 | TIMER1 Toggle Output 3 |
TIMER1_TOGGLE4 | TIMER1 Toggle Output 4 |
TIMER2_TOGGLE1 | TIMER2 Toggle Output 1 |
TIMER2_TOGGLE2 | TIMER2 Toggle Output 2 |
TIMER2_TOGGLE3 | TIMER2 Toggle Output 3 |
TIMER2_TOGGLE4 | TIMER2 Toggle Output 4 |
CLK_SPI2 | Clock SPI2 |
CLK_I2C2 | Clock I2C2 |