找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1885|回复: 10
收起左侧

关于颜色传感器TCS230的测量RGB值的实验

[复制链接]
ID:958627 发表于 2021-8-3 18:20 | 显示全部楼层 |阅读模式
大家好,我是学习单片机的新手,我在用TCS230和单片机STC8A8K64S4A12做测量RGB值的实验,但不知为何,液晶屏只显示RGB值皆为255,不会变化,所以想求助各位有没有碰到过这种情况,怎么解决的?

程序在楼下

回复

使用道具 举报

ID:280000 发表于 2021-8-4 08:58 | 显示全部楼层
单片机和颜色传感器通信协议编写的有问题吧,没有读取到正确的数据
回复

使用道具 举报

ID:958627 发表于 2021-8-4 09:01 | 显示全部楼层
湖南 发表于 2021-8-4 08:58
单片机和颜色传感器通信协议编写的有问题吧,没有读取到正确的数据

您好,您可以帮助我一下吗,这是我的程序
#include <stc8a.h>
#include <LCD1602.h>
#define uchar unsigned char
#define uint  unsigned int

//=================颜色传感模块连接=====================
/*-----------------------------------------------------
       |EO-----GND
       |S0-----VCC | S2-----P1.0 | OUT-------P3.5
       |S1-----VCC | S3-----P1.1 |
  ---------------------------------------------------*/
sbit    tcs230_s2=P1^0;//TCS230 S2接单片机P1.0
sbit    tcs230_s3=P1^1;//TCS230 S3接单片机P1.1
sbit    tcs230_en=P3^0; //TCS230 EN(E0)接GND
//**************函数声明***************************************
void    DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符
void    baipingheng();//白平衡子程序
void    celiang();//实际颜色程序
void    LCD1602_Init(void);
void    LCD1602_Display_Str(uchar* str);
void    Delay_ms(unsigned int ms);
uint    ryz,gyz,byz;//分别定义红色因子 绿色因子 蓝色因子
uint    rb,gb,bb;//RGB值
uchar   tab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//***********************主程序******************************
main()   
{   
   TMOD=0x51;//设定T0以工作方式1定时10毫秒
   LCD1602_Init();//LCD初始
   baipingheng();//上电时先白平衡一次
   while(1)
   {
       celiang();//颜色测试
       DisplayOneChar(0, 0,'R');//以十进制显示RGB中红色的分值
       DisplayOneChar(0, 1, rb/100+0x30); //显示百位数据
       DisplayOneChar(0, 2, rb/10%10+0x30);//显示十位数据
       DisplayOneChar(0, 3, rb%10+0x30);//显示个位数据
                   DisplayOneChar(0, 5,'G');//以十进制显示RGB中绿色的分值
       DisplayOneChar(0, 6, gb/100+0x30); //显示百位数据
       DisplayOneChar(0, 7, gb/10%10+0x30);
       DisplayOneChar(0, 8, gb%10+0x30);
       DisplayOneChar(0, 10,'B');//以十进制显示RGB中蓝色的分值
       DisplayOneChar(0, 11, bb/100+0x30);
       DisplayOneChar(0, 12, bb/10%10+0x30);
       DisplayOneChar(0, 13, bb%10+0x30);
       //*****在LCD1602的第二行以16进制显示RGB*******************
       DisplayOneChar(1, 1, tab1[rb/16]);
       DisplayOneChar(1, 2, tab1[rb%16]);
       DisplayOneChar(1, 3, 'H');
       DisplayOneChar(1, 6, tab1[gb/16]);
       DisplayOneChar(1, 7, tab1[rb%16]);
       DisplayOneChar(1, 8, 'H');
       DisplayOneChar(1, 11,tab1[bb/16]);
       DisplayOneChar(1, 12,tab1[bb%16]);
       DisplayOneChar(1, 13,'H');
       Delay_ms(1000);//每隔2.5秒测试一次颜色
   }
}
//******************************************************
//白平衡子程序
void   celiang()
{
        TMOD=0x51;//设定T0以工作方式1定时10毫秒
     //*********求R值************************************
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=0;
     tcs230_s3=0;//选择红色滤光器
     tcs230_en=0;
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     rb=(unsigned long)(TH1*256+TL1)*255/ryz;
     if(rb>255)rb=255;//判断RGB值是否合法
     //***********求B值**************************************
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=0;
     tcs230_s3=1;//选择蓝色滤光器
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     bb=(unsigned long)(TH1*256+TL1)*255/byz;
     if(bb>255)bb=255;//判断RGB值是否合法     
     //***********求G值**************************************   
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=1;
     tcs230_s3=1;//选择绿色滤光器
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     tcs230_en=1;
     gb=(unsigned long)(TH1*256+TL1)*255/gyz;
     if(gb>255)gb=255;//判断RGB值是否合法  
}
//******************************************************
//白平衡子程序
void    baipingheng()
{
        TMOD=0x51;//设定T0以工作方式1定时10毫秒
     //**************求取红色因子***********************
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=0;
     tcs230_s3=0;//选择红色滤光器
     tcs230_en=0;
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     ryz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
     //**************求取蓝色因子***********************
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=0;
     tcs230_s3=1;//选择蓝色滤光器
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     byz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
     //**************求绿红色因子***********************
     TH0=(65536-10000)/256;
           TL0=(65536-10000)%256;
     TH1=0;
     TL1=0;
     tcs230_s2=1;
     tcs230_s3=1;//选择绿色滤光器
     TR0=1;//10毫秒开始计时
     TR1=1;//开始计数
     while(TF0==0);//等待定时器溢出
     TF0=0;//清楚定时器0溢出标志
     TR0=0;//关闭定时0
     TR1=0;
     tcs230_en=1;
     gyz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
}
/***********************************************
函数名称:LCD1602_Init
功    能:LCD1602初始化
入口参数:无
返 回 值:无       
备    注:详见数据手册定义。
************************************************/
void LCD1602_Init(void)  
{
        //将P04 P05 P06 P07设置为准双向口
        P0_Mode_IO_PU(PIN_4|PIN_5|PIN_6|PIN_7);  
        //将P41 P43 P44设置为准双向口
        P4_Mode_IO_PU(PIN_1|PIN_3|PIN_4);
       
  Delay_ms(15);                              //上电延时15ms
        LCD1602_SetFourMode();        //设置为四线模式
  Delay_ms(5);
  LCD1602_WriteCMD(0x28); //写显示指令(不检测忙信号)
  Delay_ms(5);
  LCD1602_WriteCMD(0x28); //写显示指令(不检测忙信号)
  LCD1602_CheckBusy();
  LCD1602_WriteCMD(0x28); //写显示指令
  LCD1602_CheckBusy();
  LCD1602_WriteCMD(0x08); //显示关闭
  LCD1602_CheckBusy();
  LCD1602_WriteCMD(0x01); //清屏
  LCD1602_CheckBusy();
  LCD1602_WriteCMD(0x06); //显示光标移动设置
  LCD1602_CheckBusy();
  LCD1602_WriteCMD(0x0c); //显示开及光标设置  
}

