STM32驱动TCS34725颜色识别传感器

简介

在这里插入图片描述

特征参数

1.红、绿、蓝(RGB)带有红外阻挡滤镜的透明光感应功能:
(1)可编程模拟增益和积分时间3800000: 1动态范围
(2)超高灵敏度–非常适合在深色玻璃后方使用
2.可屏蔽中断:具有持久性过滤器的可编程上限和下限阈值
3.电源管理
(1)低功耗,2.5uA休眠状态
(2)65uA等待状态,可编程等待状态时间从2.4 ms-0.7m
(3)工作电压:3.3-5V
4.接口类型:IIC接口
5.检测距离:3-10mm

功能框图

在这里插入图片描述

TCS34725光电数字转换器包含一个3X4像素的光电二极管阵列、四个整合光电二极管电流的模数转换器(ADC) 、数据寄存器、一个状态机以及一个l2C接口。3x4像素的光电二极管阵列由红色滤光、绿色滤光、蓝色滤光和透明未滤光)的光电二极管组成。此外,这些光电二极管还涂有红外阻挡滤光片。四个积分型ADC同时将放大后的光电二极管电流转换为16位数字值。在完成一个转换周期后,结果会传输到数据寄存器中,这些寄存器采用双缓冲方式以确保数据的完整性。所有内部定时以及低功耗等待状态均由状态机控制。
TCS34725数据的传输是通过一条快速(最高可达400KHZ)的双线I2C串行总线来实现的。除了I2C总线之外,TCS34725还提供了一个独立的中断信号输出。当中断被启用,并且在使用定义的阈值被超过时,低电平激活的中断会被触发,并一直保持激活状态, 直到被控制器清除为止。这种中断功能通过消除对TCS34725的轮询操作,简化并提高了系统软件的效率。使用时可以定义上、下中断阈值,并应用中断持续性过滤器。中断持续性过滤器允许在使用时定义在产生中断之前连续超出阈值的事件数量。中断输出是开漏型的,因此可以与其他设备进行逻辑“或”连接。

原理图

在这里插入图片描述

通讯时序

在这里插入图片描述

读写时序

在这里插入图片描述
在这里插入图片描述
写时序:
主机首先(即STM32)会发送一个开始信号, 随后将其I2C的7位地址与写操作位组合成8位的数据发送给从机(即TCS34725),从机接收到后会响应一个应答信号,主机此时将命令寄存器地址发送给从机,从机接收到发送响应信号,此时主机发送命令寄存的值,从机回应-个响应信号,直到主机发送一个停止信号,此次I2C写数据操作结束。
读时序:
首先主机会发送一个开始信号, 然后将其I2C的7位地址与写操作位组合成8位的数据发送给从机,从机接收到后会响应一个应答信号, 主机此时将命令寄存器地址发送给从机,从机接收到发送响应信号,此时主机重新发送一个开始信号, 并且将其7位地址和读操作位组合成8位的数据发送给从机,从机接收到信号后发送响应信号,再将其寄存器中的值发送给主机,主机端给予响应信号,直到主机端发送停止信号,此次通信结束。

寄存器

在这里插入图片描述
从上表中可以看出:

命令寄存器
在这里插入图片描述命令寄存器指定目标寄存器的地址,以便将来执行写入和读取操作。

0X00-启动寄存器
启动寄存器主要用于打开和关闭TCS34725设备,以及启用下表所示的功能和中断。
在这里插入图片描述
0X01-RGBC 定时寄存器
在这里插入图片描述RGBC定时寄存器以2.4ms的增量控制RGBC清除和IR通道ADC的内部积分时间。最大RGBC计数=(256−ATIME)×1024,最大值为65535。

0X03-等待时间寄存器
在这里插入图片描述
等待时间设置为2.4 ms,除非WLONG位被置位,此时等待时间延长12倍。WTIME编程为二进制补码数。

