pixy php,Pixy2与STM32进行SPI通信
簡單來說,如果你通過檢索從而看到這篇文章,那就假設你已經(jīng)知道Pixy2是用來干什么的(一款功能強大的開源視覺傳感器),以及你已擁有一些STM32基礎。你可以通過訪問官方手冊來獲得更多關于Pixy2的相關信息。
如果你已經(jīng)非常了解Pixy2的運作模式,只是想快速與STM32建立通信,那么你可以直接參考我的代碼:
通常情況下Pixy2是搭配Arduino使用的,并且Pixy2能通過SPI以2 Mbits/秒的速度向Arduino發(fā)送信息。不過如果讓Pixy2與不同的平臺進行通信,首先就要確定以哪種方式進行通信。官方給出Pixy2支持的通信方式有SPI、I2C、UART、USB和Analog/digital,并且通信速度USB>SPI>I2C>UART>A/D。本文將具體描述Pixy2與STM32的SPI通信。
設置與連接
首先,你需要去官網(wǎng)下載一個叫PixyMon的軟件,它能讓你在Windows或Mac平臺對Pixy2進行設置。
將你的Pixy2與電腦用USB線連接后,打開軟件,在Configure-Interface-Data out port選項中,我們選擇Arduino ICSP SPI。是的,即使是與Arduino通信的SPI選項,也可以應用到STM32上,其他選項不用更改。
設置好后,我們把Pixy2與電腦連接的USB斷開,用杜邦線將Pixy2與STM32連接,我這里用的STM32是正點原子的STM32mini開發(fā)板。在連接之前,我們先看一下Pixy2的管腳圖:
在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)
串口協(xié)議
Pixy2是以數(shù)據(jù)包的形式來和上位機進行通信的,也就是說,想要和Pixy2通信,你必須向Pixy2發(fā)送一個請求數(shù)據(jù)包,然后Pixy2再把你想要得到的數(shù)據(jù)或者狀態(tài)用數(shù)據(jù)包發(fā)給你。所以你的請求/反饋數(shù)據(jù)包就像下面的格式:
Requests-(你發(fā)給pixy的)
字節(jié)
說明
數(shù)值
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發(fā)給你的)
字節(jié)
說明
數(shù)值
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)
就拿請求數(shù)據(jù)包來說,上位機向Pixy2發(fā)送長度為 len 字節(jié)的數(shù)據(jù)包,其中0-1字節(jié)是同步碼,同步碼又分為:
帶校驗位的同步碼 0xc1af
不帶校驗位的同步碼 0xc1ae
所以你的請求數(shù)據(jù)包里的0-1字節(jié)一般是固定的,然后剩下的字節(jié)根據(jù)你想要Pixy2反饋的功能來改變。至于每種功能的詳細格式,官網(wǎng)的手冊已經(jīng)詳細列出了,你細品。
Pixy2收到上位機發(fā)送的數(shù)據(jù)包后,會根據(jù)要求返送一個包含著數(shù)據(jù)的包,也是以同步碼打頭,后面跟著就是你想要的數(shù)據(jù)了,不同的請求數(shù)據(jù)包有不同的反饋數(shù)據(jù)包,至于Pixy2發(fā)出的同步碼有什么用,我們會在實例中具體講述。你可以用UART串口把這些數(shù)據(jù)打印在電腦屏幕上,這會更好的幫助你了解Pixy2的通信原理。
實例1
現(xiàn)在,就以STM32用SPI通信向Pixy2發(fā)送一個請求版本的數(shù)據(jù)包,來獲取Pixy2版本,并將Pixy2返回的數(shù)據(jù)打印在屏幕上的一個實例。
根據(jù)官網(wǎng)的說明:
getVersion()
Request:
字節(jié)
說明
數(shù)值
0-1
16-bit sync
174, 193 (0xc1ae)
2
Type of packet
14
3
Length of payload
0
就是說,你想獲取Pixy2的版本,你要發(fā)送4個字節(jié)的數(shù)據(jù)包給Pixy查詢,前兩個字節(jié)是同步碼,第三個是14,第四個是0,我們來看看,怎么樣用Keil來寫這個發(fā)送數(shù)據(jù)包的程序。
#define PIXY_CHECKSUM_SYNC 0xc1af //帶校驗位的同步碼
#define PIXY_NO_CHECKSUM_SYNC 0xc1ae //不帶校驗位的同步碼
#define GETVERSION_LENSEND 4 //發(fā)送數(shù)據(jù)包長度
#define GETVERSION_LENRECEIVED 22 //接收數(shù)據(jù)包長度,先假設是22個字節(jié)
uint8_t i, header_buf[16]; //header_buf用來存放發(fā)送的數(shù)據(jù)
uint8_t recvBuf[32]; //recvBuf用來存放接收到的數(shù)據(jù)
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
SPI1_ReadWriteByte(header_buf[i]);
for(i=0;i
received[i]=SPI1_ReadWriteByte(0XFF);
}
int main(void)
{
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES) //WK_UP按下后就發(fā)送版本查詢數(shù)據(jù)包
{
Pixy2_SendRecvPacket_getVersion(recvBuf); //發(fā)送并接收數(shù)據(jù)
printf("Received %d bytes.\r\n", GETVERSION_LENRECEIVED);
for (i=0; i
printf("%hhu: %#x\r\n", i, recvBuf[i]);
}
}
}
跟著注釋,是不是也不難看懂?雖然這些程序并不完整,但它能夠完整的表達與Pixy2通信的整個過程。按下開發(fā)板上WK_UP按鍵后,發(fā)送并接收數(shù)據(jù)包,然后用串口顯示接收到的字節(jié),我們打開串口調(diào)試助手來康康:
仔細看,接收到的字節(jié),第一個是0x6c,第二個是0,講道理不應該是0xaf和0xc1嗎?因為Pixy2發(fā)送的數(shù)據(jù)包,一定會以同步碼打頭,那現(xiàn)在接收到的這兩個是啥東西?我也不知道,但我知道這兩個數(shù)據(jù)肯定不是我們想要的。可以看到字節(jié)7,8,9分別是0xaf,0xaf,0xc1。有兩個0xaf,而且好像字節(jié)8,9是我們想要的同步碼,那是不是可以寫一個語句來判斷字節(jié)7如果是0xaf,那么接下來所有的數(shù)據(jù)都是我們想要的,所以只用將字節(jié)7之后的字節(jié)放入recvBuf[]就行了呢?看如下的程序:
uint8_t PIXY_GET_FLAG_AF=0XAF;//af標志字節(jié)
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
SPI1_ReadWriteByte(header_buf[i]);
//接收數(shù)據(jù)但不寫入received[]直到接收到的數(shù)據(jù)為0xaf
while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF));
//接收第二個0xaf以及之后的字節(jié)
for(i=0;i
received[i]=SPI1_ReadWriteByte(0XFF);
}
對之前的程序進行修改,加入了一行關鍵語句,我們再來看看串口調(diào)試助手的輸出:
好像有點像我們希望看到的數(shù)據(jù)了,其實在官網(wǎng)上有一段說明,就是通過向Pixy2發(fā)送獲取版本(getVersion())數(shù)據(jù)包,你會得到的字節(jié),如下圖:
對比看下我們獲得的字節(jié),發(fā)現(xiàn)我們的數(shù)據(jù)是正確的(雖然根據(jù)版本不同,數(shù)據(jù)可能不同),程序也是可行的。
還能通過STM32來獲取Pixy2看到色塊的坐標,如下圖:
其實Pixy2是一款非常好玩的視覺傳感器,它能應用到許多場合,在它的官網(wǎng)手冊中列出了所有的功能數(shù)據(jù)包格式,獲取版本就是其中之一,每種功能包的格式以請求數(shù)據(jù)包格式和其對應的反饋數(shù)據(jù)包格式給出,你可以根據(jù)手冊中的請求數(shù)據(jù)包格式來寫程序,然后對比手冊中的反饋數(shù)據(jù)包格式和你真正接收到的數(shù)據(jù),看看自己的程序是否有效。下面列出了一些我寫的,認為比較重要的一些請求數(shù)據(jù)包程序庫,你可以根據(jù)我的格式來寫其他你需要的功能程序庫,當然你也可以用更優(yōu)化的方法來自己寫。
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
SPI1_ReadWriteByte(header_buf[i]);
while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF));
for(i=0;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
SPI1_ReadWriteByte(header_buf[i]);
while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF));
for(i=0;i
received[i]=SPI1_ReadWriteByte(0XFF);
}
//setCameraBrightness()調(diào)節(jié)相機亮度
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
SPI1_ReadWriteByte(header_buf[i]);
while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF));
for(i=0;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
SPI1_ReadWriteByte(header_buf[i]);
while (PIXY_GET_FLAG_AF!=SPI1_ReadWriteByte(0XFF));
for(i=0;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來參考:
歡迎大家討論與指正~!
以上。
總結(jié)
以上是生活随笔為你收集整理的pixy php,Pixy2与STM32进行SPI通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wacom linux 驱动下载,Dri
- 下一篇: pixy php,Pixy快速入门指南.