stm32单片机使用串口通信连接GY-33颜色传感器完成对颜色的识别并且打印出其颜色和对应的RGB值

目录

1.GY-33介绍及其接线

2.通信原理

3.代码

4.GY-33发送出来的数据及如何处理数据​

5.软件使用

所需:stm32单片机(这里使用的是正点原子stm32mini板),GY_33传感器,GY_33配套软件,串口助手,USB转TTL


1.GY-33介绍及其接线

GY-33是一款低成本颜色识别传感器模块。工作电压3-5v,功耗小,体积小,安装方便。其工作原理是,照明LED发光,照射到被测物体后,返回光经过滤镜检测RGB的比例值,根据RGB的比例值识别出颜色。此模块,有两种方式读取数据,即串口UART(TTL电平)或者IIC(2线)。串口的波特率有9600bps与115200bps,可配置,有连续,询问输出两种方式,其响应频率为10hz。具体资料查看

http://pan.baidu.com/s/1kVq51dl

                                                                                                                  先来看看GY-33的实物及其接线

我们只需要焊接排针在这四位上,然后用杜邦线把这四位同stm32对应的引脚连接即可,由于我设置GY-33通过串口3同stm32通信 ,根据原理图DR应该连接PB10,CT应该连接PB11

  

2.通信原理

首先我们得先了解GY-33是怎么通过stm32和上位机完成通信的(这一步至关重要,如果连这个过程是怎样进行的都不知道,那就像无头苍蝇,永远完成不了这个功能)--------------

思路是1. 上位机通过串口1发送指令到stm32                                                                 2.stm32再通过串口3把指令发到GY-33颜色传感器                                                          3.GY-33接受到指令后会自动输出其测量的颜色对应的数据(第四部分会讲数据类型及数据处理)回串口3                                                                                                                            4.串口3接受到数据后中断,我们可以在串口3中断函数里对数据进行处理,从而提取出RGB值并打印出对应的颜色和RGB值

(文字看着腻歪,直接看下图通信思路及实现方法)

3.代码

 先看看串口的通信协议

程序应该按通信协议设置

 话不多说,直接上代码(看串口3中断函数代码前可以先看第四部分)

#include "stm32f10x.h"
#include "stdio.h"//printf函数

void USART1_Init(void)
{
	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;//根据GY-33响应频率10hz
	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;//根据GY-33响应频率10hz
	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);//使能串口1
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接收缓存非空寄存器
}
void USART3_Init(void)
{
	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;//根据GY-33响应频率10hz
	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);//串口3发送指令给传感器
	}
}
void USART3_IRQHandler()
{

	if(USART_GetITStatus(USART3,USART_IT_RXNE))//如果接收到数据
	{
		u8 data;
		static int result1,result2,result3;//静态保存
		static int i=0,staus=0,j=0,staus2=0,temp1=0,temp2=0,temp3=0;
		data=USART_ReceiveData(USART3);//赋值	
		if(data==0x5A)
			staus2=1;
		if(staus2)
		{
			j++;
			if(j==1)temp1=data;
			if(j==2)temp2=data;
			if(j==3)
				{
					temp3=data;j=0;
					if(temp3==0x45&&temp2==0x5A&&temp1==0X5A)
					{
						staus2=0;
						staus=1;
					}
				}
		}//如果连续收到0x5a,0x5a,0x45,staus置1,进入下面数据处理
		if (staus)//将0x45看成第一位数据,保存第三,四,五位数据,分别对应红,绿,蓝的RGB值
		{
			i++;
			if(i==3)
				result1=USART_ReceiveData(USART3);
			if(i==4)
				result2=USART_ReceiveData(USART3);
			if(i==5)
			{
				result3=USART_ReceiveData(USART3);
				if(result1==255&&result2==255&&result3==255)//三者RGB值都为255即打印白色
					printf("R=%d G=%d B=%d 白色\r\n",result1,result2,result3);
				if(result1<50&&result2<50&&result3<50)//三者RGB值都比较小即为黑色
					printf("R=%d G=%d B=%d 黑色\r\n",result1,result2,result3);
				else
				{
				if(result1>result2&&result1>result3)//不符合三者RGB都大或都小的情况下,红色RGB值最大即打印红色
					printf("R=%d G=%d B=%d 红色\r\n",result1,result2,result3);
				if(result2>result1&&result2>result3)//不符合三者RGB都大或都小的情况下,绿色RGB值最大即打印绿色
					printf("R=%d G=%d B=%d 绿色\r\n",result1,result2,result3);
				if(result3>result2&&result1<result3)//不符合三者RGB都大或都小的情况下,蓝色RGB值最大即打印蓝色
					printf("R=%d G=%d B=%d 蓝色\r\n",result1,result2,result3);
			    }
				i=0;
				staus=0;
			}
		}
}
}
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	USART1_Init();
	USART3_Init();
	while(1);        
}
#if 1//调用printf函数所需代码
#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

4.GY-33发送出来的数据及如何处理数据

一共有三种不同的数据类型(0x15,0x25,0x45),每种数据都是以俩个0x5a开头(帧头 

GY-33发给串口3的数据由这三种不同的数据类型组成,例如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(不同数据类型用不同颜色)

并且每一种类型的数据所含数字的个数不同(每串数据的第四位数表示这串数据的有效数据个数,同种数据类型数字个数相同),我们需要选择一种数据类型来处理,这里我们就选择最简单的第三种数据进行处理吧

处理方法:首先得判断是第三种数据(依次接收到的数据是0x5a,0x5a,0x45)//若再判断下一位为0x03会更好,然后再把第三种数据的第五,六,七位取出来并打印(具体处理方法查看上面的代码)                                                                                                                            其他俩种数据类型根据上面表格也可处理,处理方法与第三种数据类型类似                                                                                                                                                                                                                      

5.软件使用

 在使用GY-33颜色传感器前,得先对其进行颜色白校准(使用COLOR,USA转ttl)usb转ttl直接连传感器,通过COLOR软件直接配置GY-33

 

 白校准后打开xcom(注:16进制发送勾选上,波特率停止位等配置按如下)

 打开串口就可以接收到打印的数据了

 完成此次任务,我发现对信息的筛选及整合能力很关键,最重要的应该是先搞明白原理。

版权声明:本文为CSDN博主「不 凡.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/A15889277233/article/details/121043188

生成海报
点赞 0

不 凡.

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里