弄了几天终于实现了,就是传感器照在什么颜色物质上,RGB灯还还原出来,并上传电脑,和12864液晶显示器。哈哈哈哈,机器人有眼睛了。关键一点还是全开源。
制作出来的实物图如下:
单片机源码如下:
- #include <reg52.h>
- #include "usart.h"
- #include "iic.h"
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*
- 硬件接法:
- GY-33---c51
- 1、GY-33_RX---c51_TX,c51复位将发送A5 01 A6 给模块
- 2、c51_TX---FT232,STM32将数据上传给上位机
- 3、GY-33_TX---c51_RX,接收模块角度数据
- 软件说明:
- 该程序采用串口方式获取模块rgb数据,波特率9600
- 所以得用上位机先将模块串口设置成9600,然后再进行以上操作:
- 指令:A5 AE 53,模块需复位生效
- 注:中断函数位于stc_it.c
- */
- sfr T2MOD =0xC9; //定时器中断2TMOD必须定义
- /*-----------------------PWM定义---------------------------*/
- uchar PWM_T=0;//PWM脉冲周期PWM_T(max)=256*中断定时时间(1ms)
- //PWM物理地址通道定义,物理地址根据需要自由定义
- sbit PWM_IO0 = P1^0;
- sbit PWM_IO1 = P1^1;
- sbit PWM_IO2 = P1^2;
- //PWM脉冲占空比
- uchar PWM_IO0_ZKB=0; //脉冲占空比,0~255,=0时输出最大
- uchar PWM_IO1_ZKB=0;
- uchar PWM_IO2_ZKB=0;
- /*---------------定时器2初始化-------------------*/
- void timer2_init()//定时器2初始化
- {
- RCAP2H=0xff; //16位计数器,定时39us
- RCAP2L=0xdc; //X=0xffdc=65500;T=(65536-X)*机器周期(11.0592MHz,1.085us)
- //TH2=RCAP2H; //会自动重装
- //TL2=RCAP2L;
- T2CON=0;
- T2MOD=0;
- EA=1;
- ET2=1;
- TR2=1;
- }
- /*--------------定时器2中断服务程序----------------------------*/
- void timer2() interrupt 5
- {
- TF2=0; //注意:定时器2必须由软件对溢出标志位清零,
- //这里与定时器0和定时器1不同
- //PWM处理
- PWM_T++;
- if(PWM_T == 255)//取到最大值
- {PWM_T = PWM_IO0 = PWM_IO1 = PWM_IO2 = 0;} //所有通道脉冲拉至低电平
-
- //通道脉冲电平拉高
- if(PWM_T == PWM_IO0_ZKB) //通道0脉冲得高电平
- PWM_IO0 = 1;
-
- if(PWM_T == PWM_IO1_ZKB) //通道1脉冲得高电平
- PWM_IO1 = 1;
-
- if(PWM_T == PWM_IO2_ZKB) //通道2脉冲得高电平
- PWM_IO2 = 1;
-
-
- }
- void send_com(u8 datas)
- {
- u8 bytes[3]={0};
- bytes[0]=0xa5;
- bytes[1]=datas;//功能字节
- USART_Send(bytes,3);//发送帧头、功能字节、校验和
- }
- typedef struct
- {
- uint8_t Red;
- uint8_t Green;
- uint8_t Blue;
- } RGB;
- /***************************功能定义***************************/
- #define LCD12864_W_COM 0xF8 //写指令
- #define LCD12864_R_COM 0xFC //读指令
- #define LCD12864_W_DAT 0xFA //写数据
- #define LCD12864_R_DAT 0xFE //读数据
- #ifndef __LCD12864_H__
- #define __LCD12864_H__
- #define LCD12864_COM 0 //输入指令
- #define LCD12864_DAT 1 //输入数据
- #define LCD12864_CLEAR 0x01 //清除显示
- #define LCD12864_CURSOR 0x02 //位址归位,游标回原点
- #define LCD12864_CURSOR_RLF 0x04 //光标左移,整体显示不移动
- #define LCD12864_CURSOR_RRF 0x06 //光标右移,整体显示不移动
- #define LCD12864_CURSOR_RLN 0x05 //光标左移,整体显示移动
- #define LCD12864_CURSOR_RRN 0x07 //光标右移,整体显示移动
- #define LCD12864_DIS_OFF 0x08 //显示状态全关
- #define LCD12864_DIS_ON 0x0E //显示状态开
- #define LCD12864_DIS_CUR_ON 0x0E //游标显示开
- #define LCD12864_DIS_CURS_ON 0x0F //游标位置显示开
- #define LCD12864_CURSOR_RL 0x10 //游标左移
- #define LCD12864_CURSOR_RR 0x14 //游标右移
- #define LCD12864_CURDIS_RL 0x18 //整体显示左移,光标跟随
- #define LCD12864_CURDIS_RR 0x1C //整体显示又移,光标跟随
- #define LCD12864_COM_BASIC 0x30 //基本指令集动作
- #define LCD12864_COM_PLOT_ON 0x36 //扩展指令集动作,绘图显示ON
- #define LCD12864_COM_PLOT_OFF 0x34 //扩展指令集动作,绘图显示OFF
- #define LCD12864_STAND_TO 0x31 //进入待命模式
- #define LCD12864_PLACE_ROLL 0x03 //允许输入卷动位址
- #define LCD12864_PLACE_IRAM 0x02 //允许输入IRAM位址
- #define LCD12864_REVERES_13 0x04 //选择一、三行同时作反白显示
- #define LCD12864_REVERES_24 0x05 //选择二、四行同时作反白显示
- #define LCD12864_REST_ON 0x08 //进入睡眠模式
- #define LCD12864_REST_OFF 0x0C //脱离睡眠模式
- #define LCD12864_W_COM 0xF8 //写指令
- #define LCD12864_R_COM 0xFC //读指令
- #define LCD12864_W_DAT 0xFA //写数据
- #define LCD12864_R_DAT 0xFE //读数据
- //======串口模式=======
- sbit LCD12864_CS = P2^7; //片选信号输入
- sbit LCD12864_STD = P2^6; //串行数据输入
- sbit LCD12864_SCLK = P2^5; //串行移位脉冲输入
- sbit LCD12864_PSB = P2^4; //串并模式选择 0:串口,1:并口
- sbit LCDRST = P2^3;
- unsigned char code tabe[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//查表法//0-9数字
- /*****************************向12864写入8位数据*************************************/
- void LCD12864_Wbyte(uchar byte)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- LCD12864_SCLK = 0;
- byte <<= 1; //左移待写入数据,使最高位移至CY
- LCD12864_STD = CY; //写入一位数据
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- }
- }
- /***************************从12864读出8位数据***返回:sdat************************************/
- uchar LCD12864_Rbyte(void)
- {
- uchar i,sdat,temp1,temp2;
- temp1 = 0;
- temp2 = 0;
- //==========12864的串行数据输出形式是D7-D6-D5-D4-0-0-0-0-D3-D2-D1-D0-0-0-0-0,故要度两个八位整合==============
- for(i=0;i<8;i++)
- {
- temp1=temp1 << 1;
- LCD12864_SCLK = 0;
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- if( LCD12864_STD ) temp1|=0x01; //tempe1:D7-D6-D5-D4-0-0-0-0
- }
- for(i=0;i<8;i++)
- {
- temp2=temp2 << 1;
- LCD12864_SCLK = 0;
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- if( LCD12864_STD ) temp2|=0x01; //tempe2:D3-D2-D1-D0-0-0-0-0
- }
- sdat = ((temp1 & 0xf0)|(temp2 >> 4)); //取出D7\D6\D5\D4\D3\D2\D1\D0
- return sdat; //返回一个值(sdat)
- }
- /****************************读忙状态**************************************/
- void LCD12864_busy( void )
- {
- do LCD12864_Wbyte( LCD12864_R_COM ); //LCD12864_RW=11111,RW(1),RS(0),0
- while( LCD12864_Rbyte() & 0x80 ); //读BF,直到BF == 0
- }
- /*************************dat_com=0写指令,dat_com=1写数据*****************************************/
- void LCD12864_W (bit dat_com,uchar byte)
- {
- uchar temp;
- if(dat_com == 0) //为零,写入指令
- temp = LCD12864_W_COM; //11111,RS(0),RW(0),0
- else //否则,写入数据
- temp = LCD12864_W_DAT; //11111,RS(1),RW(0),0
- LCD12864_CS = 1; //片选使能
- LCD12864_busy(); //LCD忙检测
- LCD12864_Wbyte(temp); //写入模式选择,指令还是数据
- LCD12864_Wbyte(byte&0xf0); //写入字节
- LCD12864_Wbyte((byte<<4)&0xf0); //写入字节
- LCD12864_CS = 0; //片选关闭
- }
- /****************************LCD12864初始化**************************************/
- void LCD12864_Init(void)
- {
- LCDRST=1;
- LCD12864_PSB = 0; //选择串口模式
- LCD12864_W(LCD12864_COM,0x30); //基本指令功能.
- LCD12864_W(LCD12864_COM,0x03); //允许输入卷动位址
- LCD12864_W(LCD12864_COM,0x0c); //脱离随眠状态,显示打开,关光标,反白关.
- LCD12864_W(LCD12864_COM,0x01); //清屏指令.
- LCD12864_W(LCD12864_COM,0x06); //AC自动加一,光标右移,整体显示不移动
- }
- /**************************LCD12864字符位置自定义显示****************************************/
- void LCD12864_WPoss(uchar x,uchar y,uchar *buff)
- {
- uchar addr,i=0;
- switch (x)
- {
- case 0:addr=0x80;break;
- case 1:addr=0x90;break;
- case 2:addr=0x88;break;
- case 3:addr=0x98;break;
- }
- addr=addr+y;
- LCD12864_W(LCD12864_COM,LCD12864_COM_BASIC); //8BitMCU,基本指令集合
- LCD12864_W(LCD12864_COM,addr); //显示在自定义位置
- while(buff[i]!='\0')[/i][i]
- {
- LCD12864_W(LCD12864_DAT,buff[i++]);
- if(++y==16)
- {
- y=0;
- if(++x==4) x=0;
- switch (x)
- {
- case 0:addr=0x80;break;
- case 1:addr=0x90;break;
- case 2:addr=0x88;break;
- case 3:addr=0x98;break;
- }
- addr=addr+y;
- LCD12864_W(LCD12864_COM,addr);
- }
-
- }
- }
- void Disp_img(unsigned char *img) //图形方式12864显示字模221 横向取膜
- {
- unsigned char i,j;
- unsigned int k = 0;
- LCD12864_W(0,0x36); //图形方式
- for(i=0;i<32;i++)
- {
- LCD12864_W(0,0x80+i);
- LCD12864_W(0,0x80);
- for(j=0;j<16;j++)
- {
- LCD12864_W(1,img[k++]);
- }
- }
- for(i=0;i<32;i++)
- {
- LCD12864_W(0,0x80+i);
- LCD12864_W(0,0x88);
- for(j=0;j<16;j++)
- {
- LCD12864_W(1,img[k++]);
- }
- }
- }
- /************************显示1************************************/
- void display1(long temp)
- {
- uchar dt1,dt2,dt3,dt4,dt5,dt6,dt7,dt8;
- //temp=12345678;
- dt1 = temp%10;//1位
- dt2 = temp%100/10;//2位
- dt3 = temp%1000/100;//3位
- dt4 = temp%10000/1000;//4位
- dt5 = temp%100000/10000;//5位
- dt6 = temp%1000000/100000;//6位
- dt7 = temp%10000000/1000000;//7位
- dt8 = temp/10000000;//8位 最高位
- LCD12864_WPoss(1,0,"红色R:");//第1行显示表1
- // LCD12864_W(0,0x80+3);//LCD12864_W ((0或1),****) 0写指令 1写数据
- // LCD12864_W(1,tabe[dt8]);//6位
- //LCD12864_W(1,tabe[dt7]);//5位
- // LCD12864_W(1,tabe[dt6]);//4位
- // LCD12864_W(1,tabe[dt5]);//3位
- //LCD12864_W(1,0x2e);
- //LCD12864_W(1,tabe[dt4]);//4位
- LCD12864_W(1,tabe[dt3]);//3位
- LCD12864_W(1,tabe[dt2]);//4位
- LCD12864_W(1,tabe[dt1]);//3位
- LCD12864_WPoss(1,7,"%");//第1行显示表1
- }
- /************************显示2************************************/
- void display2(long temp)
- {
- uchar dt1,dt2,dt3,dt4,dt5,dt6,dt7,dt8;
- //temp=12345678;
- dt1 = temp%10;//1位
- dt2 = temp%100/10;//2位
- dt3 = temp%1000/100;//3位
- dt4 = temp%10000/1000;//4位
- dt5 = temp%100000/10000;//5位
- dt6 = temp%1000000/100000;//6位
- dt7 = temp%10000000/1000000;//7位
- dt8 = temp/10000000;//8位 最高位
- LCD12864_WPoss(2,0,"绿色G:");//第1行显示表1
- // LCD12864_W(0,0x80+3);//LCD12864_W ((0或1),****) 0写指令 1写数据
- // LCD12864_W(1,tabe[dt8]);//6位
- // LCD12864_W(1,tabe[dt7]);//5位
- // LCD12864_W(1,tabe[dt6]);//4位
- // LCD12864_W(1,tabe[dt5]);//3位
- //LCD12864_W(1,0x2e);
- // LCD12864_W(1,tabe[dt4]);//4位
- LCD12864_W(1,tabe[dt3]);//3位
- LCD12864_W(1,tabe[dt2]);//4位
- LCD12864_W(1,tabe[dt1]);//3位
- LCD12864_WPoss(2,7,"%");//第1行显示表1
- }
- /************************显示3************************************/
- void display3(long temp)
- {
- uchar dt1,dt2,dt3,dt4,dt5,dt6,dt7,dt8;
- //temp=12345678;
- dt1 = temp%10;//1位
- dt2 = temp%100/10;//2位
- dt3 = temp%1000/100;//3位
- dt4 = temp%10000/1000;//4位
- dt5 = temp%100000/10000;//5位
- dt6 = temp%1000000/100000;//6位
- dt7 = temp%10000000/1000000;//7位
- dt8 = temp/10000000;//8位 最高位
- LCD12864_WPoss(3,0,"兰色B:");//第1行显示表1
- // LCD12864_W(0,0x80+3);//LCD12864_W ((0或1),****) 0写指令 1写数据
- //LCD12864_W(1,tabe[dt8]);//6位
- //LCD12864_W(1,tabe[dt7]);//5位
- //LCD12864_W(1,tabe[dt6]);//4位
- //LCD12864_W(1,tabe[dt5]);//3位
- //LCD12864_W(1,0x2e);
- // LCD12864_W(1,tabe[dt4]);//4位
- LCD12864_W(1,tabe[dt3]);//3位
- LCD12864_W(1,tabe[dt2]);//4位
- LCD12864_W(1,tabe[dt1]);//3位
- LCD12864_WPoss(3,7,"%");//第1行显示表1
- }
- int main(void)
- {
- u8 sum=0,i=0;
- RGB rgb={0,0,0};
- Usart_Int(9600);
- send_com(0x01);//发送读方位角指令
-
- LCD12864_Init();
- LCD12864_WPoss(0,1,"TCS34725颜色");//第1行显示表1
-
- timer2_init();//定时器2初始化
-
- while(1)
- {
- if(Receive_ok)//串口接收完毕
- {
- for(sum=0,i=0;i<(rgb_data[3]+4);i++)//rgb_data[3]=3
- sum+=rgb_data[i];[/i][i]
- if(sum==rgb_data[i])//校验和判断[/i][i]
- {
- rgb.Red=rgb_data[4];
- rgb.Green=rgb_data[5];
- rgb.Blue=rgb_data[6];
- send_3out(&rgb_data[4],3,0x45);//上传给上位机
-
-
- display1(rgb.Red);//显示红色R:
- display2(rgb.Green);//显示绿色G:G:
- display3(rgb.Blue);//显示兰色B:
-
- //通过TCS34725传感器感受的光线进行PWM三基色彩还原、、
-
- PWM_IO0_ZKB = 255-rgb.Red; //红色R:
- PWM_IO1_ZKB = 255-rgb.Green;//绿色G:
- PWM_IO2_ZKB = 255-rgb.Blue;//兰色B:
-
-
-
- }
- Receive_ok=0;//处理数据完毕标志
- }
- }
- }
复制代码
全部资料51hei下载地址:
颜色传感器电脑端程序.zip
(1.28 MB, 下载次数: 152)
128显串STC89TCS34725颜色OK2.zip
(71.07 KB, 下载次数: 183)
|