簡單來講,若是你經過檢索從而看到這篇文章,那就假設你已經知道Pixy2是用來幹什麼的(一款功能強大的開源視覺傳感器),以及你已擁有一些STM32基礎。你能夠經過訪問官方手冊來得到更多關於Pixy2的相關信息。php
若是你已經很是瞭解Pixy2的運做模式,只是想快速與STM32創建通訊,那麼你能夠直接參考個人代碼:git
連接: https://pan.baidu.com/s/1AaIs...
提取碼:11qb
一般狀況下Pixy2是搭配Arduino使用的,而且Pixy2能經過SPI以2 Mbits/秒的速度向Arduino發送信息。不過若是讓Pixy2與不一樣的平臺進行通訊,首先就要肯定以哪一種方式進行通訊。官方給出Pixy2支持的通訊方式有SPI、I2C、UART、USB和Analog/digital,而且通訊速度USB>SPI>I2C>UART>A/D。本文將具體描述Pixy2與STM32的SPI通訊。ide
首先,你須要去官網下載一個叫PixyMon的軟件,它能讓你在Windows或Mac平臺對Pixy2進行設置。優化
將你的Pixy2與電腦用USB線鏈接後,打開軟件,在Configure-Interface-Data out port選項中,咱們選擇Arduino ICSP SPI。是的,即便是與Arduino通訊的SPI選項,也能夠應用到STM32上,其餘選項不用更改。ui
設置好後,咱們把Pixy2與電腦鏈接的USB斷開,用杜邦線將Pixy2與STM32鏈接,我這裏用的STM32是正點原子的STM32mini開發板。在鏈接以前,咱們先看一下Pixy2的管腳圖:spa
在Arduino ICSP SPI模式中主要用到(1)(3)(4)三個管腳,還有5V和GND與STM32的5V和GND直接相連就好了,二者具體的鏈接方法以下:調試
Pin 1
(SPI MISO) ➜ PA6
(STM32 SPI MISO signal)Pin 4
(SPI MOSI) ➜ PA7
(STM32 SPI MOSI signal)Pin 3
(SPI SCK) ➜ PA5
(STM32 SPI SCK signal)Pin 2
➜ 5V
(STM32 5V)Pin 6
➜ GND
(STM32 GND)Pixy2是以數據包的形式來和上位機進行通訊的,也就是說,想要和Pixy2通訊,你必須向Pixy2發送一個請求數據包,而後Pixy2再把你想要獲得的數據或者狀態用數據包發給你。因此你的請求/反饋數據包就像下面的格式:code
Requests-(你發給pixy的)blog
字節 | 說明 | 數值 |
---|---|---|
0-1 | 16-bit sync | 174, 193 (0xc1ae) |
2 | Type of packet | (varies) |
3 | Length of payload in bytes (len) | (varies) |
4-len | Variable length payload | (varies) |
Responses-(pixy發給你的)開發
字節 | 說明 | 數值 |
---|---|---|
0-1 | 16-bit sync | 175, 193 (0xc1af) |
2 | Type of packet | (varies) |
3 | Length of payload in bytes (len) | (varies) |
4-5 | 16-bit checksum | sum of payload bytes |
6-len | Variable length payload | (varies) |
就拿請求數據包來講,上位機向Pixy2發送長度爲 len
字節的數據包,其中0-1字節是同步碼,同步碼又分爲:
0xc1af
0xc1ae
因此你的請求數據包裏的0-1字節通常是固定的,而後剩下的字節根據你想要Pixy2反饋的功能來改變。至於每種功能的詳細格式,官網的手冊已經詳細列出了,你細品。
Pixy2收到上位機發送的數據包後,會根據要求返送一個包含着數據的包,也是以同步碼打頭,後面跟着就是你想要的數據了,不一樣的請求數據包有不一樣的反饋數據包,至於Pixy2發出的同步碼有什麼用,咱們會在實例中具體講述。你能夠用UART串口把這些數據打印在電腦屏幕上,這會更好的幫助你瞭解Pixy2的通訊原理。
如今,就以STM32用SPI通訊向Pixy2發送一個請求版本的數據包,來獲取Pixy2版本,並將Pixy2返回的數據打印在屏幕上的一個實例。
根據官網的說明:
getVersion()
Request:
字節 | 說明 | 數值 |
---|---|---|
0-1 | 16-bit sync | 174, 193 (0xc1ae) |
2 | Type of packet | 14 |
3 | Length of payload | 0 |
就是說,你想獲取Pixy2的版本,你要發送4個字節的數據包給Pixy查詢,前兩個字節是同步碼,第三個是14
,第四個是0
,咱們來看看,怎麼樣用Keil來寫這個發送數據包的程序。
#define PIXY_CHECKSUM_SYNC 0xc1af //帶校驗位的同步碼 #define PIXY_NO_CHECKSUM_SYNC 0xc1ae //不帶校驗位的同步碼 #define GETVERSION_LENSEND 4 //發送數據包長度 #define GETVERSION_LENRECEIVED 22 //接收數據包長度,先假設是22個字節 uint8_t i, header_buf[16]; //header_buf用來存放發送的數據 uint8_t recvBuf[32]; //recvBuf用來存放接收到的數據 void Pixy2_SendRecvPacket_getVersion(uint8_t* received) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; //把同步碼拆開 header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x0e; //14 header_buf[3] = 0x00; //0 for (i=0;i<GETVERSION_LENSEND;i++) //一個一個字節發給Pixy2 SPI1_ReadWriteByte(header_buf[i]); for(i=0;i<GETVERSION_LENRECEIVED;i++) //接收Pixy發來的數據 received[i]=SPI1_ReadWriteByte(0XFF); } int main(void) { while(1) { key=KEY_Scan(0); if(key==WKUP_PRES) //WK_UP按下後就發送版本查詢數據包 { Pixy2_SendRecvPacket_getVersion(recvBuf); //發送並接收數據 printf("Received %d bytes.\r\n", GETVERSION_LENRECEIVED); for (i=0; i<GETVERSION_LENRECEIVED; i++) //把每一個字節打印到串口 printf("%hhu: %#x\r\n", i, recvBuf[i]); } } }
跟着註釋,是否是也不難看懂?雖然這些程序並不完整,但它可以完整的表達與Pixy2通訊的整個過程。按下開發板上WK_UP按鍵後,發送並接收數據包,而後用串口顯示接收到的字節,咱們打開串口調試助手來康康:
仔細看,接收到的字節,第一個是0x6c
,第二個是0
,講道理不該該是0xaf
和0xc1
嗎?由於Pixy2發送的數據包,必定會以同步碼打頭,那如今接收到的這兩個是啥東西?我也不知道,但我知道這兩個數據確定不是咱們想要的。能夠看到字節7,8,9分別是0xaf
,0xaf
,0xc1
。有兩個0xaf
,並且好像字節8,9是咱們想要的同步碼,那是否是能夠寫一個語句來判斷字節7若是是0xaf
,那麼接下來全部的數據都是咱們想要的,因此只用將字節7以後的字節放入recvBuf[]
就好了呢?看以下的程序:
uint8_t PIXY_GET_FLAG_AF=0XAF;//af標誌字節 void Pixy2_SendRecvPacket_getVersion(uint8_t* received) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x0e; header_buf[3] = 0x00; for (i=0;i<GETVERSION_LENSEND;i++) SPI1_ReadWriteByte(header_buf[i]); //接收數據但不寫入received[]直到接收到的數據爲0xaf while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF)); //接收第二個0xaf以及以後的字節 for(i=0;i<GETVERSION_LENRECEIVED;i++) received[i]=SPI1_ReadWriteByte(0XFF); }
對以前的程序進行修改,加入了一行關鍵語句,咱們再來看看串口調試助手的輸出:
好像有點像咱們但願看到的數據了,其實在官網上有一段說明,就是經過向Pixy2發送獲取版本(getVersion())數據包,你會獲得的字節,以下圖:
對比看下咱們得到的字節,發現咱們的數據是正確的(雖然根據版本不一樣,數據可能不一樣),程序也是可行的。
還能經過STM32來獲取Pixy2看到色塊的座標,以下圖:
其實Pixy2是一款很是好玩的視覺傳感器,它能應用到許多場合,在它的官網手冊中列出了全部的功能數據包格式,獲取版本就是其中之一,每種功能包的格式以請求數據包格式和其對應的反饋數據包格式給出,你能夠根據手冊中的請求數據包格式來寫程序,而後對比手冊中的反饋數據包格式和你真正接收到的數據,看看本身的程序是否有效。下面列出了一些我寫的,認爲比較重要的一些請求數據包程序庫,你能夠根據個人格式來寫其餘你須要的功能程序庫,固然你也能夠用更優化的方法來本身寫。
pixy2.c
#include "delay.h" #include "sys.h" #include "spi.h" #include "pixy2.h" uint8_t i, header_buf[16], PIXY_GET_FLAG_AF=0XAF; //getVersion()獲取版本 void Pixy2_SendRecvPacket_getVersion(uint8_t* received) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x0e; header_buf[3] = 0x00; for (i=0;i<GETVERSION_LENSEND;i++) SPI1_ReadWriteByte(header_buf[i]); while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF)); for(i=0;i<GETVERSION_LENRECEIVED;i++) received[i]=SPI1_ReadWriteByte(0XFF); } //getBlocks()獲取色塊 void Pixy2_SendRecvPacket_getBlocks(uint8_t* received, uint8_t sigmap, uint8_t numBlocks) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x20; header_buf[3] = 0x02; header_buf[4] = sigmap; header_buf[5] = numBlocks; for (i=0;i<GETBLOCKS_LENSEND;i++) SPI1_ReadWriteByte(header_buf[i]); while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF)); for(i=0;i<GETBLOCKS_LENRECEIVED;i++) received[i]=SPI1_ReadWriteByte(0XFF); } //setCameraBrightness()調節相機亮度 void Pixy2_SendRecvPacket_setCameraBrightness(uint8_t* received, uint8_t brightness) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x10; header_buf[3] = 0x01; header_buf[4] = brightness; for (i=0;i<setBrightness_LENSEND;i++) SPI1_ReadWriteByte(header_buf[i]); while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF)); for(i=0;i<setBrightness_LENRECEIVED;i++) received[i]=SPI1_ReadWriteByte(0XFF); } //setLamp()開關照明燈 void Pixy2_SendRecvPacket_setLamp(uint8_t* received, uint8_t upper, uint8_t lower) { header_buf[0] = PIXY_NO_CHECKSUM_SYNC&0xff; header_buf[1] = PIXY_NO_CHECKSUM_SYNC>>8; header_buf[2] = 0x16; header_buf[3] = 0x02; header_buf[4] = upper; header_buf[5] = lower; for (i=0;i<setLamp_LENSEND;i++) SPI1_ReadWriteByte(header_buf[i]); while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF)); for(i=0;i<setLamp_LENRECEIVED;i++) received[i]=SPI1_ReadWriteByte(0XFF); }
pixy2.h
#ifndef __PIXY2_H #define __PIXY2_H #include "sys.h" #define PIXY_DEFAULT_ARGVAL 0x80000000 #define PIXY_BUFFERSIZE 0x104 #define PIXY_CHECKSUM_SYNC 0xc1af #define PIXY_NO_CHECKSUM_SYNC 0xc1ae #define PIXY_SEND_HEADER_SIZE 4 #define PIXY_MAX_PROGNAME 33 #define GETVERSION_LENSEND 4 #define GETVERSION_LENRECEIVED 22 #define GETBLOCKS_LENSEND 6 #define GETBLOCKS_LENRECEIVED 20 #define setBrightness_LENSEND 5 #define setBrightness_LENRECEIVED 10 #define setLamp_LENSEND 6 #define setLamp_LENRECEIVED 10 void Pixy2_SendRecvPacket_getVersion(uint8_t* received); void Pixy2_SendRecvPacket_getBlocks(uint8_t* received, uint8_t sigmap, uint8_t numBlocks); void Pixy2_SendRecvPacket_setCameraBrightness(uint8_t* received, uint8_t brightness); void Pixy2_SendRecvPacket_setLamp(uint8_t* received, uint8_t upper, uint8_t lower); #endif
固然,大家能夠下載整個project來參考:
連接: https://pan.baidu.com/s/1AaIs...
提取碼:11qb
傳送門:
Pixy2 Index:https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:start
How to talk to Pixy2:https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:porting_guide
Pixy2 Downloads:https://pixycam.com/downloads-pixy2/
歡迎你們討論與指正~!
以上。