The stm32 microcontroller uploads the received color and RGB value of the GY_33 color sensor to the host computer through serial communication

Table of contents

 hardware connection

Realize mutual communication between serial port 1 and serial port 3

Overview of GY_33

Data analysis on GY_33

GY_33 Data processing

Supporting software for GY_33

the code


Main idea: Note: Here I use serial port 1 and serial port 3, you can change the serial port

                   1. The upper computer sends data to the stm32 microcontroller through serial port 1

                   2.stm32 sends data to GY_33 through serial port 3

                   3. GY_33 sends data to stm32 MCU through serial port 3

                   4. After the stm32 processes the data, it sends the data to the host through the serial port 1

Required : stm32 single-chip microcomputer ( the punctual atom stm32mini board is used here ), GY_33 sensor, GY_33 supporting software, serial port assistant, USB to TTL

The following are the supporting materials and software links of GY_33

GY-33_Free high-speed download|Baidu SkyDrive-Share unlimited


 hardware connection

The serial port 1 and serial port 3 are used here.

According to the chip diagram of the mini board

                                          The pins of serial port 1 are PA10(RX), PA9(TX)

                      

                                         The pins of serial port 3 are PB10(TX), PB11(RX)

GY_33 hardware diagram, DR(RX), CT(TX)                              

 So according to output->receiver, receiver->output:

Connection of GY_33:

1.VCC->3V3

2.GND->GND

3.DR->PB10

4.CT->PB11

stm32 MCU connection (there is no need to operate this step if the wiring cap is connected):

1.PA10->TXD

2.PA9->RXD

Host computer: plug in the usb

Realize mutual communication between serial port 1 and serial port 3

Idea: After the serial port 1 receives the data, enter the serial port 1 interrupt, save the data received by the serial port 1, and send it to the

GY_33. (Same for serial port 3)

code show as below

void USART1_IRQHandler ()//串口1中断
{
	
	if(USART_GetITStatus(USART1,USART_IT_RXNE))//如果接收到数据
	{   u8 data;
		data=USART_ReceiveData(USART1);//赋值	
		USART_SendData(USART3,data);//发给传感器
	}
}

Overview of GY_33

GY-33 is a low-cost color recognition sensor module. Working voltage 3-5v, low power consumption, small size, easy installation. Its working principle is that the lighting LED emits light, and after irradiating the object to be measured, the returned light passes through the filter to detect the ratio value of RGB, and the color is recognized according to the ratio value of RGB. There are two ways to read data in this module, namely serial port UART (TTL level) or IIC (2-wire). The baud rate of the serial port is 9600bps and 115200bps, which can be configured. There are two modes of continuous and query output, and the settings can be saved after power-off. There are simple 7 kinds of color recognition, no need to calculate RGB values. It can adapt to different working environments and connect with single-chip microcomputer and computer. In addition, the module can set the working mode of a separate sensor chip. As a simple sensor module, the MCU does not participate in data processing. 

To put it simply, it can identify different colors and feed back different data. Let us identify colors through feedback data, which can be applied to color recognition modules such as smart cars.

Data analysis on GY_33

1. The output format of GY_33:

 Analysis: 1. 0x5A 0X5A in Byte0 and Byte1 represents the start of a new data transmission

             2. The value in Byte2 represents the type of data sent (will be described in detail below)

             3. Byte3 represents several data to be sent (not including the checksum), and Byte3=6 in the figure, so the following Byte4-Byte9 is the valid data to be sent, and Byte10 is the checksum (that is, add up all the previous data (including the frame header), only the sum of the eighth bit is reserved), to check whether the data it sends is error-free (can reduce errors, but cannot be avoided, imprecise)

2. GY_33 data analysis

Since we are using the serial port mode, it will only send three kinds of data: 0x15, 0x25, 0x45

 Analysis of three data examples

1.Byte2=0x15(RGBC)

For example, send the following string of codes (hexadecimal)

<5A-5A-15-08-01-78-01-92-00-4C-05-05-33 > 

5A 5A is the prefix 0x15 is the data type, indicating that the original RGBC value is sent 08 is the eight data sent

 We can calculate the values ​​of R, G, B, and C through this string of data

2.Byte2=0x25 (brightness, color temperature, color)

For example, send the following string of codes (hexadecimal)

< 5A-5A-25-06-02-CC-0C-5D-00-02-18 > 

5A 5A is the prefix 0x25 is the data type, which means sending brightness, color temperature, color 06 is sending 6 data

 The calculation of brightness and color temperature is very simple, a bit operation is performed, and the value of the color is converted into binary, which bit is 1

It is bright, for example, color is equal to 4, converted to binary system is 100, then bit2 is 1, so it is pink.

