前言

不得不说,这颜色模块还挺有趣的,早上起床我就有想法想要把它实现了,之前一直把这模块压箱里了,本以为电赛要用到,结果材料清单无,所以就战略性放弃,现在才想起来有这个模块哈哈,就顺手拿来玩玩,其实对于TCS3200这个模块,还是比较不错的一款识别颜色,但是如果对颜色识别要求较高就不建议入手,这款识别模块抗干扰能力还是强的,是TCS230的升级版吧,具体下面再一一介绍。

另外就是发现关于这款模块的博文少,而且基于库函数的适用STM32f1的几乎没有,有的也是收费资源,因此就有了以下文章的问世哈哈

当然也有一篇基于HAL库的文章,同样在上面受益匪浅,推荐给大家:

基于STM32F103的TCS3200颜色传感器的使用_weixin_50950634的博客-CSDN博客

一、TCS3200如何用?

这里老规矩,还是讲一下TCS3200颜色识别模块怎么使用,首先,了解一下它有几个接口

上面两张图片已经很好地说明了,该模块含有8个引脚,即VCC、GND、S0、S1、S2、S3、LED(OE)、OUT,实际上在原理图上写了EO,但在实物图上并没有看到EO接口,只有LED接口,所以我就“自作主张”修改了一下,方便大家学习哈哈,这里是原理图,实物图会额外多出两个引脚(VCC、GND),那么这些引脚作用是什么呢?自问自答来了

S0、S1是一对情侣,S2、S3也是一对情侣,LED和OUT就两电灯泡

那么首先我们要如何定义这些端口呢,毋庸置疑,S0~S3全部推挽输出,LED推挽输出,OUT就下拉输入即可,怎么接比较好呢,除了OUT要设置在定时器的外部触发输入口(ETR),这里选用的是PA0(TIM2-ETR),其他接口无特别要求。测试时与被测物体保持在1cm时最佳。

先说明一下接线问题,因为我的博文主要还是以实际操作为主,理论部分较少,直接让你上手,理论后面再补哈哈

S0~S3分别接PA4~PA7,LED接PC5,OUT接PA0

那么认识认识它长怎么样吧?

是不是很酷炫哈哈

二、实现原理

那么这到底是如何实现的,接下来一探到底。

以上奉行的是拿来主义哈哈,其实是淘宝商家给的。这里比较详细地介绍了它的主要工作原理,大家在学习过程中可以多次返回来学习,肯定会有用的。

