#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P2^2;
uint wendu;
sbit sce = P1^3; //片选
sbit res = P1^4; //复位,0复位
sbit dc = P1^2; //1写数据,0写指令
sbit sdin = P1^1; //数据
sbit sclk = P1^0; //时钟
/*------------------------------------shuzihanzi-----------------------------------*/
unsigned char code shuzi[]={
//0
0xF8,0x04,0x04,0x04,0xF8,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//1
0x00,0x08,0xFC,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
//
0x18,0x84,0x44,0x44,0x38,0x00,0x03,0x02,0x02,0x02,0x02,0x00,
//3
0x88,0x04,0x24,0x24,0xD8,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//4
0xC0,0xB0,0x88,0xFC,0x80,0x00,0x00,0x00,0x00,0x03,0x00,0x00,
//5
0x3C,0x14,0x14,0x14,0xE4,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//6
0xF8,0x24,0x24,0x24,0xC8,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//7
0x04,0x04,0x04,0xE4,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
//8
0xD8,0x24,0x24,0x24,0xD8,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//9
0x38,0x44,0x44,0x44,0xF8,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//'
0x00,0x00,0x04,0x0A,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//C
0xF8,0x04,0x04,0x04,0x98,0x00,0x01,0x02,0x02,0x02,0x01,0x00,
//.
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
//:
0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
//T
0x04,0x04,0xFC,0x04,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00
};
unsigned char code hanzi[]={
0x22,0x44,0x00,0xC0,0x5F,0xD5,0x55,0xD5,0x5F,0xC0,0x00,0x00,0x04,
0x02,0x09,0x0F,0x08,0x0F,0x08,0x0F,0x08,0x0F,0x08,0x00,/*"温",0*/
0x00,0xFE,0x0A,0x8A,0xBE,0xAA,0xAB,0xAA,0xBE,0x8A,0x0A,0x00,0x08,
0x07,0x00,0x08,0x09,0x0A,0x04,0x04,0x0A,0x09,0x08,0x00,/*"度",1*/
0x11,0x22,0x80,0x3E,0x2A,0xEA,0x2A,0xEA,0x2A,0x3E,0x80,0x00,0x04,
0x02,0x08,0x09,0x08,0x0F,0x08,0x0F,0x08,0x09,0x08,0x00,/*"湿",2*/
0x00,0xFE,0x0A,0x8A,0xBE,0xAA,0xAB,0xAA,0xBE,0x8A,0x0A,0x00,0x08,
0x07,0x00,0x08,0x09,0x0A,0x04,0x04,0x0A,0x09,0x08,0x00,/*"度",3*/
0x20,0x22,0x24,0xE8,0x20,0x3F,0x20,0xE8,0x24,0x22,0x20,0x00,0x08,
0x04,0x02,0x01,0x00,0x00,0x00,0x07,0x08,0x08,0x0E,0x00,/*"光",4*/
0xF2,0x92,0x9E,0x00,0xE0,0x2F,0x29,0xF9,0x29,0x2F,0xE0,0x00,0x08,
0x08,0x07,0x00,0x09,0x09,0x09,0x0F,0x09,0x0D,0x09,0x00,/*"强",5*/
};
/*--------------------------5110驱动------------------------------*/
/**********************延时函数************************/
void delayus(uint z) //微妙级延时
{
uint y;
for(y=z;y>0;y--);
}
void delayms(uint z) //毫秒级延时
{
uint x,y;
for(y=z;y>0;y--)
for(x=1400;x>0;x--);
}
/********************写字节**************************/
void LCD_write_byte(unsigned char dt, unsigned char command) //写字节
{
unsigned char i;
sce=0; //5110片选有效,允许输入数据
dc=command; //0写指令,1写数据
for(i=0;i<8;i++) //传送8bit数据
{
if(dt&0x80)
sdin=1;
else
sdin=0;
dt=dt<<1;
sclk=0;
sclk=1;
}
dc=1;
sce=1; //禁止5110
sdin=1;
}
/*******************初始化********************************************/
void LCD_init(void) //初始化(command=0,写指令)
{
res=0;
delayms(1);
res=1;
LCD_write_byte(0x21,0);//初始化Lcd,功能设定使用扩充指令
LCD_write_byte(0xa0,0);//设定液晶偏置电压(5v),5110接5V时偏置电压改为(0xa7,0),接3.3V时改为(0xc0,0)
LCD_write_byte(0x20,0);//使用基本指令
LCD_write_byte(0x0C,0);//设定显示模式,正常显示
}
/*********************设置初始坐标************************************/
void LCD_set_XY(unsigned char X, unsigned char Y) //设置LCD坐标,X:0-83 Y:0-5
{
LCD_write_byte(0x40 | Y, 0);// column //列
LCD_write_byte(0x80 | X, 0);// row //行
}
/**********************清屏函数***************************************/
void LCD_clear(void) //LCD清屏函数
{
unsigned char t;
unsigned char k;
LCD_set_XY(0,0); //设置RAM起始地址
for(t=0;t<6;t++)
{
for(k=0;k<84;k++)
{
LCD_write_byte(0x00,1); //写数据
}
}
}
/****************************输入数字**************************************/
void LCD_write_shu(unsigned char row, unsigned char page,unsigned char c) //row:列 page:页 dd:字符,page范围为0-5,
{
unsigned char i;
LCD_set_XY(row*6, page);// 列,页
for(i=0; i<6;i++)
{
LCD_write_byte(shuzi[c*12+i],1);
}
LCD_set_XY(row*6, page+1);// 列,页
for(i=6; i<12;i++)
{
LCD_write_byte(shuzi[c*12+i],1);
}
}
/******************************输入汉字*************************************/
void LCD_write_zi(unsigned char row, unsigned char page,unsigned char c)
{
unsigned char i;
LCD_set_XY(row*6, page);// 列,页
for(i=0; i<12;i++)
{
LCD_write_byte(hanzi[c*24+i],1);
}
LCD_set_XY(row*6, page+1);// 列,页
for(i=12; i<24;i++)
{
LCD_write_byte(hanzi[c*24+i],1);
}
}
/*-----------------------------------------18b20驱动--------------------------------*/
/*************精确延时函数**************** */
// 数据表如下
/*
********************************************************************************************************************
延时时间 a的值 b的值 c的值 延时误差(us)
10us 1 1 1 -0.5
20us 1 1 8 0
30us 1 1 15 +0.5
40us 2 1 9 0
50us 1 1 28 0
60us 1 1 35 +0.5
70us 1 1 42 +1
80us 1 1 48 0
90us 1 1 55 +0.5
100us 1 1 61 -0.5
200us 1 1 128 0
300us 3 1 63 +1.5
400us 2 1 129 0
500us 5 1 63 +0.5
600us 6 1 63 0
700us 7 1 63 -0.5
800us 1 3 175 +0.5
900us 9 1 63 -1.5
1ms 1 3 219 -1.5
2ms 2 3 220 +3
3ms 3 3 220 +3
Xms X 3 220 +3
(X的范围为2到255)
*/
void Delay(unsigned char a1,b1,c1)
{
unsigned char a,b,c;
for(a=0;a<a1;a++)
for(b=0;b<b1;b++)
for(c=0;c<c1;c++);
}
/*****************DS18B20******************/
void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
{
DQ = 1; //DQ复位,不要也可行。
Delay(1,1,1); //稍做延时 10us
DQ = 0; //单片机拉低总线
Delay(6,1,63); //600 us //精确延时,维持至少480us
//Delay(1,1,15); //20us
DQ = 1; //释放总线,即拉高了总线
Delay(5,1,63); //500us //此处延时有足够,确保能让DS18B20发出存在脉冲。
}
uchar Read_One_Byte() //读取一个字节的数据read a byte date
//读数据时,数据以字节的最低有效位先从总线移出
{
uchar i = 0;
uchar dat = 0;
for(i=8;i>0;i--)
{
DQ = 0; //将总线拉低,要在1us之后释放总线
//单片机要在此下降沿后的15us内读数据才会有效。
_nop_(); //至少维持了1us,表示读时序开始
dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。
DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上
Delay(1,1,1); //延时10us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
if(DQ) //控制器进行采样
{
dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0
}
Delay(1,1,8); //20us //此延时不能少,确保读时序的长度60us。
}
return (dat);
}
void Write_One_Byte(uchar dat)
{
uchar i = 0;
for(i=8;i>0;i--)
{
DQ = 0; //拉低总线
_nop_(); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
DQ = dat&0x01; //从字节的最低位开始传输
//指令dat的最低位赋予给总线,必须在拉低总线后的15us内,
//因为15us后DS18B20会对总线采样。
Delay(1,1,15); //必须让写时序持续至少60us
DQ = 1; //写完后,必须释放总线,
dat >>= 1;
Delay(1,1,1);
}
}
void Get_Tmp_dispaly() //获取温度get the wenduerature
{
uchar A1,A2,A3;
float tt;
uchar a,b;
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0x44); //温度转换指令
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0xbe); //读暂存器指令
a = Read_One_Byte(); //读取到的第一个字节为温度LSB
b = Read_One_Byte(); //读取到的第一个字节为温度MSB
wendu = b; //先把高八位有效数据赋于wendu
wendu <<= 8; //把以上8位数据从wendu低八位移到高八位
wendu = wendu|a; //两字节合成一个整型变量
tt = wendu*0.0625; //得到真实十进制温度值
//因为DS18B20可以精确到0.0625度
//所以读回数据的最低位代表的是0.0625度
wendu = tt*10+0.5; //放大十倍
//这样做的目的将小数点后第一位也转换为可显示数字
//同时进行一个四舍五入操作。
A1 = wendu/100; //百位
A2 = wendu%100/10; //十位
A3 = wendu%10; //个位
LCD_write_shu(6,2,A1); //得到十位数
LCD_write_shu(7,2,A2 ); //得到个位数
LCD_write_shu(9,2,A3); //得到个位数
}
void main()
{
unsigned char k,i;
res=0;
for(k=0;k<250;k++);
res=1;
LCD_init(); //初始化LCD模块
LCD_clear(); //清屏幕
LCD_write_shu(8,2,12); //点
LCD_write_shu(10,2,10);//ling
LCD_write_shu(11,2,11); //C
//LCD_write_shu(5,0,13);
// LCD_write_zi(1,0,0); //温
//LCD_write_zi(3,0,1); //度
LCD_write_zi(1,2,0); //wen
LCD_write_zi(3,2,3);//度
//LCD_write_shu(5,2,13);
//LCD_write_zi(1,4,4); //guang
//LCD_write_zi(3,4,5); //qiang
LCD_write_shu(5,2,13); //强冒
while(1)
{
Get_Tmp_dispaly();
}
}