stm32单片机使用串口通信连接GY-33颜色传感器完成对颜色的识别并且打印出其颜色和对应的RGB值
Posted 不 凡.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32单片机使用串口通信连接GY-33颜色传感器完成对颜色的识别并且打印出其颜色和对应的RGB值相关的知识,希望对你有一定的参考价值。
目录
所需: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进制发送勾选上,波特率停止位等配置按如下)
打开串口就可以接收到打印的数据了
完成此次任务,我发现对信息的筛选及整合能力很关键,最重要的应该是先搞明白原理。
以上是关于stm32单片机使用串口通信连接GY-33颜色传感器完成对颜色的识别并且打印出其颜色和对应的RGB值的主要内容,如果未能解决你的问题,请参考以下文章