3.Byte=0x45 (processed RGB value)

 This piece of data is the data of Byte=0x15, the R, G, B values ​​calculated by the MCU

 It is easy to see that 5A 5A is the frame header, 0x45 represents the data type, and 03 represents three valid data

The first digit is R: FF The second digit G: FF The third digit B: 4C The fourth digit is the checksum

GY_33 Data processing

Since the sensor will send out three types of data, and each type of data contains a different number of numbers, we need to select one type of data, process it, return the RGB value, and judge the color.

The data of Byte=0x45 is selected here, that is, the processed RGB value, and the method of receiving other types of data is similar.

<5A-5A-15-08-01-78-01-92-00-4C-05-05-33 > (Byte2=0x15)

< 5A-5A-25-06-02-CC-0C-5D-00-02-18 > (Byte2=0x25)

<5A-5A-45-03-FF-FF-4C-46> (Byte2=0x45)

Note: Although the three types of data have different lengths, the same type of data has the same length

It is easy to see that the data types and lengths of the 3 are different, but the sensor will send them together, for example

5A 5A 15 08 01 78 01 92 00 4C 05 05 33 5A 5A 25 06 02 CC 0C 5D 00 02 18 5A 5A 45 03 FF F 4C 46 5A 5A 15 08 01 78 01 92 00 4C 05 05 33 5A 5A 25  06  02 CC 0C 5D 00 02 18  5A 5A 45 03 FF F 4C 46 (darken the color for clarity)

In such a large amount of data, we need to extract the data 5A 5A 45 03 FF F 4C 46 , as long as we find the difference between this string of data, it is not difficult to find that the format of this string of data starts with 5A 5A 45, that is to say, we After receiving the connected data of 5A 5A 45, we will start to accept the data we want (5A 5A 45 03 (more precise) can also be used)

The code is implemented as follows

if(USART_GetITStatus(USART3,USART_IT_RXNE))//如果接收到数据,进入串口3中断
	{
		int data;//
		u8 result;
		static int i=0,temp1,temp2,staus=0,j=0,staus2=0,temp3=1,temp4=2,temp5=3;
		data=USART_ReceiveData(USART3);//赋值	
		if(data==0x5A){staus2=1;}//如果接收到帧头开始准备接受数据
		if(staus2)//测试是否是我们所需的数据
		{
			j++;
			if(j==1){temp3=data;}//将第一个帧头保存下来
			if(j==2){temp4=data;}//第二个帧头保存下来
			if(j==3)
				{
					temp5=data;//保存数据类型
                    j=0;//归0
					if(temp5==0x45&&temp4==0x5A&&temp3==0X5A)//符合我们所需类型
					{
						staus2=0;//关闭测试
						staus=1;//数据类型正确,开启接受数据
					}
		        }
		 }
		if (staus)//接收数据
		{	
			  i++;
			  if(i==3){ temp1 = data;}//存放R
			  if(i==4){ temp2 = data;}//存放G
			  if(i==5)
				   {   delay_us(20);/*延时避免数据传输过快导致错误,单个中断时可用,多中断不行,该中断完成时间太久,未完成任务就被其他中断打断*/
					   //判断颜色(通过实际测试得)
					  if(temp1>=255&&temp2>=255&&data>=255)
					  {
						  printf("R:%d   G:%d   B:%d   白色\r\n",temp1,temp2,data);
					  }
                     if(temp1<=40&&temp2<=40&&data<=40)
					  {
						  printf("R:%d   G:%d   B:%d   黑色\r\n",temp1,temp2,data);
					  }
					  else
					  {	  
	                     if(temp2>temp1&&temp2>data)
						  {
							  printf("R:%d   G:%d   B:%d   绿色\r\n",temp1,temp2,data);
						  }
	                     if(temp1>temp2&&temp1>data)
						  {
							  printf("R:%d   G:%d   B:%d   红色\r\n",temp1,temp2,data);
						  }
					       if(data>temp1&&data>temp2)
						  {
							  printf("R:%d   G:%d   B:%d   蓝色\r\n",temp1,temp2,data);
						  }					  
					  }    					  					
					  i = 0;//发送完毕,接受新数据
					  staus = 0;//关闭数据接受状态
				  }
		}					
		
	}

Supporting software for GY_33

The following commands are required for this time

 

 The implementation of this command can be directly connected to the sensor through USB to TTL, and the GY_33 can be directly configured through the supporting software in the above figure.

Note, to adjust the white balance, the debugging method is to point the sensor at the white object, and then send the white balance command, otherwise the sensor data will be inaccurate because there is no reference object.

Command sending can be realized by the following software.