/***********************************************
函数名称:LCD1602_Display_Str
功    能:lcd1602显示字符函数
入口参数:str指针地址
返 回 值:无       
备    注:无
************************************************/
void LCD1602_Display_Str(uchar* str)
{
        while(*str!='\0')               //未到字符串末尾
  {
                LCD1602_CheckBusy();   //检测忙信号
    LCD1602_WriteDAT(*str);//写入数据
          str++;
  }
}

/*======================================================================
功 能:     在1602 指定位置显示一个字符:第一行位置0~15,第二行16~31
说 明:     第 X 行,第 y 列  注意:字符串不能长于16个字符
======================================================================*/
void DisplayOneChar( uchar X, uchar Y, uchar ASCII)
{
  X &= 0x1;
  Y &= 0xF; //限制Y不能大于15,X不能大于1
  if (X) Y |= 0x40; //当要显示第二行时地址码+0x40;
  Y |= 0x80; // 算出指令码
  LCM_WriteCMD(Y,0); //这里不检测忙信号,发送地址码
  LCD1602_Display_Str(&ASCII);
}

/***********************************************
函数名称:Delay_ms
功    能:STC8系列单片机1ms延时程序
入口参数:ms:延时的毫秒数
返 回 值:无       
备    注:示波器实测:1.01ms,内部时钟:24MHz           
************************************************/
void Delay_ms(unsigned int ms)
{
  unsigned int i;
  while( (ms--) != 0)
  {
    for(i = 0; i < 1850; i++);
  }            
}
回复

使用道具 举报

