【模块系列】STM32&TCS3472

前言

手上正好有TCS3472模块,也正好想在加深一下自己对I2C协议的理解和应用,所以就写了这个代码库出来。参考的资料主要来源于TCS3472的数据手册,和arduino中MH_TCS3472库的宏定义,和函数名称,我就没有重新命名,方便大家理解和使用修改之类的。

环境

  • 开发板:STM32C6T6最小系统板

  • 案例的代码环境:Keil5+STM32CubeMX生成的HAL库,OLED(4P)+TCS3472

  • 案例接线:TCS3472模块的VIN接到ST-LINK的5V,OLED模块VCC接3.3V。TCS3472和OLED的SDA接到PB9,SCL接到PB8。TCS3472模块的LED引脚接PA3(闪烁)或GND都行,不接的话LED的会一直亮,导致RGB值与透明度计算后大于256的。

    注意:假如TCS3472模块的VIN接到板载的3.3V的话,可能会发生供电不足的情况。

特点

下述介绍参考数据手册

  • 支持I2C协议快速模式,接口数据传输速率高达 400 kbit/s

  • TCS3472提供红、绿、蓝(RGB)和透明光©感应值的16位数字量的返回。

  • 红、绿、蓝(RGB)和透明光。带红外屏蔽滤光片的感应器。可编程模拟增益和积分时间。3,800,000:1。动态范围灵敏度极高-非常适合在暗玻璃后操作。

  • 外置可编程中断引脚,启用可屏蔽中断当超出预设值时,系统会发出电平式中断可编程上下限阈值,带持久性过滤器,从而减少MCU的开销

  • 有着电源管理,低功耗-2.5μA 休眠状态65μA等待状态,可编程等待状态时间从2.4ms 至>7 秒

代码

代码方面除了CubeMX生成的工程框架外,还导入了OLED(4P),自制了MyI2C,TCS34725库,假如其它项目要用到的话注意也要导入这几个库。下面仅展示TCS34725库,完整工程文件会放在文章末尾的

TCS34725.H

c 复制代码
#ifndef __TCS34725_H__
#define __TCS34725_H__

#define TCS34725_ADDRESS          (0x52)		// 八位地址
#define TCS34725_ADDRESS_7bit     (0x29)		// 七位地址

#define TCS34725_COMMAND_BIT      (0x80)