(0X04-0X07)-RGBC中断阈值寄存器
在这里插入图片描述RGBC中断阈值寄存器提供了用于比较函数的高触发点和低触发点的值,这些值用于生成中断。如果清除通道产生的值低于指定的较低阈值,或者高于较高的阈值,则会在中断引脚上产生中断信号。

0X0C-持续寄存器

在这里插入图片描述持续性寄存器控制着设备的滤波中断功能。提供了可配置的滤波功能,以便能够在每次积分周期结束后或在积分过程产生了超出阈值寄存器所指定值的范围内的结果且持续时间达到指定阈值的情况下生成中断。

0X0D-配置寄存器

在这里插入图片描述配置寄存器主要是设置等待的时间。

0X0F-控制寄存器
在这里插入图片描述控制寄存器为模拟模块提供了8位的各类控制信息。这些位通常用于控制比如增益设置和或二极管选择等功能。

0X12为设备ID寄存器,该ID寄存器是一个只读寄存器。

0X13-状态寄存器

在这里插入图片描述状态寄存器用于提供设备的内部状态,是一个只读寄存器。

(0X14-0X1B)-RGBC 通道数据寄存器

在这里插入图片描述

硬件连接

STM32TCS34725OLED
3.3VVCCVCC
GNDGNDGND
PB6SCL
PB7-SDA
PB8SDA-
PB9SCL-

代码

main.c

#include "stm32f10x.h"
#include "OLED_I2C.h"
#include "delay.h"
#include "TCS34725.h"
#include "TCS34725_IIC.h"
#include "bsp_usart.h"

uint32_t Remainder=0;
uint32_t Divisor=0;
uint32_t RGB888=0;

uint8_t R_Dat=0,G_Dat=0,B_Dat=0;

uint8_t  Dis_Buf1[8]={"R:   "};
uint8_t  Dis_Buf2[8]={"G:   "};
uint8_t  Dis_Buf3[8]={"B:   "};
//距离数据填到Dis_Buf中
//*P_data:存放数组
//Location:在数组中存放开始位数 如上面uint8_t  Dis_Buf1[8]={"R:   "};  填入数据是从Dis_Buf1[2]开始
//temp_data:需要转换的数据
//Length:数据位数长度 如999是3位数  此处为3
void OLED_printf( uint8_t *P_data,uint8_t Location,uint16_t temp_data,uint8_t Length)
{
		uint8_t i;
		Remainder=1;
		Divisor=1;
    for(i=0;i<Length;i++)
		{	
				Remainder=Remainder*10;

		}			
    for(i=0;i<Length-1;i++)
		{	

				Divisor=Divisor*10;
		} 
    for(i=0;i<Length;i++)
		{			

				P_data[Location+i] =temp_data%Remainder/Divisor+0x30;
				Remainder=Remainder/10;
			  Divisor=Remainder/10;
		}

}
void Data_Processing(void)
{

	R_Dat=(RGB888>>16);
	G_Dat=(RGB888>>8) & 0xff;
	B_Dat=(RGB888) & 0xff;

}
void Dis_Temp(void)
{
		Data_Processing();
		OLED_printf(Dis_Buf1,2,R_Dat,3);
		OLED_printf(Dis_Buf2,2,G_Dat,3);
		OLED_printf(Dis_Buf3,2,B_Dat,3);
	    OLED_ShowStr(30,0,"TCS34725",2);
		OLED_ShowStr(10,2,Dis_Buf1,2);
		OLED_ShowStr(10,4,Dis_Buf2,2);
		OLED_ShowStr(10,6,Dis_Buf3,2);
}

int main(void)
{
	RGB rgb;

	TCS34725_GPIO_Init();
	USART_Config();
	DelayInit();
	I2C_Configuration();
	OLED_Init();
	OLED_Fill(0x00);//全屏灭
	TCS34725_Init();
	integrationTime(33);
	while(1)
	{
			rgb=TCS34725_Get_RGBData();
			RGB888=TCS34725_GetRGB888(rgb);
	   	    Dis_Temp();
		    printf("RGB888 : ");
		    printf("R=%d ", R_Dat);
		    printf("G=%d ", G_Dat);
		    printf("B=%d \r\n", B_Dat);
			DelayMs(1000);
	}
}