ID:958627 发表于 2021-8-4 09:02 | 显示全部楼层
湖南 发表于 2021-8-4 08:58
单片机和颜色传感器通信协议编写的有问题吧,没有读取到正确的数据

这是LCD1602的程序
#include "LCD1602.h"
//包含该函数可以使用_nop_()函数
#include <intrins.h>

#define  Busy  0x80
/***********************************************
函数名称:LCD1602_Delay1us
功    能:STC 1T单片机1us延时程序
入口参数:us:延时的微秒数
返 回 值:无       
备    注:外部时钟24MHz
************************************************/
void LCD1602_Delay1us(unsigned int us)
{
  while( us--)
  {
    _nop_();
  }            
}

/*************************************
* 函 数 名: LCD1602_WriteHalfByte
* 函数功能: 向lcd1602写入半个字节数据
* 入口参数: dat:数据
* 返    回: 无
* 备    注:写入的数据为高四位有效,低四位无效
**************************************/
void LCD1602_WriteHalfByte(unsigned char dat)
{
        LCD1602_D7=dat&0x80;        //取数据的第7位       
        LCD1602_D6=dat&0x40;        //取数据的第6位
        LCD1602_D5=dat&0x20;        //取数据的第5位       
        LCD1602_D4=dat&0x10;        //取数据的第4位
}
/*************************************
* 函 数 名: LCD1602_ReadHalfByte
* 函数功能: 从lcd1602半个读取字节数据
* 入口参数: dat:数据
* 返    回: 无
* 备    注:读出的数据为高四位有效,低四位无效
**************************************/
unsigned char LCD1602_ReadHalfByte(void)
{
        unsigned char LCD1602_Dat=0;
        //输入先置高
        LCD1602_D7=1;
        LCD1602_D6=1;
        LCD1602_D5=1;
        LCD1602_D4=1;

        if(LCD1602_D7==1)
        {
                LCD1602_Dat |=0x80;
        }
        if(LCD1602_D6==1)
        {
                LCD1602_Dat |=0x40;
        }
        if(LCD1602_D5==1)
        {
                LCD1602_Dat |=0x20;
        }
        if(LCD1602_D4==1)
        {
                LCD1602_Dat |=0x10;
        }

        return LCD1602_Dat;
}