#define TCS34725_ENABLE           (0x00)
#define TCS34725_ENABLE_AIEN      (0x10)    ///< RGBC Interrupt Enable 
#define TCS34725_ENABLE_WEN       (0x08)    ///< Wait enable - Writing 1 activates the wait timer 
#define TCS34725_ENABLE_AEN       (0x02)    ///< RGBC Enable - Writing 1 actives the ADC, 0 disables it 
#define TCS34725_ENABLE_PON       (0x01)    ///< Power on - Writing 1 activates the internal oscillator, 0 disables it 
#define TCS34725_ATIME            (0x01)    ///< Integration time 
#define TCS34725_WTIME            (0x03)    ///< Wait time (if TCS34725_ENABLE_WEN is asserted) 
#define TCS34725_WTIME_2_4MS      (0xFF)    ///< WLONG0 = 2.4ms   WLONG1 = 0.029s 
#define TCS34725_WTIME_204MS      (0xAB)    ///< WLONG0 = 204ms   WLONG1 = 2.45s  
#define TCS34725_WTIME_614MS      (0x00)    ///< WLONG0 = 614ms   WLONG1 = 7.4s   
#define TCS34725_AILTL            (0x04)    ///< Clear channel lower interrupt threshold 
#define TCS34725_AILTH            (0x05)
#define TCS34725_AIHTL            (0x06)    ///< Clear channel upper interrupt threshold 
#define TCS34725_AIHTH            (0x07)
#define TCS34725_PERS             (0x0C)    ///< Persistence register - basic SW filtering mechanism for interrupts 
#define TCS34725_PERS_NONE        (0b0000)  ///< Every RGBC cycle generates an interrupt                                
#define TCS34725_PERS_1_CYCLE     (0b0001)  ///< 1 clean channel value outside threshold range generates an interrupt   
#define TCS34725_PERS_2_CYCLE     (0b0010)  ///< 2 clean channel values outside threshold range generates an interrupt  
#define TCS34725_PERS_3_CYCLE     (0b0011)  ///< 3 clean channel values outside threshold range generates an interrupt  
#define TCS34725_PERS_5_CYCLE     (0b0100)  ///< 5 clean channel values outside threshold range generates an interrupt  
#define TCS34725_PERS_10_CYCLE    (0b0101)  ///< 10 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_15_CYCLE    (0b0110)  ///< 15 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_20_CYCLE    (0b0111)  ///< 20 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_25_CYCLE    (0b1000)  ///< 25 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_30_CYCLE    (0b1001)  ///< 30 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_35_CYCLE    (0b1010)  ///< 35 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_40_CYCLE    (0b1011)  ///< 40 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_45_CYCLE    (0b1100)  ///< 45 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_50_CYCLE    (0b1101)  ///< 50 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_55_CYCLE    (0b1110)  ///< 55 clean channel values outside threshold range generates an interrupt 
#define TCS34725_PERS_60_CYCLE    (0b1111)  ///< 60 clean channel values outside threshold range generates an interrupt 
#define TCS34725_CONFIG           (0x0D)
#define TCS34725_CONFIG_WLONG     (0x02)    ///< Choose between short and long (12x) wait times via TCS34725_WTIME 
#define TCS34725_CONTROL          (0x0F)    ///< Set the gain level for the sensor 
#define TCS34725_ID               (0x12)    ///< 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 
#define TCS34725_STATUS           (0x13)
#define TCS34725_STATUS_AINT      (0x10)    ///< RGBC Clean channel interrupt 
#define TCS34725_STATUS_AVALID    (0x01)    ///< Indicates that the RGBC channels have completed an integration cycle 
#define TCS34725_CDATAL           (0x14)    ///< Clear channel data 
#define TCS34725_CDATAH           (0x15)
#define TCS34725_RDATAL           (0x16)    ///< Red channel data 
#define TCS34725_RDATAH           (0x17)
#define TCS34725_GDATAL           (0x18)    ///< Green channel data 
#define TCS34725_GDATAH           (0x19)
#define TCS34725_BDATAL           (0x1A)    ///< Blue channel data 
#define TCS34725_BDATAH           (0x1B)

typedef enum
{
  TCS34725_INTEGRATIONTIME_2_4MS  = 0xFF,   ///<  2.4ms - 1 cycle    - Max Count: 1024  
  TCS34725_INTEGRATIONTIME_24MS   = 0xF6,   ///<  24ms  - 10 cycles  - Max Count: 10240 
  TCS34725_INTEGRATIONTIME_50MS   = 0xEB,   ///<  50ms  - 20 cycles  - Max Count: 20480 
  TCS34725_INTEGRATIONTIME_101MS  = 0xD5,   ///<  101ms - 42 cycles  - Max Count: 43008 
  TCS34725_INTEGRATIONTIME_154MS  = 0xC0,   ///<  154ms - 64 cycles  - Max Count: 65535 
  TCS34725_INTEGRATIONTIME_700MS  = 0x00    ///<  700ms - 256 cycles - Max Count: 65535 
}
tcs34725IntegrationTime_t;

typedef enum
{
  TCS34725_GAIN_1X                = 0x00,   ///<  No gain  
  TCS34725_GAIN_4X                = 0x01,   ///<  4x gain  
  TCS34725_GAIN_16X               = 0x02,   ///<  16x gain 
  TCS34725_GAIN_60X               = 0x03    ///<  60x gain 
}
tcs34725Gain_t;

typedef unsigned          char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;


