[国产单片机]色彩识别与样本色彩显示器

文章介绍了使用TCS34725色彩传感器制作色彩识别与样本色彩显示器的过程。TCS34725相较于早期的TCS230,提供了更方便的数字接口和丰富的色彩模式。系统以FM33LGxx开发板为核心,通过I2C与TCS34725通信,LCD屏显示色彩信息。文中详细列出了传感器初始化、数据传输及LCD屏驱动的相关函数。通过程序验证,展示了系统在不同颜色检测上的表现。
摘要由CSDN通过智能技术生成

要想识别色彩就离不开色彩传感器的使用,而色彩传感器的种类又有许多种,如早期的TCS230、TCS3200到现在的TCS34725等。

对于TCS230这类的传感器,它是以脉冲计数的方式来获得检测值,并通过色彩通道的选择来获得RGB的值。此外,为了达到一个可供使用的标准值,还需进行白平衡等处理,使用起来相对比较麻烦。

图1  TCS230

而现在推出的色彩传感器,如TCS34725则是数字化的,并采用I2C接口来传送数据,在使用时直接就可读取到色彩的RGB值,并可获得两种色彩模式的检测结果,即RGB模式和HSL模式。因此在使用上,它要比以前的色彩传感器要方便许多,功能也丰富一些。

图2  TCS34725


 

1. 整体结构

为此,在制作色彩识别与样本色彩显示器时是直接选取TCS34725来做检测器件,该设计的整体结构见图3所示。

图3 整体结构

在整体结构中,是以复旦微的FM33LGxx开发板作为处理核心,由TCS34725检测色彩值,由彩色的LCD屏来承担显示任务,其实物构成如图4所示。 

图4 实物构成

2.色彩传感器及其使用

TCS34725是采用I2C方式工作,其遵循的通讯协议如下:

TCS34725与开发板的引脚连接关系为:

PE9 ---SCL

PD10---SDA

由于TCS34725使用I2C的方式工作,为此是以GPIO口来模拟I2C的方式来实现。

其中,对所用引脚的功能配置函数为:

void TCS34725_I2C_Init()

{

    FL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);

    GPIO_InitStruct.pin = FL_GPIO_PIN_10;

    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;

    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

    GPIO_InitStruct.pull = FL_DISABLE;

    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        

    FL_GPIO_ResetOutputPin(GPIOE, FL_GPIO_PIN_9);

    GPIO_InitStruct.pin = FL_GPIO_PIN_9;

    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;

    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

    GPIO_InitStruct.pull = FL_DISABLE;

    FL_GPIO_Init(GPIOE, &GPIO_InitStruct);

}

由于在TCS34725工作时,既有数据输入处理,又有数据输出处理,故为其配置的输入、输出模式设置函数为:
void TCS_SDA_OUT()

{

    FL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);

    GPIO_InitStruct.pin = FL_GPIO_PIN_10;

    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;

    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

    GPIO_InitStruct.pull = FL_DISABLE;

    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

}



void TCS_SDA_IN()

{

    FL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);

    GPIO_InitStruct.pin = FL_GPIO_PIN_10;

    GPIO_InitStruct.mode = FL_GPIO_MODE_INPUT; 

    GPIO_InitStruct.pull = FL_ENABLE;

    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

}


TCS34725发送和接收字节数据的函数分别为:
void TCS34725_I2C_Send_Byte(u8 byte)

{

        u8 i;

        TCS_SDA_OUT();

        TCS_SCL_L;

        for(i = 0; i < 8; i++)

        {

                if(((byte&0x80)>>7)==1)  TCS_SDA_H;

                else

                        TCS_SDA_L;

                byte <<= 1;

                FL_DelayUs(2);

                TCS_SCL_H;

                FL_DelayUs(2);

                TCS_SCL_L;

                FL_DelayUs(2);

        } 

}



u8 TCS34725_I2C_Read_Byte(u8 ack)