TCS34725.c

#include "TCS34725.h"
#include "delay.h"

float INTEGRATION_CYCLES_MIN = 1.0f;
float INTEGRATION_CYCLES_MAX = 256.0f;
float INTEGRATION_TIME_MS_MIN= 2.4f;
float INTEGRATION_TIME_MS_MAX =2.4 * 256.0f;


uint8_t C_Dat[8]={0};


//读指定地址数据
uint8_t TCS34725_ReadWord(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
{  
	TCS34725_IIC_start();
	TCS34725_IIC_write_byte(TCS34725_ADDRESS);
	TCS34725_IIC_Get_ack();				//接收应答	
	TCS34725_IIC_write_byte(TCS34725_CMD_BIT|ReadAddr);
	TCS34725_IIC_Get_ack();				//接收应答	
	
	TCS34725_IIC_start();
	TCS34725_IIC_write_byte(TCS34725_ADDRESS+1);
	TCS34725_IIC_Get_ack();				//接收应答	
	while(NumByteToRead)  
  {
		*pBuffer = TCS34725_IIC_read_byte();
		if(NumByteToRead == 1)
    {
				/* Disable Acknowledgement */
				TCS34725_IIC_NACK();

				/* Send STOP Condition */
				TCS34725_IIC_stop();


		}
		else
		{
			TCS34725_IIC_ACK();
		}
		 pBuffer++; 
		 NumByteToRead--; 
	}
	return 0;
}
uint8_t TCS34725_WriteByte(uint8_t addr,uint8_t data) 
{
		TCS34725_IIC_start();
		TCS34725_IIC_write_byte(TCS34725_ADDRESS);
		TCS34725_IIC_Get_ack();				//接收应答	
		TCS34725_IIC_write_byte(TCS34725_CMD_BIT|addr);
		TCS34725_IIC_Get_ack();				//接收应答	
		
		TCS34725_IIC_write_byte(data);
		TCS34725_IIC_Get_ack();				//接收应答		
		return 0;
}
//初始化
uint8_t TCS34725_Init(void)  
{
		uint8_t ID = 0;
		TCS34725_ReadWord(&ID, TCS34725_ID, 1);
		if(ID != 0x44 && ID != 0x4D)
		{
				return 1;
		}
		TCS34725_WriteByte(TCS34725_CMD_Read_Byte,TCS34725_ENABLE_AIEN|TCS34725_ENABLE_AEN|TCS34725_ENABLE_PON);
		TCS34725_WriteByte(TCS34725_PERS,TCS34725_PERS_NONE);
		TCS34725_WriteByte(TCS34725_CONTROL,TCS34725_GAIN_60X);
		return 0;
}

void integrationTime(float ms) // 2.4 - 614.4 ms
{
		uint8_t data;
		if (ms < INTEGRATION_TIME_MS_MIN) ms = INTEGRATION_TIME_MS_MIN;
		if (ms > INTEGRATION_TIME_MS_MAX) ms = INTEGRATION_TIME_MS_MAX;
		 data = (uint8_t)(256.f - ms / INTEGRATION_TIME_MS_MIN);
		TCS34725_WriteByte(TCS34725_ATIME,data);	

}

RGB TCS34725_Get_RGBData(void)
{
	  RGB temp;
		uint8_t STATUS_AINT=0;

		while(STATUS_AINT!=(TCS34725_STATUS_AINT|TCS34725_STATUS_AVALID))
		{
				TCS34725_ReadWord(&STATUS_AINT,TCS34725_STATUS,1);
		}

		TCS34725_ReadWord(C_Dat,TCS34725_CDATAL | TCS34725_CMD_Read_Word,8);

	
		temp.C = (uint16_t)C_Dat[1]<<8|C_Dat[0];
		temp.R = (uint16_t)C_Dat[3]<<8|C_Dat[2];
		temp.G = (uint16_t)C_Dat[5]<<8|C_Dat[4];
		temp.B = (uint16_t)C_Dat[7]<<8|C_Dat[6];

		return temp;
}
/******************************************************************************
function:   Convert raw RGB values to RGB888 format
parameter	:
     rgb    : RGBC Numerical value
******************************************************************************/

uint32_t TCS34725_GetRGB888(RGB rgb)
{
    float i=1;
    //Limit data range
    if(rgb.R >= rgb.G && rgb.R >= rgb.B){ 
        i = rgb.R / 255 + 1;
    }
    else if(rgb.G >= rgb.R && rgb.G >= rgb.B){ 
        i = rgb.G / 255 + 1;
    }
    else if(rgb.B >=  rgb.G && rgb.B >= rgb.R){ 
        i = rgb.B / 255 + 1;  
    }
    if(i!=0)
    {
        rgb.R = (rgb.R) / i;
        rgb.G = (rgb.G) / i;
        rgb.B = (rgb.B) / i;
    }
    //Amplify data differences
    /*Please don't try to make the data negative, 
        unless you don't change the data type*/
    if(rgb.R > 30)
        rgb.R = rgb.R - 30;
    if(rgb.G > 30)
        rgb.G = rgb.G - 30;
    if(rgb.B > 30)
        rgb.B = rgb.B - 30;
    rgb.R = rgb.R * 255 / 225;
    rgb.G = rgb.G * 255 / 225;
    rgb.B = rgb.B * 255 / 225;
    
    if(rgb.R>255)
           rgb.R = 255; 
    if(rgb.G>255)
           rgb.G = 255; 
    if(rgb.B>255)
           rgb.B = 255; 
    return (rgb.R << 16) | (rgb.G << 8) | (rgb.B);
}
/******************************************************************************
function:   Convert raw RGB values to RGB565 format
parameter	:
     rgb    : RGBC Numerical value
******************************************************************************/
uint16_t TCS34725_GetRGB565(RGB rgb)
{
    float i=1;
    //Limit data range
    if(rgb.R >= rgb.G && rgb.R >= rgb.B){ 
        i = rgb.R / 255 + 1;
    }
    else if(rgb.G >= rgb.R && rgb.G >= rgb.B){ 
        i = rgb.G / 255 + 1;
    }
    else if(rgb.B >=  rgb.G && rgb.B >= rgb.R){ 
        i = rgb.B / 255 + 1;  
    }
    if(i!=0){
        rgb.R = (rgb.R) / i;
        rgb.G = (rgb.G) / i;
        rgb.B = (rgb.B) / i;
    }
    if(rgb.R > 30)
        rgb.R = rgb.R - 30;
    if(rgb.G > 30)
        rgb.G = rgb.G - 30;
    if(rgb.B > 30)
        rgb.B = rgb.B - 30;
    rgb.R = rgb.R * 255 / 225;
    rgb.G = rgb.G * 255 / 225;
    rgb.B = rgb.B * 255 / 225;
    
    if(rgb.R>255)
           rgb.R = 255; 
    if(rgb.G>255)
           rgb.G = 255; 
    if(rgb.B>255)
           rgb.B = 255; 
    return (rgb.R << 11) | (rgb.G << 5) | (rgb.B);
}

结果

串口打印RGB值:
在这里插入图片描述
OLED显示RGB值:

在这里插入图片描述

总结

以上是基于STM32驱动TCS34725颜色传感器的应用说明和程序展示。TCS34725有广泛的应用领域,包括RGB灯板背光控制、固态照明、健康/健身产品、工业过程控制以及医疗诊断设备等。此外,红外阻挡滤镜使 TCS34725能够执行环境光感应(ALS)。环境光感应在比如手机、笔记本电脑和电视等基于显示的产品中被广泛应用,用于感知照明环境并实现自动调整显示亮度,以达到最佳观看效果和节能目的。
感兴趣的可以关注收藏一下。需要资料代码的可以评论留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值