/*****	底层函数	 *****/
void TCS34725_WriteReg(uint8_t reg,uint8_t data);
uint8_t TCS34725_ReadReg(uint8_t reg);

/*****	功能函数	 *****/
void TCS34725_Init(void);						// 初始化TCS34725配置
void TCS34725_enable(void);					// 使能器件
void TCS34725_lock(void);						// 使能TCS34725内部中断
uint8_t TCS34725_getID(void);			// 获取器件ID
uint8_t TCS34725_getStatus(void);	// 获取TCS34725状态
void TCS34725_setGain(tcs34725Gain_t gain);		// 设置增益
void TCS34725_setIntegrationTime(tcs34725IntegrationTime_t time);		// 设置时间增益
void TCS34725_getRGBC(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);		// 获取TCS34725的颜色反馈


#endif

TCS34725.C

c 复制代码
#include "TCS34725.h"
#include "MyI2C.h"

/**
 * @描述:基于TCS34725 写寄存器 ID-地址-数据
 */
void TCS34725_WriteReg(uint8_t reg,uint8_t data)
{
	MyI2C_Start();					
	MyI2C_SendByte(TCS34725_ADDRESS);			
  MyI2C_ReceiveAck();	
	MyI2C_SendByte(TCS34725_COMMAND_BIT | reg);		
  MyI2C_ReceiveAck();			
	MyI2C_SendByte(data);
	MyI2C_ReceiveAck();
  MyI2C_Stop();						
}

/**
 * @描述:基于TCS34725 读寄存器 ID-地址-数据
 */
uint8_t TCS34725_ReadReg(uint8_t reg)
{
	uint8_t reData = 0;
	MyI2C_Start();					
	MyI2C_SendByte(TCS34725_ADDRESS);		
	MyI2C_ReceiveAck();	
	MyI2C_SendByte(TCS34725_COMMAND_BIT | reg);			
  MyI2C_ReceiveAck();
	
	MyI2C_Start();	// 666
	MyI2C_SendByte(TCS34725_ADDRESS | 0x01);		
	MyI2C_ReceiveAck();	
	reData = MyI2C_ReceiveByte();
	MyI2C_SendAck(1);
	
	MyI2C_Stop();		
  return reData;
}


/**
* @描述:初始化TCS34725配置
*/
void TCS34725_Init()
{
	TCS34725_setIntegrationTime(TCS34725_INTEGRATIONTIME_101MS);
	TCS34725_setGain(TCS34725_GAIN_1X);
	TCS34725_enable();
}

/**
* @描述:TCS34725毫秒级延时
*/
void TCS34725_DelayMs(uint16_t ms)
{
	char i;
	for(i = 0;i < ms;i++)
	{
		MyI2C_DelayUs(1000);
	}
	
}

/**
* @描述:设置时间增益
*/
void TCS34725_setIntegrationTime(tcs34725IntegrationTime_t time)
{
  // 更新时序寄存器
	TCS34725_WriteReg(TCS34725_ATIME,time);
}

/**
* @描述:设置增益
*/
void TCS34725_setGain(tcs34725Gain_t gain)
{
	// 设置增益
	TCS34725_WriteReg(TCS34725_CONTROL,gain);

}

