電路原理圖如下:
LCD602顯示DS18B20溫度值proteus仿真.PNG (73.07 KB, 下載次數: 82)
下載附件
2018-8-2 18:51 上傳
采用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 //定義結束
|