本模块是基于AMS的TCS3472XFN彩色光数字转换器为核心的颜色传感器,传感器提供红色,绿色,蓝色(RGB)和清晰光感应值的数字输出。集成红外阻挡滤光片可最大限度地减少入射光的红外光谱成分,并可精确地进行颜色测量。具有高灵敏度,宽动态范围和红外阻隔滤波器。最小化IR和UV光谱分量效应,以产生准确的颜色测量。并且带有环境光强检测和可屏蔽中断。通过12C接口通信。本设计基于同一个设计原理,提供2个不同造型设计(方形版本/双孔版本),提供用户更多安装尺寸和环境的选择,其中双孔版本布局了2个LED灯对于物体进行补光。
模块来源
规格参数
工作电压:3.3-5V
工作电流:2.5~330uA
输出方式: IIC
管脚数量:7 Pin
以上信息见厂家资料文件
移植过程
我们的目标是将例程移植至开发板上【能够识别颜色数据】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
查看资料
I2C地址:
I2C 设备地址为 0X29
注意:0X29 这个设备地址是 7 位的,8 位设备地址需要向高位移一位变成0X52。
I2C写时序:
首先主机会发送一个开始信号,然后将其 I2C 的 7 位地 址与写操作位组合成8位的数据发送给从机, 从机接收到后会响应一个应答信号,主机此时将命令寄存器地址发送给从机,从机接收到发送响应信号,此时主机发送命令寄存的值,从机回应一个响应信号,直到主机发送一个停止信号,此次 IIC 写数据操作结束。
I2C读时序:
首先主机会发送一个开始信号,然后将其 I2C 的 7 位地址与写操作位组合成 8位的数 据发送给从机,从机接收到后会响应一个应答信号,主机此时将命令寄存器地址发送给从机, 从机接收到发送响应信号,此时主机重新发送一个开始信号,并且将其 7 位地址和读操作位 组合成 8 位的数据发送给从机,从机接收到信号后发送响应信号,再将其寄存器中的值发送 给主机,主机端给予响应信号,直到主机端发送停止信号,此次通信结束。
引脚选择
这里选择的引脚见引脚接线表
代码移植
下载为大家准备的驱动代码文件夹,复制到自己工程中\luban-lite\application\rt-thread\helloworld\user-bsp
文件夹下
提示
如果未找到 user-bsp
这个文件夹,说明你未进行模块移植的前置操作。请转移到手册使用必要操作(点击跳转)中进行必要的配置操作!!!
接下来打开自己的工程,开始修改Kconfig文件。
1、在 VSCode 中打开 application\rt-thread\helloworld\Kconfig 文件
2、在该文件的 #endif
前面添加该模块的 Kconfig路径语句
# TCS34725颜色识别传感器
source "application/rt-thread/helloworld/user-bsp/tcs34725-color-recognition-sensor/Kconfig"
2
menuconfig操作
1、我们 双击 luban-lite
文件夹下的 win_env.bat
脚本打开env工具:
2、输入以下命令列出所有可用的默认配置:
scons --list-def
3、选择 d13x_JLC_rt-thread_helloworld
这个配置!这个是我们衡山派开发板的默认配置!输入以下命令即可:
scons --apply-def=7
或者
scons --apply-def=d13x_JLC_rt-thread_helloworld_defconfig
这两个命令作用是一样的,一个是 文件名 ,一个是 编号 !!!
4、输入以下命令进入menuconfig菜单
scons --menuconfig
进入以下界面:
5、选中 Porting code using the LCKFB module
按
Y
选中按
N
取消选中方向键
左右
调整 最下面菜单的选项方向键
上下
调整 列表的选项
回车
执行最下面菜单的选项
6、回车进入 Porting code using the LCKFB module
菜单
7、按方向键 上下
选中 Using TCS34725 color recognition sensor
后按 Y
键,看到前面括号中出现一个 *
号,就可以下一步了。
8、按方向键 左右
选中 <Save>
然后一路回车
,然后 退出
即可
编译
我们 保存并退出menuconfig菜单 之后,输入以下命令进行编译:
scons
或
scons -j16
-j 用来选择参与编译的核心数: 我这里是选择16
大家可以根据自己的电脑来选择
核心越多编译越快
如果写的数量高于电脑本身,那么就自动按照最高可用的来运行!
镜像烧录
编译完成之后会在 \luban-lite\output\d13x_JLC_rt-thread_helloworld\images
文件夹下生成一个 d13x_JLC_v1.0.0.img
镜像文件!
然后我们烧录镜像,具体的教程请查看:镜像烧录(点击跳转🚀)
到这里完成了,请移步到 最后一节 进行移植验证。
工程代码解析
bsp_tcs34725.c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 文档网站:wiki.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 嘉立创社区问答:https://www.jlc-bbs.com/lckfb
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <getopt.h>
#include <sys/time.h>
#include <rtthread.h>
#include <inttypes.h>
#include <finsh.h>
#include "hal_adcim.h"
#include "rtdevice.h"
#include "aic_core.h"
#include "aic_log.h"
#include "hal_gpai.h"
#include "aic_hal_gpio.h"
#include "hal_i2c.h"
#include "bsp_tcs34725.h"
/******************************************************************************/
#define TCS34725_ADDRESS (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)
#define TCS34725_INTEGRATIONTIME_2_4MS 0xFF /**< 2.4ms - 1 cycle - Max Count: 1024 */
#define TCS34725_INTEGRATIONTIME_24MS 0xF6 /**< 24ms - 10 cycles - Max Count: 10240 */
#define TCS34725_INTEGRATIONTIME_50MS 0xEB /**< 50ms - 20 cycles - Max Count: 20480 */
#define TCS34725_INTEGRATIONTIME_101MS 0xD5 /**< 101ms - 42 cycles - Max Count: 43008 */
#define TCS34725_INTEGRATIONTIME_154MS 0xC0 /**< 154ms - 64 cycles - Max Count: 65535 */
#define TCS34725_INTEGRATIONTIME_240MS 0x9C /**< 240ms - 100 cycles - Max Count: 65535 */
#define TCS34725_INTEGRATIONTIME_700MS 0x00 /**< 700ms - 256 cycles - Max Count: 65535 */
#define TCS34725_GAIN_1X 0x00 /**< No gain */
#define TCS34725_GAIN_4X 0x01 /**< 4x gain */
#define TCS34725_GAIN_16X 0x02 /**< 16x gain */
#define TCS34725_GAIN_60X 0x03 /**< 60x gain */
/******************************************************************************/
#define max3v(v1, v2, v3) ((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))
#define min3v(v1, v2, v3) ((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v1)))
/******************************************************************************/
#define I2C_BUS_NAME "i2c0" /* I2C总线设备名称 */
#define SLAVE_ADDR TCS34725_ADDRESS /* 器件地址 */
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
/* 发送数据 */
static rt_err_t write_data(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *data)
{
struct rt_i2c_msg msgs;
msgs.addr = SLAVE_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = data;
msgs.len = len;
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
/* 读取数据 */
static rt_err_t read_data(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)
{
struct rt_i2c_msg msgs;
msgs.addr = SLAVE_ADDR; // 器件地址
msgs.flags = RT_I2C_RD; // 读写标志的设定
msgs.buf = buf; // 发送缓存区地址
msgs.len = len; // 发送的字节长度
/* 调用I2C设备接口传输数据 */
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
/**********************************************************
* 函 数 名 称:TCS34725_I2C_Write
* 函 数 功 能:向从设备写入数据。
* 传 入 参 数: slaveAddress - 从设备的地址。
* dataBuffer - 指向存储传输数据的缓冲区的指针。
* bytesNumber - 要写入的字节数。
* stopBit - 停止条件控制。
*
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_I2C_Write(uint8_t slaveAddress, uint8_t* dataBuffer,uint8_t bytesNumber, uint8_t stopBit)
{
if(RT_EOK != write_data(i2c_bus, bytesNumber, dataBuffer))
{
LOG_E("TCS34725_I2C_Write failed !!");
}
}
/**********************************************************
* 函 数 名 称:TCS34725_I2C_Read
* 函 数 功 能:从设备读取数据。
* 传 入 参 数: slaveAddress - 从设备的地址。
* dataBuffer - 指向一个缓冲区的指针,该缓冲区将存储接收到的数据。
* bytesNumber - 要读取的字节数。
* stopBit - 停止条件控制。
*
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_I2C_Read(uint8_t slaveAddress, uint8_t* dataBuffer, uint8_t bytesNumber, uint8_t stopBit)
{
if(RT_EOK != read_data(i2c_bus, bytesNumber, dataBuffer))
{
LOG_E("TCS34725_I2C_Read failed !!");
}
}
/**********************************************************
* 函 数 名 称:TCS34725_Write
* 函 数 功 能:将数据写入TCS34725寄存器,从选定的寄存器地址指针开始。
* 传 入 参 数: subAddr - 选定的寄存器地址指针。
* dataBuffer - 指向存储传输数据的缓冲区的指针。
* bytesNumber - 将要发送的字节数。
*
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_Write(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
uint8_t sendBuffer[10] = {0};
uint8_t byte = 0;
sendBuffer[0] = subAddr | TCS34725_COMMAND_BIT;
for(byte = 1; byte <= bytesNumber; byte++)
{
sendBuffer[byte] = dataBuffer[byte - 1];
}
TCS34725_I2C_Write(TCS34725_ADDRESS, sendBuffer, bytesNumber + 1, 1);
}
/**********************************************************
* 函 数 名 称:TCS34725_Read
* 函 数 功 能:从TCS34725寄存器读取数据,从选定的寄存器地址指针开始。
* 传 入 参 数: subAddr - 选定的寄存器地址指针
* dataBuffer - 指向一个缓冲区,该缓冲区将存储接收到的数据。
* bytesNumber - 将要读取的字节数。
*
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_Read(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
subAddr |= TCS34725_COMMAND_BIT;
TCS34725_I2C_Write(TCS34725_ADDRESS, (uint8_t*)&subAddr, 1, 0);
TCS34725_I2C_Read(TCS34725_ADDRESS, dataBuffer, bytesNumber, 1);
}
/**********************************************************
* 函 数 名 称:TCS34725_SetIntegrationTime
* 函 数 功 能:设置积分时间
* 传 入 参 数: time - 时间
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_SetIntegrationTime(uint8_t time)
{
TCS34725_Write(TCS34725_ATIME, &time, 1);
}
/**********************************************************
* 函 数 名 称:TCS34725_SetGain
* 函 数 功 能:设置增益
* 传 入 参 数: gain - 数据
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_SetGain(uint8_t gain)
{
TCS34725_Write(TCS34725_CONTROL, &gain, 1);
}
/**********************************************************
* 函 数 名 称:TCS34725_Enable
* 函 数 功 能:使能TCS34725
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_Enable(void)
{
uint8_t cmd = TCS34725_ENABLE_PON;
TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
cmd = TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN;
TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
//delay_s(600000);//delay_ms(3);//延时应该放在设置AEN之后
}
/**********************************************************
* 函 数 名 称:TCS34725_Disable
* 函 数 功 能:失能TCS34725
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:无
* 备 注:无
**********************************************************/
static void TCS34725_Disable(void)
{
uint8_t cmd = 0;
TCS34725_Read(TCS34725_ENABLE, &cmd, 1);
cmd = cmd & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
}
/**********************************************************
* 函 数 名 称:TCS34725_Disable
* 函 数 功 能:TCS34725获取单个通道数据
* 传 入 参 数:reg - 寄存器
* 函 数 返 回:data - 该通道的转换值
* 作 者:无
* 备 注:无
**********************************************************/
static uint16_t TCS34725_GetChannelData(uint8_t reg)
{
uint8_t tmp[2] = {0,0};
uint16_t data;
TCS34725_Read(reg, tmp, 2);
data = (tmp[1] << 8) | tmp[0];
return data;
}
/**********************************************************
* 函 数 名 称:TCS34725_Init
* 函 数 功 能:初始化TCS34725
* 传 入 参 数:无
* 函 数 返 回:RT_OK:完成 -RT_ERROR:错误
* 作 者:LCKFB
* 备 注:
**********************************************************/
int TCS34725_Init(void)
{
uint8_t id = 0;
/* 查找I2C总线设备,获取I2C总线设备句柄 */
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME);
if(i2c_bus == RT_NULL)
{
LOG_E("no device: %s",I2C_BUS_NAME);
return -RT_ERROR;
}
else
{
rt_kprintf("\nfind device: %s\n",I2C_BUS_NAME);
}
/* TCS34725 的 ID 是 0x44 可以根据这个来判断是否成功连接,0x4D是TCS34727 */
TCS34725_Read(TCS34725_ID, &id, 1);
if((id == 0x4D) | (id == 0x44))
{
TCS34725_SetIntegrationTime(TCS34725_INTEGRATIONTIME_24MS);
TCS34725_SetGain(TCS34725_GAIN_1X);
TCS34725_Enable();
}
else
{
LOG_E("TCS34725_Init failed: [%d]", __LINE__);
return -RT_ERROR;
}
return RT_EOK;
}
/******************************************************************
* 函 数 名 称:TCS34725_Read_RGBC
* 函 数 说 明:TCS34725获取各个通道数据
* 函 数 形 参:数据存储结构体地址
* 函 数 返 回:RT_EOK:成功 -RT_ERROR:错误
* 作 者:LC
* 备 注:无
******************************************************************/
int TCS34725_Read_RGBC(COLOR_RGBC *RGBC)
{
uint8_t status = TCS34725_STATUS_AVALID;
TCS34725_Read(TCS34725_STATUS, &status, 1);
if(status & TCS34725_STATUS_AVALID)
{
RGBC->c = TCS34725_GetChannelData(TCS34725_CDATAL);
RGBC->r = TCS34725_GetChannelData(TCS34725_RDATAL);
RGBC->g = TCS34725_GetChannelData(TCS34725_GDATAL);
RGBC->b = TCS34725_GetChannelData(TCS34725_BDATAL);
return RT_EOK;
}
return -RT_ERROR;
}
/******************************************************************
* 函 数 名 称:TCS34725_RGBC_to_HSL
* 函 数 说 明:RGB转HSL
* 函 数 形 参:RGBC源数据地址 HSL目标数据地址
* 函 数 返 回:RT_EOK:成功 -RT_ERROR:错误
* 作 者:LC
* 备 注:无
******************************************************************/
int TCS34725_RGBC_to_HSL(COLOR_RGBC *RGBC, COLOR_HSL *HSL)
{
uint8_t maxVal,minVal,difVal;
uint8_t r = RGBC->r * 100 / RGBC->c; //[0-100]
uint8_t g = RGBC->g * 100 / RGBC->c;
uint8_t b = RGBC->b * 100 / RGBC->c;
maxVal = max3v(r,g,b);
minVal = min3v(r,g,b);
difVal = maxVal-minVal;
//计算亮度
HSL->l = (maxVal+minVal)/2; //[0-100]
if(maxVal == minVal)//若r=g=b,灰度
{
HSL->h = 0;
HSL->s = 0;
}
else
{
//计算色调
if(maxVal==r)
{
if(g>=b)
HSL->h = 60*(g-b)/difVal;
else
HSL->h = 60*(g-b)/difVal+360;
}
else
{
if(maxVal==g)HSL->h = 60*(b-r)/difVal+120;
else
if(maxVal==b)HSL->h = 60*(r-g)/difVal+240;
}
//计算饱和度
if(HSL->l<=50)HSL->s=difVal*100/(maxVal+minVal); //[0-100]
else
HSL->s=difVal*100/(200-(maxVal+minVal));
}
return RT_EOK;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
bsp_tcs34725.h
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 文档网站:wiki.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 嘉立创社区问答:https://www.jlc-bbs.com/lckfb
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#ifndef __BSP_TCS34725_H__
#define __BSP_TCS34725_H__
#include "stdio.h"
typedef struct{
unsigned short c; //[0-65536]
unsigned short r;
unsigned short g;
unsigned short b;
}COLOR_RGBC;//RGBC
typedef struct{
unsigned short h; //[0,360]
unsigned char s; //[0,100]
unsigned char l; //[0,100]
}COLOR_HSL;//HSL
int TCS34725_Init(void);
int TCS34725_Read_RGBC(COLOR_RGBC *RGBC);
int TCS34725_RGBC_to_HSL(COLOR_RGBC *RGBC, COLOR_HSL *HSL);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Kconfig
这个是一个menuconfig中的选项,如果在菜单中选中该选项,就会在rtconfig.h
中定义一个语句,用来if判断条件编译之类的。
config LCKFB_TCS34725_COLOR_RECOGNITION_SENSOR
bool "Using TCS34725 color recognition sensor"
select AIC_USING_I2C0
default n
help
More information is available at: https://wiki.lckfb.com/
2
3
4
5
6
7
SConscript
自动化构建文件,如果定义了 LCKFB_TCS34725_COLOR_RECOGNITION_SENSOR
和 USING_LCKFB_TRANSPLANT_CODE
就自动编译当前目录下的文件!!
Import('RTT_ROOT')
Import('rtconfig')
import rtconfig
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = []
if GetDepend('LCKFB_TCS34725_COLOR_RECOGNITION_SENSOR') and GetDepend('USING_LCKFB_TRANSPLANT_CODE'):
src = Glob(os.path.join(cwd, '*.c'))
group = DefineGroup('lckfb-tcs34725-color-recognition-sensor', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test_tcs34725_color_recognition_sensor.c
这个文件定义了一个处理TCS34725颜色传感器的线程,初始化了传感器的板级支持包(BSP),并设置了线程的优先级、栈大小和时间片。
线程的主要任务是读取TCS34725传感器的RGB颜色值,并转换为HSL(色相、饱和度、亮度)格式,然后打印这些数据到控制台。线程会持续读取数据,直到用户通过命令行接口输入特定命令来退出读取循环。
线程入口函数逻辑
- 初始化时调用
TCS34725_Init
函数来初始化TCS34725传感器。 - 定义一个返回值变量
ret
和一个循环计数器while_count
,并将while_count
初始化为1。 - 定义
COLOR_RGBC
和COLOR_HSL
结构体变量RGBC
和HSL
,用于存储RGB和HSL颜色值。 - 如果初始化传感器失败,则打印错误信息并返回。
- 在一个无限循环中,首先尝试读取TCS34725传感器的RGB颜色值。
- 如果读取成功,将RGB值转换为HSL值,并将读取到的RGB和HSL值打印到控制台。
- 如果读取失败,打印错误信息。
- 当循环次数达到100次时,提示用户可以通过输入命令
test_exit_tcs34725_sensor
来退出传感器读取循环。 - 在每次循环结束时,线程会挂起一段时间,这里是1000毫秒。
此外,该文件还定义了两个命令,test_tcs34725_sensor
和test_exit_tcs34725_sensor
,它们分别用于启动和退出TCS34725传感器线程。
test_tcs34725_sensor
命令创建并启动一个名为tcs34725_thread
的线程,该线程将执行tcs34725_thread_entry
函数。test_exit_tcs34725_sensor
命令用于删除tcs34725_thread
线程,从而退出传感器读取循环,并打印退出成功的消息。如果删除线程失败,将打印错误信息。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <sys/time.h>
#include <rtthread.h>
#include "rtdevice.h"
#include "aic_core.h"
#include "aic_hal_gpio.h"
#include "bsp_tcs34725.h"
#define THREAD_PRIORITY 25 // 线程优先级
#define THREAD_STACK_SIZE 1024 // 线程大小
#define THREAD_TIMESLICE 20 // 时间片
static rt_thread_t tcs34725_thread = RT_NULL; // 线程控制块
// 线程入口函数
static void tcs34725_thread_entry(void *param)
{
int ret = 0;
int while_count = 1; // 循环次数
COLOR_RGBC RGBC;
COLOR_HSL HSL;
/* TCS34725初始化 */
ret = TCS34725_Init();
if(ret != RT_EOK)
{
LOG_E("failed to TCS34725_Init !!");
return;
}
rt_thread_mdelay(100);
rt_kprintf("Start Loop !!\n");
while(while_count++)
{
int ret = TCS34725_Read_RGBC(&RGBC); //读取
if(ret != RT_EOK)
{
LOG_E("failed to TCS34725_Read_RGBC !");
}
else
{
TCS34725_RGBC_to_HSL(&RGBC, &HSL);
rt_kprintf("\nRead [TCS34725] RGBC: R[%d] G[%d] B[%d]\n", RGBC.r, RGBC.g, RGBC.b, RGBC.c);
rt_kprintf("Read [TCS34725] HSL: H[%d] S[%d] L[%d]\n", HSL.h, HSL.s, HSL.l);
}
if(while_count >= 100)
{
while_count = 1;
rt_kprintf("\nType [test_exit_tcs34725_sensor] command to exit TCS34725 to read data\n");
rt_kprintf("Note: Pressing [TAB] as you type will autocomplete the command\n");
rt_thread_mdelay(2000);
}
rt_thread_mdelay(1000);
}
rt_kprintf("\nEND!!\n");
}
/* TCS34725启动函数 */
static void test_tcs34725_sensor(int argc, char **argv)
{
/* 创建线程,名称是 tcs34725_thread,入口是 tcs34725_thread_entry */
tcs34725_thread = rt_thread_create("tcs34725_thread1",
tcs34725_thread_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (tcs34725_thread != RT_NULL)
rt_thread_startup(tcs34725_thread);
}
// 导出函数为命令
MSH_CMD_EXPORT(test_tcs34725_sensor, run TCS34725 sensor);
/* TCS34725退出函数 */
static void test_exit_tcs34725_sensor(void)
{
int ret = rt_thread_delete(tcs34725_thread);
if(ret != RT_EOK)
{
LOG_E("failed to test_exit_tcs34725_sensor !!");
}
else
{
rt_kprintf("\n========TCS34725 exit successful !!========\n");
}
}
// 导出函数为命令
MSH_CMD_EXPORT(test_exit_tcs34725_sensor, quit TCS34725);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
移植验证
我们使用串口调试,将 USB转TTL模块 连接到衡山派开发板上面!!
具体的教程查看:串口调试(点击跳转🚀)
串口波特率默认为
115200
我们在输入下面的命令运行该模块的线程:
输入的时候按下
TAB键
会进行命令补全!!
test_tcs34725_sensor
模块上电效果: