|
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- //**********宏定义所需指令
- #define BASIC_SET 0x30
- #define EXTEND_SET 0x34
- #define DRAW_ON 0x36
- #define DRAW_OFF 0x34
- //*************端口定义
- sbit LCD_RS = P3^5;
- sbit LCD_RW = P3^6;
- sbit LCD_EN = P3^4;
- sbit DQ=P2^2;
- //sbit k1=P1^0;
- //定义温度DS18B20接口
- //************变量定义
- uchar code t0[]="温度 . ℃";
- uchar code t1[]="0123456789"; //利用一个温度表解决温度显示乱码
- uchar i,k,a,b;
- unsigned int temperature;
- unsigned char temp_x; //温度小数部分
- unsigned int temp_disp;
- //****************短延时
- void delay(uint k)
- {
- uint i;
- uchar j;
- for(i = 0; i < k ;i ++)
- for(j = 120; j>0 ;j--);
- }
- //***********12864写指令函数
- void write_com(uchar cmd)
- {
- LCD_RS = 0;
- LCD_RW = 0;
-
- delay(5);
- LCD_EN = 1; P0 = cmd;
- delay(10);
- LCD_EN = 0;
- }
- //********12864写数据函数
- void write_dat(uchar dat)
- {
- LCD_RS = 1;
- LCD_RW = 0;
- delay(5);
- LCD_EN = 1; P0 = dat;
- delay(10);
- LCD_EN = 0;
- }
- //
- uchar read_dat(void)
- {
- uchar temp;
- P0 = 0XFF;
- //释放数据线
- LCD_RS = 1;
- //数据
- LCD_RW = 1;
- // 读模式
- LCD_EN = 1;
- //E为高电平进行读数据或指令
- delay(1);
- temp = P0;
- LCD_EN = 0;
- return temp;
- }
- //设置光标(地址)函数
- //参数说明:x---为行号,y为列号
- void set_cursor(unsigned char x, unsigned char y)
- {
- unsigned char i;
- switch(x)
- //确定行号
- {
- case 0x00: i=0x80; break; //第一行
- case 0x01: i=0x90; break; //第二行
- case 0x02: i=0x88; break; //第三行
- case 0x03: i=0x98; break; //第四行
- default : break;
- }
- i = y+i; //确定列号
- write_com(i);
- }
- //********************************************************
- //显示字符函数
- //********************************************************
- void display_char(unsigned char Alphabet)
- {
- write_dat(Alphabet);
- //写入需要显示字符的显示码
- }
- //********************************************************
- //指定位置显示字符串函数
- //参数说明:x为行号,y为列号
- //********************************************************
- void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet)
- {
- unsigned char i=0;
- set_cursor(x,y); //设置显示的起始地址
- while(Alphabet[i]!='\0')
- {
- write_dat(Alphabet[i]); //写入需要显示字符的显示码
- i++;
- }
- }
- //以下为GDRAM绘图部分
- //绘图显示的清屏函数(因清屏指令在画图时不能用)
- void gui_clear()
- {
- uchar i , j , k;
- write_com(EXTEND_SET);//扩展指令集,8位数据传输
- write_com(DRAW_OFF);//绘图显示关闭
- for(i = 0; i < 2; i ++)//分上下两屏写
- {
- for(j = 0; j < 32; j ++)
- {
- write_com(0x80 + j);//写y坐标
- delay(1);
- if(i == 0) //写x坐标
- {
- write_com(0x80);
- delay(1);
- }
- else //写下半屏
- {
- write_com(0x88);
- delay(1);
- }
- for(k = 0; k < 16; k ++)//写一整行数据
- {
- write_dat(0x00);//写高字节
- write_dat(0x00);//写低字节
- delay(1);
- }
-
- }
- }
- write_com(DRAW_ON);//打开绘图显示
- write_com(BASIC_SET);//打开基本指令集
- }
- //(给定坐标并打点的)任意位置打点函数
- void lcd_set_dot(uchar x,uchar y)
- {
- uchar x_byte,x_bit; //确定在坐标的那一字节哪一位
- uchar y_ping , y_bit; //确定在坐标的哪一屏哪一行
- uchar tmph , tmpl; //定义两个临时变量,用于存放读出来的数据
- write_com(EXTEND_SET); //扩展指令集
- write_com(DRAW_OFF); //绘图显示关闭
- x_byte = x / 16; //算出在哪一字节,注意一个地址是16位的
- x_bit = x % 16; //& 0x0f;//算出在哪一位
- y_ping = y / 32; //确定在上半屏还是下半屏,0代表上半屏,1代表下半屏
- y_bit = y % 32; //& 0x1f;//确定在第几行
- write_com(0X80 + y_bit);//先写垂直地址(最高位必须)
- write_com(0x80 + x_byte + 8 * y_ping);//水平坐标,下半屏坐标起始地址为0x88,(+8*y_ping)就是用来确定上半屏还是下半屏
- read_dat();//预读取数据
- tmph = read_dat();//读取当前显示高8位数据
- tmpl = read_dat();//读取当前显示低8位数据
- delay(1);
- write_com(0x80 + y_bit);//读操作会改变AC,所以重新设置一下
- write_com(0x80 + x_byte + 8 * y_ping);
- delay(1);
- if(x_bit < 8)
- {
- write_dat(tmph | (0x01 << (7 - x_bit)));//写高字节,因为坐标是从左向右的,GDRAM高位在昨,低位在右
- write_dat(tmpl);//原低位数据送回
- }
- else
- {
- write_dat(tmph);//原高位数据送回
- write_dat(tmpl | (0x01 << (15 - x_bit)));
- }
- write_com(DRAW_ON); //打开绘图显示
- write_com(BASIC_SET);//回到基本指令集
- }
- //画水平线函数
- //x0、x1为起始点和终点的水平坐标,y为垂直坐标
- //**********************************************************
- void gui_hline(uchar x0, uchar x1, uchar y)
- {
- uchar bak;//用于对两个数互换的中间变量,使x1为大值
- if(x0 > x1)
- {
- bak = x1;
- x1 = x0;
- x0 = bak;
- }
- do
- {
- lcd_set_dot(x0 , y);//从左到右逐点显示
- x0 ++;
- }
- while(x1 >= x0);
- }
- //***********画竖直线函数***********************************//
- //x为起始点和终点的水平坐标,y0、y1为垂直坐标***************//
- //**********************************************************//
- void gui_rline(uchar x, uchar y0, uchar y1)
- {
- uchar bak;//用于对两个数互换的中间变量,使y1为大值
- if(y0 > y1)
- {
- bak = y1;
- y1 = y0;
- y0 = bak;
- }
- do
- {
- lcd_set_dot(x , y0);//从上到下逐点显示
- y0++;
-
- }
- while(y1 >= y0);
- }
- //*********任意两点间画直线*********************************//
- //x0、y0为起始点坐标,x1、y1为终点坐标**********************//
- //**********************************************************//
- void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1)
- {
- char dx; //直线x轴差值
- char dy; //直线y轴差值
- char dx_sym; //x轴增长方向,为-1时减值方向,为1时增值方向
- char dy_sym; //y轴增长方向,为-1时减值方向,为1时增值方向
- char dx_x2; //dx*2值变量,用于加快运算速度
- char dy_x2; //dy*2值变量,用于加快运算速度
- char di; //决策变量
- if(x0 == x1)//判断是否为垂直线
- {
- gui_rline(x0 , y0 , y1);//画垂直线
- return;
- }
- if(y0 == y1)//判断是否为水平线
- {
- gui_hline(x0 , x1 , y0);//画水平线
- return;
- }
- dx = x1 - x0;//求取两点之间的差值
- dy = y1 - y0;//****判断增长方向,或是否为水平线、垂直线、点*//
- if(dx > 0)//判断x轴方向
- dx_sym = 1;
- else
- {
- if(dx < 0)
- dx_sym = -1;
- else
- {
- gui_rline(x0 , y0 , y1);
- return;
- }
- }
- if(dy > 0)//判断y轴方向
- dy_sym = 1;
- else
- {
- if(dy < 0)
- dy_sym = -1;
- else
- {
- gui_hline(x0 , x1 , y0);
- return;
- }
- }
- /*将dx、dy取绝对值***********/
- dx = dx_sym * dx;
- dy = dy_sym * dy;
- /****计算2倍的dx、dy值*******/
- dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点对应
- dy_x2 = dy * 1; /***使用bresenham法进行画直线***/
- if(dx >= dy)//对于dx>=dy,使用x轴为基准
- {
- di = dy_x2 - dx;
- while(x0 != x1)
- {
- lcd_set_dot(x0,y0);
- x0 +=dx_sym;
- if(di < 0)
- di += dy_x2;//计算出下一步的决策值
- else
- {
- di += dy_x2 - dx_x2;
- y0 += dy_sym;
- }
- }
- lcd_set_dot(x0, y0);//显示最后一点
- }
- else //对于dx<dy使用y轴为基准
- {
- di = dx_x2 - dy;
- while(y0 != y1)
- {
- lcd_set_dot(x0, y0);
- y0 += dy_sym;
- if(di < 0)
- di += dx_x2;
- else
- {
- di += dx_x2 - dy_x2;
- x0 += dx_sym;
- }
- }
- lcd_set_dot(x0, y0);//显示最后一点
- }
- }
- //以上为自定义字库部分
- //****************12864初始化函数
- void lcd_init()
- {
- write_com(0x30);//基本指令操作,8位并口
- delay(1);
- write_com(0x0c);//设置为游标右移,DDRAM地址加一,画面不动
- delay(1);
- write_com(0x01);//显示开,关光标
- delay(1);
- write_com(0x06);//清除lcd显示内容
- delay(1);
- } //5ms延时
- void Delay5Ms(void)
- {
- unsigned int TempCyc = 5552;
- while(TempCyc--);
- }
- //400ms延时
- void Delay400Ms(void)
- {
- unsigned char TempCycA = 5;
- unsigned int TempCycB;
- while(TempCycA--)
- {
- TempCycB=7269;
- while(TempCycB--);
- };
- }
- /*************DS18B20温度读取模块*************/
- void delay_nus(unsigned char n)
- {
- while(n--)
- {
- _nop_();
- _nop_();
- }
- }
- bit ds18b20_reset(void)
- {
- CY = 1;
- while(CY)
- {
- DQ = 0; //送低电平复位信号
- delay_nus(240); //至少延时480us
- delay_nus(240);
- DQ = 1; //释放数据线
- delay_nus(60); //等待60us
- CY = DQ; //检测存在脉冲
- delay_nus(240); //等待设备释放数据线
- delay_nus(180);
- }
- return 1;
- }
- unsigned char ds18b20_readbyte(void)
- {
- unsigned char i;
- unsigned char dat = 0;
- for(i=0;i<8;i++)
- {
- dat >>= 1;
- DQ = 0; //开始时间片
- delay_nus(1); //延时等待
- DQ = 1; //准备接收
- delay_nus(1); //延时
- if(DQ) dat |= 0x80; //读取数据
- delay_nus(60); //等待时间片结束
- }
- return dat;
- }
- void ds18b20_writebyte(unsigned char dat)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- DQ = 0;
- delay_nus(1);
- dat >>= 1;
- DQ = CY;
- delay_nus(60);
- DQ = 1;
- delay_nus(1);
- }
- }
- void read_temp(void)
- {
- if(ds18b20_reset())
- {
- ds18b20_writebyte(0xcc);
- ds18b20_writebyte(0x44);
- if(ds18b20_reset())
- {
- ds18b20_writebyte(0xcc);
- ds18b20_writebyte(0xbe);
- temperature = ds18b20_readbyte(); //读温度整数值
- temperature = (ds18b20_readbyte() << 8) + temperature;
- temp_x = (unsigned char)(temperature & 0x000f); //读温度小数值
- temp_x = (unsigned char)(((unsigned int)temp_x * 625) / 1000);
- temperature >>= 4;
- temp_disp = temperature * 10 + temp_x;
- }
- }
- }
- //*****************************显示函数
- void display()
- {
- uint num;
- uint shi,ge,xiaoshu;
- num=temp_disp;
- shi=num/100;
- ge=num/10%10;
- xiaoshu=num%10;
- if(k==100)
- {
- ++i;
- k=0;
- if(i>127)
- {
- i=0;
- a=0;
- b=0;
- gui_clear();//画图时清屏函数
- gui_line(0,15,0,63);
- gui_line(0,63,127,63);
- }
- gui_line(a,63-b,i,63-shi*10-ge);
- b=shi*10+ge;
- a=i;
- }
- write_com(0x82);
- write_dat(t1[shi]);
- write_dat(t1[ge]);
- write_com(0x84);
- write_dat(t1[xiaoshu]);
- }
- void init_time0()
- {
- TMOD |= 0x10;
- TH1=(65536-50000)/256; //50毫秒
- TL1=(65536-50000)%256;
- EA=1;
- ET1=1;
- TR1=1;
- }
-
-
- void main()
- {
- init_time0(); //中断
- lcd_init();//12864初始化函数
- gui_clear();//画图时清屏函数
- delay(10);
- display_string(0,0,t0);
- gui_line(0,15,0,63);
- gui_line(0,63,127,63);
-
- while(1)
- {
- display();read_temp();
- }
- }
- void time0() interrupt 3
- {
- TH1=(65536-50000)/256; //,50毫秒
- TL1=(65536-50000)%256;
- k++;
- }
复制代码 |
|