1. Serial port assistant (note: choose hexadecimal to send)

 2.COLOR

the code

 According to the agreement to initialize the serial port parameters, the following is the complete code

#include "stm32f10x.h"
#include "stdio.h"
#include "delay.h"
void USART1_Init(void)//初始化串口1
{
	GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体
	USART_InitTypeDef USART_InitStructure;//定义串口结构体
	NVIC_InitTypeDef NVIC_InitStructure;//定义优先级结构体
	//使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE);//使能串口1
	//发送TX
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//PA9
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA
	//接收RX
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA
	//串口
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//不使用硬件
	USART_InitStructure.USART_BaudRate=9600;//波特率
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验关闭
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长
	USART_Init(USART1,&USART_InitStructure);//初始化串口1
	//优先级配置
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口1中断
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能串口1中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级
	NVIC_Init(&NVIC_InitStructure);//初始化优先级
	//使能
	USART_Cmd(USART1,ENABLE);//使能串口
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接收缓存非空寄存器
}
void USART3_Init(void)//初始化串口3
{
	GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体
	USART_InitTypeDef USART_InitStructure;//定义串口结构体
	NVIC_InitTypeDef NVIC_InitStructure;//定义优先级结构体
	//使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 ,ENABLE);//使能串口3
	//发送TX
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//PB10
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB
	//接收RX
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;//PB11
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB
	//串口
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//不使用硬件
	USART_InitStructure.USART_BaudRate=9600;//波特率
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验关闭
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长
	USART_Init(USART3,&USART_InitStructure);//初始化串口3
	//优先级配置
	NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;//串口3中断
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能串口3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级
	NVIC_Init(&NVIC_InitStructure);//初始化优先级
	//使能
	USART_Cmd(USART3,ENABLE);//使能串口3
	USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//使能接收缓存非空寄存器
}
void USART1_IRQHandler ()//串口1中断
{
	
	if(USART_GetITStatus(USART1,USART_IT_RXNE))//如果接收到数据
	{   u8 data;
		data=USART_ReceiveData(USART1);//赋值	
		USART_SendData(USART3,data);//发给传感器
	}
}
void USART3_IRQHandler()//串口3中断
{

	if(USART_GetITStatus(USART3,USART_IT_RXNE))//如果接收到数据
	{
		int data;
		u8 result;
		static int i=0,temp1,temp2,staus=0,j=0,staus2=0,temp3=1,temp4=2,temp5=3;
		data=USART_ReceiveData(USART3);//赋值	
		if(data==0x5A){staus2=1;}//如果接收到帧头开始准备接受数据
		if(staus2)//测试是否所需数据
		{
			j++;
			if(j==1){temp3=data;}保存第一个数
			if(j==2){temp4=data;}保存第二个数
			if(j==3)
				{
					temp5=data;j=0;
					if(temp5==0x45&&temp4==0x5A&&temp3==0X5A)//如果数据为0X5A 0X5A,0X45
					{
						staus2=0;//关闭测试
						staus=1;//前缀正确,开启接受数据
					}
		        }
		 }
		if (staus)//接收数据
		{	
			  i++;
			  if(i==3){ temp1 = data;}//存放R
			  if(i==4){ temp2 = data;}//存放G
			  if(i==5)
				   {   delay_us(20);//延时避免数据传输过快导致错误
					   //判断颜色
					  if(temp1>=255&&temp2>=255&&data>=255)
					  {
						  printf("R:%d   G:%d   B:%d   白色\r\n",temp1,temp2,data);
					  }
                     if(temp1<=40&&temp2<=40&&data<=40)
					  {
						  printf("R:%d   G:%d   B:%d   黑色\r\n",temp1,temp2,data);
					  }
					  else
					  {	  
	                     if(temp2>temp1&&temp2>data)
						  {
							  printf("R:%d   G:%d   B:%d   绿色\r\n",temp1,temp2,data);
						  }
	                     if(temp1>temp2&&temp1>data)
						  {
							  printf("R:%d   G:%d   B:%d   红色\r\n",temp1,temp2,data);
						  }
					       if(data>temp1&&data>temp2)
						  {
							  printf("R:%d   G:%d   B:%d   蓝色\r\n",temp1,temp2,data);
						  }					  
					  }    					  					
					  i = 0;//发送完毕,接受新数据
					  staus = 0;//关闭数据接受状态
				  }
		}					
		
	}
}
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	USART1_Init();
	USART3_Init();
	delay_init();
	while(1);        
}
//print所需函数
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
int handle; 
};  
FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
USART1->DR = (u8) ch;      
return ch;
}
#endif

Guess you like

Origin blog.csdn.net/A15768533126/article/details/121043023