{

        u8 i,receive = 0;

        TCS_SDA_IN();

        for(i = 0; i < 8; i++)

        {

                TCS_SCL_L;

                FL_DelayUs(2);

                TCS_SCL_H;

                receive <<= 1;

                if(TCS_SDA_READ) receive++;

                FL_DelayUs(1);

        }

        if (!ack) TCS34725_I2C_NACK();

        else TCS34725_I2C_ACK(); 

        return  receive;

}


TCS34725的初始化函数为:
u8 TCS34725_Init(void)

{

        u8 id=0;

        TCS34725_I2C_Init(); 

        TCS34725_Read(TCS34725_ID, &id, 1);

        if(id==0x4D | id==0x44)

        {

                        TCS34725_SetIntegrationTime(TCS34725_INTEGRATIONTIME_50MS);

                        TCS34725_SetGain(TCS34725_GAIN_1X);

                        TCS34725_Enable();

                        return 1;

        }

        return 0;

}


获取输出值的函数为:
u8 TCS34725_GetRawData(COLOR_RGBC *rgbc)

{

        u8 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 1;

        }

        return 0;

}


3.LCD屏显示驱动
在显示方面,所使用的显示器件为0.96寸的彩色LCD屏,其显示分辨率为160*80像素点。该显示屏采用SPI接口方式工作,为此它与开发板的引脚连接关系为:
SCL ---PD3
SDA ---PD5
RES ---PD4
DC ---PC5
CS ---PD2
LCD屏对引脚的功能配置函数为:
void lcd_app(void)

{

    FL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5);

    GPIO_InitStruct.pin = FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5;

    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;

    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

    GPIO_InitStruct.pull = FL_DISABLE;

    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        

    FL_GPIO_ResetOutputPin(GPIOC, FL_GPIO_PIN_5);

    GPIO_InitStruct.pin = FL_GPIO_PIN_5;

    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;

    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

    GPIO_InitStruct.pull = FL_DISABLE;

    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}



以GPIO口模拟SPI方式发送字节数据的函数为:

void LCD_Writ_Bus(u8 dat)

{

    u8 i;

    OLED_CS_Clr();

    for(i=0;i<8;i++)

    {

        OLED_SCLK_Clr();

        if(dat&0x80)

           OLED_SDIN_Set();

        else

           OLED_SDIN_Clr();

        OLED_SCLK_Set();

        dat<<=1;

    }

    OLED_CS_Set();

}



LCD屏的初始化函数为:
voidLcd_Init(void)
{
  OLED_RST_Clr();
  FL_DelayMs(200);
  OLED_RST_Set();
  FL_DelayMs(200);
  LCD_WR_REG(0x11);
  FL_DelayMs(100);
  LCD_WR_REG(0x21);
  LCD_WR_REG(0xB1);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB2);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB3);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB4);
  LCD_WR_DATA8(0x03);
  LCD_WR_REG(0xC0);
  LCD_WR_DATA8(0x62);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x04);
  LCD_WR_REG(0xC1);
  LCD_WR_DATA8(0xC0);
  LCD_WR_REG(0xC2);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x00);
  LCD_WR_REG(0xC3);
  LCD_WR_DATA8(0x8D);
  LCD_WR_DATA8(0x6A);
  LCD_WR_REG(0xC4);
  LCD_WR_DATA8(0x8D);
  LCD_WR_DATA8(0xEE);
  LCD_WR_REG(0xC5);
  LCD_WR_DATA8(0x0E);
  LCD_WR_REG(0xE0);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x0A);
  LCD_WR_DATA8(0x12);
  LCD_WR_DATA8(0x27);
  LCD_WR_DATA8(0x37);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x10);
  LCD_WR_REG(0xE1);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x0F);
  LCD_WR_DATA8(0x06);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x0A);
  LCD_WR_DATA8(0x13);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x10);
  LCD_WR_REG(0x3A);
  LCD_WR_DATA8(0x05);
  LCD_WR_REG(0x36);
  LCD_WR_DATA8(0x78);
  LCD_WR_REG(0x29);
}



 

