电路原理图如下:
采用11.0592Mhz晶振,stc89c52芯片实时LCD602实时显示DS18B20温度值.
主程序
#include"ds18b20.h"
#include"lcd1602.h"
void main()
{
uint i;
uchar L,M;
uchar display[3];
ds_init();
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x4e);//写暂存器指令
write_byte(0x7f);
write_byte(0xf7);
write_byte(0x7f);//配置工作在12位模式下
ds_init(); //初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x48);//写入EEPROM
LCD_init(); //lcd初始化
while(1)
{
ds_init(); //初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x44);//发送温度转换指令
Delay_Ms(1);
ds_init(); //初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0xbe);//读取DS18B20暂存器值
L = read_byte(); //L
M = read_byte(); //H
i = M;
i <<= 8;
i |= L;
i = i * 0.0625 * 10 + 0.5;
display[0]=(uint)i/100;
display[1]=(uint)i%100/10;
display[2]=(uint)i%10;
Write_Cmd(0x80|0x00);
Write_Dat(display[0]+0x30);
Write_Cmd(0x80|0x01);
Write_Dat(display[1]+0x30);
Write_Cmd(0x80|0x02);
Write_Dat('.');
Write_Cmd(0x80|0x03);
Write_Dat(display[2]+0x30);
//Delay_Ms(20);
}
}
DS18B20.h文件
#ifndef _ds18b20_h_
#define _ds18b20_h_
#include"reg52.h"
#include"intrins.h"
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
//#define uchar unsigned char //定义无符号字符型变量
//#define uint unsigned int //定义无符号整型变量
typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned int INT16U;
typedef unsigned int uint;
/*硬件接口位声明*/
sbit DS = P2^2; //DS18B20单总线
/*描述:12T 51单片机自适应主时钟毫秒级延时函数*/
void Delay_Ms(INT16U ms);
/*单总线初始化时序*/
bit ds_init();
/*写一个字节*/
void write_byte(uchar dat);
/*读一个字节*/
uchar read_byte();
/*us延时函数,执行一次US--所需6.5us进入一次函数需要11.95us*/
void Delay_us(uchar us);
void Delay_5us();
#endif
DS18B20.c文件
#include"ds18b20.h"
void Delay_Ms(INT16U ms)
{
INT16U i;
do{
i = MAIN_Fosc; // 96000
while(--i); //96T per loop
}while(--ms); //
}
/*单总线初始化时序*/
bit ds_init()
{
bit i;
DS = 1;
_nop_();//
DS = 0;
Delay_us(75); //拉低总线75*6.5+11.95=499.45us 挂接在总线上的18B20将会全部被复位
DS = 1; //释放总线
Delay_us(4); //4*6.5+11.95=37.95us 等待50.95us
i = DS;
Delay_us(20); //20*6.5+11.95=141.95us 读取存在信号
DS = 1; //释放总线
_nop_();//
return (i);
}
/*写一个字节*/
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生些时序
DS = dat & 0x01;
Delay_us(10);//10*6.5+11.95=76.95us
DS = 1; //释放总线准备下一次数据写入
_nop_();
dat >>= 1;
}
}
/*读一个字节*/
uchar read_byte()
{
uchar i, j, dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生读时序
DS = 1;
_nop_();//释放总线
j = DS;
Delay_us(10);//6.5*10+11.95=76.95us
DS = 1;
_nop_();
dat = (j<<7)|(dat>>1);
}
return (dat);
}
/*us延时函数,执行一次US--所需6.5us.进入和出去一次函数需要11.95us*/
void Delay_us(uchar us)
{
/*****************11us延时函数*************************/
while(us--);
}
/*12T 51单片机5微秒延时函数自适应时钟(11.0592M,12M,22.1184M*/
void Delay_5us()
{
#if MAIN_Fosc == 11059200
_nop_();
#elif MAIN_Fosc == 12000000
_nop_();
#elif MAIN_Fosc == 22118400
_nop_(); _nop_(); _nop_();
#endif
}
LCD1602.c文件
#include<lcd1602.h>
#include<reg52.h>
sbit RS = P3^5;
sbit RW = P3^6;
sbit EN = P3^4;
//#define uchar unsigned char
//#define uint unsigned int
//判断液晶忙,如果忙则等待
/*void Read_Busy()
{
uchar busy;
P0=0xff; //p0置1
RS=0; //数据,命令选择端为0,表示数据
RW=1; //写
do
{
EN=1;
busy=P0;
EN=0;
}
while(busy&0x80); //最高位为1,则为忙。
} */
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=112;y>0;y--);
}
//写LCD1602命令一个字节
void Write_Cmd(uchar cmd)
{
RS = 0;
RW = 0;
P0 = cmd;
EN = 1;
EN = 0;
delay(5);
}
//写一个字节数据,一个字符uchar类型
void Write_Dat(uchar dat)
{
RS = 1;
RW = 0;
P0 = dat;
EN = 1;
EN = 0;
}
//lcd1602初始化
void LCD_init()
{
delay(15);
Write_Cmd(0x38);//第一步:显示模式设置。设置16*2显示 0011 100
delay(15);
Write_Cmd(0x38);//第一步:显示模式设置。设置16*2显示 0011 100
delay(15);
Write_Cmd(0x38);//第一步:显示模式设置。设置16*2显示 0011 100
delay(15);
Write_Cmd(0x38);//第一步:显示模式设置。设置16*2显示 0011 100
Write_Cmd(0x08);
//Write_Cmd(0x0f);//第二步:显示开/关光标设置 0000 1 D C B D=1:开显示 C=1:显示光标反之。B=1:光标闪烁B=0;光标不闪烁
Write_Cmd(0x01);//第三步:清屏指令 ,以免之前残留在LCD上的数据
Write_Cmd(0x06);//第四步:0000 01NS 。N=1;地址指针加1,光标加1.地址指针移位命令,读或写一个字符后,地址指针加1,且光标加1
Write_Cmd(0x0f);//显示开及光标设置
}
//x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行) *str:需要显示的字符串
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
{
if(y)
x |= 0x40;
x |= 0x80;
Write_Cmd(x);
while(*str != '\0')
{
Write_Dat(*str++);
}
}
//x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行) dat:需要显示的数据以ASCLL形式显示
void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat)
{
if(y)
x |= 0x40;
x |= 0x80;
Write_Cmd(x);
Write_Dat(dat);
}
#ifndef _LCD_H_
#define _LCD_H_
LCD1602.h文件
#include"reg52."
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
//uchar x,y,*str,dat,cmd;
void Read_Busy(); //判断液晶忙?
void delay(uint z);
void Write_Cmd(uchar cmd); //写入一字节指令
void Write_Dat(uchar dat); //写入一字节数据
void LCD_init(); //lcd初始化
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str); //显示字符串
void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat); //显示一个字符
#endif //定义结束
|