下面是S0~S3分别在高低电平下代表的意义(L表示低电平,H表示高电平

这里我们可以看到四种模式,在测试时,按红绿蓝清除的顺序进行

这里可以看到四种情况,双L下不启动,其他按比例因子情况启动

后面我选择的是2%,参照另一位博主的,大家也可以自行更改。

当然在进行测试之前,一定要进行白平衡校准,即每次运行前拿一个白色物体放在模块前进行第一次识别,之后就可以识别其他颜色了,白平衡等到的R值G值B值均为255。之后就可以开始测试了。

三、测试实现程序

TCS3200函数:

#include "tcs3200.h"#include "delay.h"#include "usart.h"#include "lcd.h"float RGB_Scale[3];         int count=0;              int cnt[3];             int flag=0; //S0-----PA4,S1-----PA5,S2-----PA6,S3-----PA7,LED-----PC5,OUT-----PA0void TCS_GPIO_Init(void){  GPIO_InitTypeDef  GPIO_InitStructure;  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_4|GPIO_Pin_7); //PA.4567 Êä³ö¸ß GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;     GPIO_Init(GPIOC, &GPIO_InitStructure);   GPIO_SetBits(GPIOC,GPIO_Pin_5); }void filter(int s2,int s3) {    if(s2==0&&s3==0){S2_L;S3_L;}    if(s2==0&&s3==1){  S2_L;S3_H;}    if(s2==1&&s3==0){S2_H;S3_L;}    if(s2==1&&s3==1){  S2_H;S3_H;}}void TSC_WB(int s2, int s3){  count = 0;     flag ++;     filter(s2, s3); }

定时器函数:

#include "timer.h"#include "led.h"#include "usart.h"#include "tcs3200.h"#include "lcd.h"extern float RGB_Scale[3];                    extern int cnt[3];             extern int flag;extern int count;void TIM3_Int_Init(u16 arr,u16 psc){    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler =psc;  TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  TIM_ITConfig(  TIM3, //TIM2TIM_IT_Update  | TIM_IT_Trigger, ENABLE  );NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);  TIM_Cmd(TIM3, ENABLE);  //ʹÄÜTIMxÍâÉè }void TIM2_Cap_Init(void)                                        {        GPIO_InitTypeDef GPIO_InitStructure;    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);          GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;             GPIO_Init(GPIOA, &GPIO_InitStructure);    GPIO_ResetBits(GPIOA,GPIO_Pin_0);                         TIM_TimeBaseStructure.TIM_Period = 0xFFFF;              TIM_TimeBaseStructure.TIM_Prescaler =0;               TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;      TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);            TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF);             TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);    TIM_SetCounter(TIM2, 0);                TIM_Cmd(TIM2,ENABLE );                            }void TIM3_IRQHandler(void)   {if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {      TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );        count=TIM_GetCounter(TIM2);           switch(flag){         case 0:            TSC_WB(0, 0);               break;         case 1:            cnt[0] = count;                TSC_WB(1, 1);             break;         case 2:            cnt[1] = count;                TSC_WB(0, 1);              break;         case 3:            cnt[2] = count;                 TSC_WB(1, 0);                break;         default:            count = 0;                 break;      }      TIM_SetCounter(TIM2,0);}}

最后主函数:

#include "led.h"#include "delay.h"#include "key.h"#include "sys.h"#include "usart.h"#include "lcd.h"#include "tcs3200.h"#include "timer.h"extern float RGB_Scale[3];       //外部声明             extern int cnt[3];             extern int flag;extern int count; int main(void) {delay_init();       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200); LED_Init();  LCD_Init(); TCS_GPIO_Init();TIM3_Int_Init(9999,719);//100msTIM2_Cap_Init(); POINT_COLOR=RED; S0_L;//这里直接2%设置,LED永远亮着即可    S1_H;        LED_ON;delay_ms(8000);     RGB_Scale[0] = 255.0/ cnt[0];        RGB_Scale[1] = 255.0/ cnt[1] ;       RGB_Scale[2] = 255.0/ cnt[2] ;  LCD_ShowString(10,10,210,16,16,"Init"); LCD_ShowString(20,70,210,16,16,"R:");LCD_ShowString(20,90,210,16,16,"G:"); LCD_ShowString(20,110,210,16,16,"B:"); LCD_ShowNum(50, 10,(int)(cnt[0]*RGB_Scale[0]),3,16);LCD_ShowNum(50, 30,(int)(cnt[1]*RGB_Scale[1]),3,16);LCD_ShowNum(50, 50,(int)(cnt[2]*RGB_Scale[2]),3,16); //白平衡结束POINT_COLOR=BLUE;while(1){flag=0;  count=0;       delay_ms(10000); LCD_ShowNum(50, 70,(int)(cnt[0]*RGB_Scale[0]),3,16);LCD_ShowNum(50, 90,(int)(cnt[1]*RGB_Scale[1]),3,16);LCD_ShowNum(50, 110,(int)(cnt[2]*RGB_Scale[2]),3,16);         } }

四、结果展示

白平衡结束后,我选用了一个青绿色纸盒进行测试,得到RGB值

RGB值如下:76、96、80

在自带的画图软件上查询是否准确

基本上误差不大,但是要说多么精准也没有哈哈,不过简单的识别还是可以做到的,不错,我又试了一个红色和粉色的,那个识别就比较准确。

五、总结

本来我想着直接拿来主义直接理解一波就行了,没想到网上资料少得可怜,拿来主义行不通,商家给的也只有51程序,所以没办法,只得自己手动敲代码了,刚开始那是毫无头绪,但是在看了其他优秀博文后,渐渐就有了思路,就开始上手了,其实不难,但是贵在坚持,肯定会有很多bug等着你,但是成功是给坚持到底的人的,遇到不懂及时查找资料解决,就算做不出来,也肯定会有收获。加油!

那么老规矩,觉得文章写的还可以的记得给点一下赞,收藏一下,说不定以后用得上呢哈哈

题外话:

挺喜欢彭于晏说的一句话:“我就是没有才华,所以才用命去拼!”

学习32之路固然辛苦,但要是坚持下来了,那不是很酷?哈哈哈