4. 功能实现
有了前面的准备工作,就可以开始其功能设计了。
其设计思想为:
1)进行色彩值的归一化处理
由于TCS34725传感器是按3基色的亮度来进行检测的,因此对其检测值需要进行归一化处理,其处理方法就是用RGB的色彩值*255/亮度值。
以红色为例,其进行归一化的语句为:
rv=rgb.r*255/rgb.c;
对于G、B这两种色彩的归一化处理与之相仿。

2)实现样本色彩的标识处理
在获得了色彩的归一化结果后,其输出值是24位色,为了便于以16位色彩的形式进行显示,需进行色彩位数的变换处理,对于565的色彩表示方式,所进行的变换处理为:
fv=((rv>>3)<<8)+((gv>>2)<<5)+(bv>>3);
其中fv就是变换后的16位色彩值,而rv、gv和bv是8位色彩值。

此外,还要做的2件事为:一是绘制样本色彩框,以标识样本色彩的区域,另一个则是标识样本色彩,即填充一个样本色彩块。
实现样本色彩框的绘制函数为:
void LCD_box(u16 x1,u16 y1,u16 x2,u16 y2)

{

      int i,l;

      LCD_Address_Set(x1,y1,x2,y1);

      l=x2-x1;

      for(i=0;i<l;i++)

      {

            LCD_WR_DATA8(0xff);

            LCD_WR_DATA8(0xff);

      }

      LCD_Address_Set(x1,y2,x2,y2);

      for(i=0;i<l;i++)

      {

            LCD_WR_DATA8(0xff);

            LCD_WR_DATA8(0xff);

      }

      l=y2-y1;

      for(i=0;i<l;i++)

      {

          LCD_DrawPoint(x1,y1+i,WHITE);

      }

      for(i=0;i<l;i++)

      {

          LCD_DrawPoint(x2,y1+i,WHITE);

      } 

}
实现样本色彩标识的函数为:
void LCD_color(u16 Color)

{

    u16 i,j;

    LCD_Address_Set(110,30,129,49);

    for(i=0;i<20;i++)

    {

       for (j=0;j<20;j++)

       {

          LCD_WR_DATA(Color);

       }

    }

}

功能处理的主程序:

int main(void)

{

    u16 rv,gv,bv,fv; 

    MF_Clock_Init();

    MF_SystemClock_Config();

    FL_Init();

    MF_Config_Init();

    UserInit();

    led_int();

    lcd_app();

    Lcd_Init();

    LCD_Clear(BLACK);

    BACK_COLOR=BLACK;

    FL_DelayMs(2000);

    LCD_ShowString(20,30,"R:  G:  B:",YELLOW);

    LCD_color(RED);

    LCD_box(109,29,130,50);

    TCS34725_Init();

    TCS34725_GetRawData(&rgb);

    while(1)

    {

               TCS34725_GetRawData(&rgb);

               rv=rgb.r*255/rgb.c;

               gv=rgb.g*255/rgb.c;

               bv=rgb.b*255/rgb.c;

               LCD_ShowNum(0,50,rv,4,YELLOW);

               LCD_ShowNum(32,50,gv,4,YELLOW);

               LCD_ShowNum(64,50,bv,4,YELLOW);

               fv=((rv>>3)<<8)+((gv>>2)<<5)+(bv>>3);

               LCD_color(fv);

               FL_DelayMs(1000);

               LED0_TOG();

     }

}
5. 验证测试
经程序的编译与下载,其检测的效果如图5至图7所示,其中用于彩色检测的材料为彩色的泡沫塑料板。
从测试效果看,其结果还是可信的,能在一定应用场合使用。
此外,由于传感器上所配的LED灯有些偏黄,会对反射光的检测有一定的影响。

图5 检测粉色

图6 检测绿色

图7 检测蓝色。
---------------------
作者:jinglixixi
链接:https://bbs.21ic.com/icview-3275564-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值