實現功能:實現功能:對顏色傳感器輸出RGB
使用芯片:AT89S52 或者 STC89C52
晶振:12MHZ
編譯環境:Keil
單片機源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- //==============LCD1602接口連接方法=====================
- /*-----------------------------------------------------
- |DB0-----P0.0 | DB4-----P0.4 | RW-------P2.3 |
- |DB1-----P0.1 | DB5-----P0.5 | RS-------P2.4 |
- |DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 |
- |DB3-----P0.3 | DB7-----P0.7 |
- ---------------------------------------------------*/
- //================================================*/
- #define LCM_Data P0 //LCD1602數據接口
- #define Busy 0x80 //用于檢測LCM狀態字中的Busy標識
- sbit LCM_RW = P2^3; //讀寫控制輸入端,LCD1602的第五腳
- sbit LCM_RS = P2^4; //寄存器選擇輸入端,LCD1602的第四腳
- sbit LCM_E = P2^2; //使能信號輸入端,LCD1602的第6腳
- sbit LED1=P1^0;
- sbit LED2=P1^1;
- sbit LED3=P1^2;
- //=================顏色傳感模塊連接=====================
- /*-----------------------------------------------------
- |EO-----GND
- |S0-----VCC | S2-----P2.0 | OUT-------P3.5
- |S1-----VCC | S3-----P2.1 |
- ---------------------------------------------------*/
- sbit tcs230_s2=P2^0;//TCS230 S2接單片機P2.0
- sbit tcs230_s3=P2^1;//TCS230 S3接單片機P2.1
- sbit tcs230_en=P3^0; //TCS230 EN(E0)接GND
- //**************函數聲明***************************************
- void WriteDataLCM (uchar WDLCM);//LCD模塊寫數據
- void WriteCommandLCM (uchar WCLCM,BuysC); //LCD模塊寫指令
- uchar ReadStatusLCM(void);//讀LCD模塊的忙標
- void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置顯示一個字符
- void LCMInit(void);//LCD初始
- void DelayMs(uint Ms);//1MS基準延時程序
- void baipingheng();//白平衡子程序
- void celiang();//實際顏色程序
- uint ryz,gyz,byz;//分別定義紅色因子 綠色因子 藍色因子
- uint rb,gb,bb,z;//RGB值
- uchar tab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- //***********************主程序******************************
- main()
- {
- P0=0xff;
- TMOD=0x51;//設定T0以工作方式1定時10毫秒
- LCMInit();//LCD初始
- baipingheng();//上電時先白平衡一次
- while(1)
- {
- celiang();//顏色測試
- z = rb+gb+bb;
- 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);
- DisplayOneChar(1, 6, 'Y');
- DisplayOneChar(1, 7, 'u');
- DisplayOneChar(1, 8, 'a');
- DisplayOneChar(1, 9, 'n');
- //*****?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');
- if (tab1[rb/16]>=tab1[gb/16]) //紅色
- {
- P1=0xfe;
- DisplayOneChar(1, 3, '1');
- DisplayOneChar(1, 4, '0');
- DisplayOneChar(1, 5, '0');
- }
- if( tab1[gb/16]>=tab1[bb/16]) //綠色
- {
- P1=0xfd;
- DisplayOneChar(1, 3, '5');
- DisplayOneChar(1, 4, '0');
- DisplayOneChar(1, 5, ' ');
- }
- if(tab1[bb/16]>=tab1[rb/16]) //藍色
- {
- P1=0xfb;
- DisplayOneChar(1, 3, '1');
- DisplayOneChar(1, 4, '0');
- DisplayOneChar(1, 5, ' ');
- }
- DelayMs(250);//每隔0.25秒測試一次顏色
- }
- }
- //******************************************************
- //白平衡子程序
- void celiang()
- {
- //*********求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-30;
- 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-70;
- 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)-70;
- if(gb>255)gb=255;//判斷RGB值是否合法
- }
- //******************************************************
- //白平衡子程序
- void baipingheng()
- {
- //**************求取紅色因子***********************
- 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)
- }
- /*======================================================================
- LCM初始化
- ======================================================================*/
- void LCMInit(void)
- {
- LCM_Data = 0;
- WriteCommandLCM(0x38,0); //三次顯示模式設置,不檢測忙信號
- DelayMs(5);
- WriteCommandLCM(0x38,0);
- DelayMs(5);
- WriteCommandLCM(0x38,0);
- DelayMs(5);
- WriteCommandLCM(0x38,1); //顯示模式設置,開始要求每次檢測忙信號
- WriteCommandLCM(0x08,1); //關閉顯示
- WriteCommandLCM(0x01,1); //顯示清屏
- WriteCommandLCM(0x06,1); // 顯示光標移動設置
- WriteCommandLCM(0x0C,1); // 顯示開及光標設置
- DelayMs(100);
- }
- //==============================LCD1602顯示子程序================================================
- // 寫數據函數: E =高脈沖 RS=1 RW=0
- //======================================================================*/
- void WriteDataLCM(uchar WDLCM)
- {
- ReadStatusLCM(); //檢測忙
- LCM_Data = WDLCM;
- LCM_RS = 1;
- LCM_RW = 0;
- LCM_E = 0; //若晶振速度太高可以在這后加小的延時
- LCM_E = 0; //延時
- LCM_E = 1;
- }
- /*====================================================================
- 寫指令函數: E=高脈沖 RS=0 RW=0
- ======================================================================*/
- void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC為0時忽略忙檢測
- {
- if (BuysC) ReadStatusLCM(); //根據需要檢測忙
- LCM_Data = WCLCM;
- LCM_RS = 0;
- LCM_RW = 0;
- LCM_E = 0;
- LCM_E = 0;
- LCM_E = 1;
- }
- /*====================================================================
- 正常讀寫操作之前必須檢測LCD控制器狀態:E=1 RS=0 RW=1;
- DB7: 0 LCD控制器空閑,1 LCD控制器忙。
- 讀狀態
- ======================================================================*/
- uchar ReadStatusLCM(void)
- {
- LCM_Data = 0xFF;
- LCM_RS = 0;
- LCM_RW = 1;
- LCM_E = 0;
- LCM_E = 0;
- LCM_E = 1;
- while (LCM_Data & Busy); //檢測忙信號
- return(LCM_Data);
- }
- /*======================================================================
- 功 能: 在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; // 算出指令碼
- WriteCommandLCM(Y, 0); //這里不檢測忙信號,發送地址碼
- WriteDataLCM(ASCII);
- }
- /*====================================================================
- 設定延時時間:x*1ms
- ====================================================================*/
- void DelayMs(uint Ms)
- {
- uint i,TempCyc;
- for(i=0;i<Ms;i++)
- {
- TempCyc = 250;
- while(TempCyc--);
- }
- }
復制代碼
|