void LCM_WriteCMD(unsigned char cmd,BusyC)
{
        unsigned char H_Data,L_Data;
       
   if(BusyC)
                LCD1602_CheckBusy();
         
        H_Data=cmd&0xf0;                          //取高四位
        L_Data=(cmd&0x0f)<<4;          //取低四位

  EN_Clr();
  RS_Clr();
  RW_Clr();

  LCD1602_Delay1us(10);                          
  EN_Set();
  LCD1602_Delay1us(10);                          //写入高四位
  LCD1602_WriteHalfByte(H_Data);
  LCD1602_Delay1us(10);
  EN_Clr();

        LCD1602_Delay1us(10);
  EN_Set();
  LCD1602_Delay1us(10);                          //写入低四位
  LCD1602_WriteHalfByte(L_Data);
  LCD1602_Delay1us(10);
  EN_Clr();
}
/*************************************
* 函 数 名: LCD1602_WriteCMD
* 函数功能: 向lcd1602写指令
* 入口参数: cmd:指令
* 返    回: 无
* 备    注:无
**************************************/
void LCD1602_WriteCMD(unsigned char cmd)
{
        unsigned char H_Data,L_Data;

        H_Data=cmd&0xf0;                          //取高四位
        L_Data=(cmd&0x0f)<<4;          //取低四位

  EN_Clr();
  RS_Clr();
  RW_Clr();

  LCD1602_Delay1us(10);                          
  EN_Set();
  LCD1602_Delay1us(10);                          //写入高四位
  LCD1602_WriteHalfByte(H_Data);
  LCD1602_Delay1us(10);
  EN_Clr();

        LCD1602_Delay1us(10);
  EN_Set();
  LCD1602_Delay1us(10);                          //写入低四位
  LCD1602_WriteHalfByte(L_Data);
  LCD1602_Delay1us(10);
  EN_Clr();
}
/***********************************************
函数名称:LCD1602_WriteDAT
功    能:向lcd1602写数据
入口参数:dat:数据
返 回 值:无       
备    注:无
************************************************/
void LCD1602_WriteDAT(unsigned char dat)
{
        unsigned char H_Data,L_Data;

        H_Data=dat&0xf0;                  //取高四位
        L_Data=(dat&0x0f)<<4; //取低四位

        EN_Clr();
  RS_Set();
  RW_Clr();

  LCD1602_Delay1us(10);
  EN_Set();
  LCD1602_Delay1us(10);                          //写入高四位
  LCD1602_WriteHalfByte(H_Data);
  LCD1602_Delay1us(10);
  EN_Clr();

        LCD1602_Delay1us(10);
  EN_Set();
  LCD1602_Delay1us(10);                          //写入低四位
  LCD1602_WriteHalfByte(L_Data);
  LCD1602_Delay1us(10);
  EN_Clr();
}
/***********************************************
函数名称:LCD1602_CheckBusy
功    能:检测lcd1602忙信号
入口参数:无
返 回 值:无       
备    注:无
************************************************/
void LCD1602_CheckBusy(void)
{
        unsigned char H_Data,L_Data;
       
  while(1)
  {   
    EN_Clr();                  
    RS_Clr();
    RW_Set();

    LCD1602_Delay1us(10);
    EN_Set();
    LCD1602_Delay1us(10);
    H_Data=LCD1602_ReadHalfByte();    //读取忙通道数据高四位
    LCD1602_Delay1us(10);
    EN_Clr();
               
                LCD1602_Delay1us(10);
    EN_Set();
    LCD1602_Delay1us(10);
    L_Data=LCD1602_ReadHalfByte();    //读取忙通道数据低四位
    LCD1602_Delay1us(10);
    EN_Clr();

    if((H_Data&0x80)!=0x80)                                          //判断忙信号
    {   
      break;
    }
  }
}
/***********************************************
函数名称:LCD1602_SetFourMode
功    能:设置lcd1602为四线模式。
入口参数:无
返 回 值:无       
备    注:无
************************************************/
void LCD1602_SetFourMode(void)
{
        EN_Clr();
  RS_Clr();
  RW_Clr();

  LCD1602_Delay1us(10);
  EN_Set();
  LCD1602_Delay1us(10);
  LCD1602_WriteHalfByte(0x20);//写入控制字节,四位模式
  LCD1602_Delay1us(10);
  EN_Clr();
}
回复

使用道具 举报

ID:958627 发表于 2021-8-4 09:03 | 显示全部楼层
湖南 发表于 2021-8-4 08:58
单片机和颜色传感器通信协议编写的有问题吧,没有读取到正确的数据

谢谢您了
回复

使用道具 举报

ID:844772 发表于 2021-8-4 09:03 | 显示全部楼层
我只在arduino用过,没出啥特别问题,只是离远的时候测的不准。
回复

使用道具 举报

ID:958627 发表于 2021-8-4 09:17 | 显示全部楼层
现在我已经有程序了,并且编译过并没有任何错误,所以想让各位帮我看一下是有哪里不妥当吗
回复

使用道具 举报

ID:958627 发表于 2021-8-4 09:18 | 显示全部楼层
这里是我的程序
回复

使用道具 举报

ID:844772 发表于 2021-8-4 15:44 | 显示全部楼层
bb=(unsigned long)(TH1*256+TL1)*255/byz; 这句有点问题,数据类型也不对,建议你先不用白平衡,改为bb=TH1*256+TL1,距离近点用不着白平衡。等差不多了,你再调白平衡。
回复

使用道具 举报

ID:958627 发表于 2021-8-4 15:58 | 显示全部楼层
glinfei 发表于 2021-8-4 15:44
bb=(unsigned long)(TH1*256+TL1)*255/byz; 这句有点问题,数据类型也不对,建议你先不用白平衡,改为bb=TH ...

你好,我尝试改变了,但是依旧显示的全部是255
回复

使用道具 举报

ID:844772 发表于 2021-8-4 17:22 | 显示全部楼层
安逸啊 发表于 2021-8-4 15:58
你好,我尝试改变了,但是依旧显示的全部是255

抱歉,我没说清楚,既然没做白平衡,它的范围是0-65535,你看是不是在这个范围,这决定你模块是否有效,
我主要认为你在强制类转换上有问题,简单办法是改比例因子算法: 1。是改这句 ryz=65535/(TH1*256+TL1);//其实这里的比例因子应该为255/(TH1*256+TL1)  2。是改bb=(TH1*256+TL1)/byz;
当然三个颜色都要改啊。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表