标题:
单片机LCD1602温度计实验 Proteus仿真加源程序
[打印本页]
作者:
51黑电子happy
时间:
2017-3-30 01:35
标题:
单片机LCD1602温度计实验 Proteus仿真加源程序
51单片机LCD1602液晶显示的温度计的仿真原理图(proteus工程文件可到本帖附件下载):
0.png
(21.67 KB, 下载次数: 86)
下载附件
2017-3-30 01:32 上传
单片机源程序:
//--------------------------------------------------------------------------------------------
//程序名: LCD_TEMP09-1.c
//程序功能:LCD温度计
//--------------------------------------------------------------------------------------------
#include <reg51.h>
#include<intrins.h> //包含_nop_()函数定义的头文件
sbit RS=P2^5; // 引脚定义
sbit RW=P2^6;
sbit EN=P2^7;
sbit busy=P0^7; // "忙"标志位
#define LCD P0 //命令或数据线
sbit DQ=P2^0;
//代码表
unsigned char code TAB1[]={ 0x0c,0x12,0x12,0x0c,
0x00,0x00,0x00,0x00,
};
//字符表
unsigned char code TAB2[]={"DS18B20 OK"};
unsigned char code Error[]={"Error!Check!"}; //说明没有检测到DS18B20
unsigned char code digit[10]={"0123456789"}; //定义字符数组显示数字
unsigned char code TEMP[]={"TEMP:"}; //说明显示的是温度
unsigned char fuhao;
//------------------------------------ 延时函数 -------------------------------------------
void delay(unsigned int t) //延时若干微秒
{
while(t--);
}
//---------------------------------- 判断液晶显示器是否忙函数 ----------------------------------
CHECK_BF() //判断是否忙碌
{
do
{
LCD=0xff;
RS=0; // RS=0,选择指令寄存器
RW=1; // RW=1,选择读模式
EN=0; // 执行显示命令
EN=1; // 允许读/写
}
while(busy); //busy为高电平表示忙,循环等待
}
//-------------------------------------- 写命令函数 -----------------------------------
WR_COMM() //写命令
{
RS=0; // RS=0,选择指令寄存器
RW=0; // RW=0,选择写模式
EN=0; // 执行显示命令
CHECK_BF(); // 等待
EN=1; // E=1,允许读/写LCD
}
//-------------------------------------- 写数据函数 -------------------------------------
WR_DATA() //写数据
{
RS=1; // RS=1,选择数据寄存器
RW=0; //准备写入数据
EN=0; //执行显示命令
CHECK_BF(); //判断液晶模块是否忙
EN=1; // E=1,允许读/写LCD
}
//--------------------------------------- 初始化函数 ----------------------------------
INIT_LCD() //初始化
{
unsigned char i=200;
{
while(--i);
LCD=0x01; //清屏并光标复位
WR_COMM(); //写入命令
LCD=0x38; //设置显示模式:8位2行5x7点阵
WR_COMM();
LCD=0x0c; //开显示屏
WR_COMM();
LCD=0x06; //文字不动,光标自动右移
WR_COMM(); //写入命令
}
}
//-------------------------------- 显示温度标记字符C函数 ----------------------------
TEMP_BJ() //显示字符C
{
LCD=0xce; //写入显示起始地址
WR_COMM(); //写入命令
LCD=('C' );
WR_DATA(); //送出
}
//----------------------------------- 自定义温度标志符函数 --------------------------------
STORE_DATA()
{
unsigned char i;
LCD=0x40; // 指定CG RAM起始地址
WR_COMM(); //写入命令
for(i=0;i<9;i++)
{
LCD=TAB1[i]; //提取字符
WR_DATA(); //送出
}
LCD=0xcd; //写入显示起始地址
WR_COMM(); //写入命令
LCD=0x00; //CGRAM内第0号图形
WR_DATA(); //写入数据
TEMP_BJ();
}
//------------------------------------------- DS18B20初始化函数 --------------------------------------
bit INIT_1820(void)
{
bit flag; //flag为标志符
DQ = 1; //DQ复位
delay(3); //稍作延时
DQ = 0; //将数据线从高拉低,保持480~960us
delay(80);
DQ = 1; //释放数据线
delay(10);
flag=DQ; //DQ=0表示存在
delay(25);
return (flag); //返回检测标志
}
//------------------------------------------ 读出DS18B20函数 ----------------------------------------
unsigned char READ_1820(void)
{
unsigned char i=0;
unsigned char dat; //储存读出的一个字节数据
for (i=0;i<8;i++)
{
DQ =1; //将数据线拉高
DQ = 0; //将数据线从高拉低,启动读时序
dat>>=1;
DQ = 1; //将数据线拉高,为输出电平作准备
_nop_();
if(DQ==1)
dat|=0x80; //读数据,存入dat
else
dat|=0x00; //读数据,存入dat
delay(3);
}
return(dat); //返回读出的十进制数据
}
//--------------------------------------------- 写入DS18B20函数 ---------------------------------------------
WRITE_1820(unsigned char dat)
{
unsigned char i=0;
for (i=0; i<8; i++)
{
DQ =1; // 先将数据线拉高
DQ=0; //数据线从高拉低,开始写入
DQ=dat&0x01; //利用与运算取出要写的某位二进制数据,
delay(3);
DQ=1; //释放数据线
_nop_();
dat>>=1; //将dat中的各二进制位数据右移1位
}
delay(3);
}
//---------------------------------------- 显示错误信息函数 ------------------------------------------
void DISP_ERR(void)
{
unsigned char i;
LCD=0x80; //写显示地在第1行第1列
WR_COMM();
i = 0; //从第一个字符开始显示
while(Error[i] != '\0') //写到结束标志
{
LCD=(Error[i]); //将字符常量写入LCD
WR_DATA();
i++; //指向下一个字符
delay(1000); //延时
}
while(1); //循环,等待查明原因
}
//-------------------------------------- 显示温度的小数点 ------------------------------------------
void DISP_D(void)
{
LCD=0xc9; //写显示地址在第2行第10列
WR_COMM();
LCD=('.');
WR_DATA();
delay(200); //延时一点时间
}
//------------------------------------------ 显示TEMP字符函数 ------------------------------------------------
void DISP_TEMP(void)
{
unsigned char i;
LCD=0xc0; //写入显示起始地址
WR_COMM(); //写入命令
for(i=0;i<5;i++)
{
LCD=TEMP[i]; //提取字符
WR_DATA(); //送出
}
}
//------------------------------------------- 显示菜单函数 --------------------------------------------
DISP_EXP( )
{
unsigned char i;
LCD=0x83; //写入显示起始地址
WR_COMM(); //写入命令
for(i=0;i<11;i++)
{
LCD=TAB2[i]; //提取字符
WR_DATA(); //送出
}
DISP_TEMP();
DISP_D();
}
//---------------------------------------------- 读温度函数 -----------------------------------------
RE_TEMP()
{
unsigned char time;
INIT_1820(); //将DS18B20初始化
WRITE_1820(0xCC); // 跳过读序号列号的操作
WRITE_1820(0x44); // 启动温度转换
for(time=0;time<100;time++);
INIT_1820(); //将DS18B20初始化
WRITE_1820(0xCC); //跳过读序号列号的操作
WRITE_1820(0xBE); //读取温度的低位和高位
}
//------------------------------------------ 显示温度正负的符号 ---------------------------------------
void DISP_ZF(unsigned char fuhao)
{
unsigned char show;
show=fuhao;
LCD=0xc5; //写显示地址在第2行第10列
WR_COMM();
LCD=(show); //将小数点的字符常量写入LCD
WR_DATA();
delay(200); //延时一点时间
}
//---------------------------------------- 显示温度的整数部分函数 ----------------------------------------
void DISP_TEMP1(unsigned char x)
{
unsigned char j,k,l; //j,k,l分别储存温度的百位、十位和个位
j=x/100; //取百位
k=(x%100)/10; //取十位
l=x%10; //取个位
LCD=0xc6; //写显示地址在第2行第7列
WR_COMM();
LCD=(digit[j]);
WR_DATA();
LCD=0xc7;
WR_COMM();
LCD=(digit[k]);
WR_DATA();
LCD=0xc8;
WR_COMM();
LCD=(digit[l]);
WR_DATA();
delay(200); //延时一点时间
}
//---------------------------------------- 显示温度的小数数部分函数 -----------------------------------------
void DISP_TEMP2(unsigned char x)
{
LCD=0xca; //写显示地址在第2行第11列
WR_COMM();
LCD=(digit[x]);
WR_DATA(); //将小数部分写入LCD
delay(200); //延时一点时间
}
//---------------------------------------- 温度数据转换显示函数 -------------------------------------------
void CONV_TEMP(void)
{
unsigned char TL; //储存温度低位
unsigned char TH; //储存温度高位
unsigned char TN; //储存整数部分
unsigned char TD; //储存小数部分
while(1) //不断检测显示温度
{
RE_TEMP(); //读温度函数
//-------------------
TL=READ_1820(); //先读温度值低位
TH=READ_1820(); //接着读温度值高位
if(TH>=0xf8)
{
DISP_ZF('-');
if(TL==0)
{
TH=(~TH+1)&0x03;
TN=TH*16+TL/16;
TD=(TL%16)*10/16;
goto loopshow;
}
TH=~TH&0x03;
TL=~TL+1;
TN=TH*16+TL/16;
TD=(TL%16)*10/16;
goto loopshow;
}
DISP_ZF('+');
TN=TH*16+TL/16; //计算温度值整数部分
TD=(TL%16)*10/16; //计算温度的小数部分
loopshow:
//------------------------
DISP_TEMP1(TN); //显示温度的整数部分
DISP_TEMP2(TD); //显示温度的小数部分
delay(100);
}
}
//---------------------------------------- 主函数 ----------------------------------------------
void main(void)
{
INIT_LCD(); //LCD初始化函数
delay(100);
if(INIT_1820()==1) //DS18B20初始化函数
DISP_ERR(); //显示错误信息函数
STORE_DATA(); //自定义温度标志符函数
DISP_EXP(); //显示菜单函数
CONV_TEMP(); //温度数据转换显示函数
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
该系列源码包含有很多非常经典,代码风格十分规范,而且注释详细的单片机例程,还带仿真,对于MCU学习特别是初学者是很有帮助的,全部源码下载(共25个项目):
http://www.51hei.com/bbs/dpj-79328-1.html
本例程下载(含proteus仿真工程文件与源码):
单片机LCD1602温度计实验.rar
(76.76 KB, 下载次数: 289)
2017-3-30 01:35 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
科学小怪蛋
时间:
2017-3-30 12:42
可以。。
作者:
gentlezr
时间:
2017-6-6 19:24
请问在这个基础上怎么加报警器,并且可以手动设置温度上限呢
作者:
bobono1
时间:
2017-6-20 13:02
完美!
作者:
慚阜嵛
时间:
2017-12-5 10:44
好贴,很给力!
作者:
292217911
时间:
2017-12-12 01:05
刚好要用到,太有帮助了
作者:
欧阳云天
时间:
2018-5-30 21:54
新手看得云里雾里的
作者:
丶Cristiano
时间:
2018-10-28 23:54
很实用,谢谢楼主
作者:
sgly
时间:
2019-3-5 16:30
正需要这个,谢谢啦
作者:
casualV
时间:
2019-3-17 09:56
感谢分享
作者:
chenziyue1996
时间:
2019-3-17 12:01
感谢分享,多谢
作者:
czbbb
时间:
2019-6-10 15:04
感谢感谢
作者:
qwerfghnm
时间:
2019-6-19 09:15
怎么能在加个NRF24L01无线传输模块呢?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1