/**
* @描述:使能器件
*/
void TCS34725_enable(void)
{
	// 开启内部振荡器--启动
	TCS34725_WriteReg(TCS34725_ENABLE,TCS34725_ENABLE_PON);
  TCS34725_DelayMs(3);
	// 启动ADC
	TCS34725_WriteReg(TCS34725_ENABLE,TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
}

/**
* @描述:读取TCS34725指定寄存器
*/
uint16_t TCS34725_readRegWord(uint8_t reg)
{
  uint16_t h = 0x0000;		// 高八位
	uint16_t l = 0x0000;		// 低八位
	
	MyI2C_Start();															// I2C开始条件
	MyI2C_SendByte(TCS34725_ADDRESS);						// I2C发送字节
  MyI2C_ReceiveAck();													// I2C接收应答
	MyI2C_SendByte(TCS34725_COMMAND_BIT | reg | 0x20);	// I2C发送字节
	MyI2C_ReceiveAck();													// I2C接收应答
	
  MyI2C_Start();	// 666
	MyI2C_SendByte(TCS34725_ADDRESS | 0x01);		
	MyI2C_ReceiveAck();	

  h = MyI2C_ReceiveByte();			// I2C接收字节
	MyI2C_SendAck(0);							// I2C发送应答
	l = MyI2C_ReceiveByte();			// I2C接收字节
	MyI2C_SendAck(1);							// I2C发送应答
	MyI2C_Stop();									// I2C结束条件
	
  h <<= 8;
  h |= l;
  return h;
}

/**
* @描述:获取TCS34725的颜色反馈
*/
void TCS34725_getRGBC(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
{

  *c = TCS34725_readRegWord(TCS34725_CDATAL);
  *r = TCS34725_readRegWord(TCS34725_RDATAL);
  *g = TCS34725_readRegWord(TCS34725_GDATAL);
  *b = TCS34725_readRegWord(TCS34725_BDATAL);
  
  // 给定一定的采集后延时
	TCS34725_DelayMs(100);
}

/**
* @描述:使能TCS34725内部中断
*/
void TCS34725_lock()
{
	uint8_t r = TCS34725_ReadReg(TCS34725_ENABLE);
	r |= TCS34725_ENABLE_AIEN;
	TCS34725_WriteReg(TCS34725_ENABLE, r);
}

/**
* @描述:获取器件ID
* @返回:0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 
*/
uint8_t TCS34725_getID()
{
	return TCS34725_ReadReg(TCS34725_ID);
}

/**
* @描述:获取TCS34725状态
* @返回:返回该寄存器数值
*/
uint8_t TCS34725_getStatus()
{
	return TCS34725_ReadReg(TCS34725_STATUS);
}

现象

下面为代码现象。OLED上显示的分别是,ID,8位R,8位G,8位B,16位C的值,可以看出来,测出的结果跟我设定的结果还差一点,不过能测量出个大概,比如偏红色啊,偏蓝色啊。当然可能也是我的参数没配置好,大家想要更高精度的话,就要关注TCS34725_Init()里面的时间增益,和数值增益了。

工程

链接包含资料:Keil5工程代码*1,TCS34727资料手册(英文)*1

链接:https://pan.baidu.com/s/1AapcmqJjpgtlvu-eMr3Bpg  提取码:wq6k

相关推荐
沉在嵌入式的鱼18 小时前
linux串口对0X0D、0X0A等特殊字符的处理
linux·stm32·单片机·特殊字符·串口配置
学习路上_write18 小时前
AD5293驱动学习
c语言·单片机·嵌入式硬件·学习
影阴19 小时前
存储器和寄存器
stm32·单片机·嵌入式硬件
吃西瓜的年年20 小时前
3. C语言核心语法2
c语言·嵌入式硬件·改行学it
李洛克0720 小时前
RDMA CM UDP 通信完整指南
单片机·网络协议·udp
思茂信息20 小时前
CST电动车EMC仿真——电机控制器MCU滤波仿真
javascript·单片机·嵌入式硬件·cst·电磁仿真
小曹要微笑20 小时前
I2C总线技术解析(纯文字版)
单片机·嵌入式硬件·esp32·iic
我送炭你添花20 小时前
可编程逻辑器件(PLD)的发展历程、原理、开发与应用详解
嵌入式硬件·fpga开发
袖手蹲21 小时前
Arduino UNO Q 从 Arduino Cloud 远程控制闪烁 LED
人工智能·单片机·嵌入式硬件·电脑
平凡灵感码头1 天前
第一次做蓝牙产品,从零开发 嵌入式开发日志(2)AC63NSDK 完整合并版目录说明
stm32·单片机·嵌入式硬件