简单来讲,若是你经过检索从而看到这篇文章,那就假设你已经知道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/
欢迎你们讨论与指正~!
以上。