标题:
W014-多功能数字温度表(DS18B20)单片机程序
[打印本页]
作者:
siyiren1
时间:
2018-11-30 09:56
标题:
W014-多功能数字温度表(DS18B20)单片机程序
温度仪表资料
单片机源程序如下:
/*******************************************************************************
* 实验名称: 多功能数字温度表(DS18B20) *
********************************************************************************
* 实验描述: 多功能数字温度表具有测温、预设温度上下限、声光报警等功能 * *
* 实验说明: 各功能键如下: *
* S1 温度上下限设置及确认键 *
* S2 温度上(下)限加1键 *
* S3 温度上(下)限减1键 *
* BELL 声音报警 *
* D04 光报警 *
* *
* 温度上下限设置过程: *
* (1)按S1进入温度上限设置界面,然后按S2或S3设置温度上限值, *
* 最后按S1确认,自动进入温度下限设置界面。 *
* (2)按S2或S3设置温度下限值,按S1确认,自动进入温度测量状态 *
* *
* 当温度超过上下限时,会发出声光报警,并显示相关信息 *
*******************************************************************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P3^7 ; //定义DS18B20端口DQ
sbit BEEP = P1^4 ; //定义蜂鸣器端口
sbit RED_Light = P1^3 ; //报警灯
sbit LCD_RS = P2^3;
sbit LCD_RW = P2^4;
sbit HC138_A = P2^5;
sbit HC138_B = P2^6;
sbit HC138_C = P2^7;
#define SELECT_LCD() HC138_A=0; HC138_B=1; HC138_C=0
#define NOSELECT_LCD() HC138_A=1; HC138_B=1; HC138_C=1
sbit S1 = P1^5 ; //设置键和确认键
sbit S2 = P1^6 ; //加1键
sbit S3 = P1^7 ; //减1键
bit presence ;
uchar TH=30; //初始温度上限值
uchar TL=25; //初始温度下限值
uchar Keyset_Flag = 0; //S1键扫描标志位
uchar BEEP_Flag = 0; //蜂鸣器报警标志位
uchar code dis_code1[ ] = {" DS18B20 OK "} ;
uchar code dis_code2[ ] = {" TEMP: . C "} ;
uchar code dis_code3[ ] = {" DS18B20 ERR0R "} ;
uchar code dis_code4[ ] = {" PLEASE CHECK "} ;
uchar data temp_data[2] = {0x00,0x00} ; //温度数据缓存
uchar data display_TH[2] = {0x00,0x00} ; //温度上限值十位个位
uchar data display_TL[2] = {0x00,0x00} ; //温度下限值十位个位
uchar data dis_data[5] = {0x00,0x00,0x00,0x00,0x00} ; //温度值百十个小数位及一个数据缓存
/*温度小数部分查表*/
uchar code ditab[16] = {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09} ;
/*自定义字符*/
uchar code mytab[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00} ; //度的符号
/*******************************************************************/
/* */
/* us级延时函数 */
/* */
/*******************************************************************/
void Delay(unsigned int num)
{
while( --num ) ;
}
/*******************************************************************/
/* */
/* ms级延时函数 */
/* */
/*******************************************************************/
void Delayms(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
/*******************************************************************/
/* */
/* 检测LCD的忙碌状态 */
/* */
/*******************************************************************/
bit LCD_Busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
SELECT_LCD();
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0 & 0x80); //检查LCD的DB7的值 1为忙 0为空闲,可写指令与数据
NOSELECT_LCD();
return result;
}
/*******************************************************************/
/* */
/* 写指令数据到LCD */
/* */
/*******************************************************************/
LCD_WriteCommand(uchar cmd)
{
while(LCD_Busy());
LCD_RS = 0;
LCD_RW = 0;
NOSELECT_LCD();
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
SELECT_LCD();
_nop_();
_nop_();
_nop_();
_nop_();
NOSELECT_LCD();
}
/*******************************************************************/
/* */
/* 写显示数据到LCD */
/* */
/*******************************************************************/
LCD_WriteDate(uchar dat)
{
while(LCD_Busy());
LCD_RS = 1;
LCD_RW = 0;
NOSELECT_LCD();
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
SELECT_LCD();
_nop_();
_nop_();
_nop_();
_nop_();
NOSELECT_LCD();
}
/*******************************************************************/
/* */
/* 设定字符在LCD上显示的位置 */
/* */
/*******************************************************************/
LCD_DisplayPosit(uchar pos)
{
LCD_WriteCommand(pos | 0x80);
}
/*******************************************************************/
/* */
/* LCD初始化 */
/* */
/*******************************************************************/
LCD_Init()
{
LCD_WriteCommand(0x38);
Delay(5);
LCD_WriteCommand(0x0c);
Delay(5);
LCD_WriteCommand(0x06);
Delay(5);
LCD_WriteCommand(0x01);
Delay(5);
}
/*******************************************************************/
/* */
/* 自定义字符写入CGRAM函数 */
/* */
/*******************************************************************/
void LCD_WriteMytab()
{
unsigned char i ;
LCD_WriteCommand(0x40) ; //写CGRAM
for (i = 0 ; i< 8 ; i++)
LCD_WriteDate(mytab[ i ]) ;
}
/*******************************************************************/
/* */
/* LCD上显示两行字符函数 */
/* */
/*******************************************************************/
void LCD_DisplayLine(uchar a[ ],uchar b[ ])
{
uchar m ;
LCD_Init() ;
LCD_DisplayPosit(0) ; //设置显示位置为第一行的第1个字符
m = 0 ;
while(a[m] != '\0')
{ //显示第一行字符
LCD_WriteDate(a[m]) ;
m++ ;
}
LCD_DisplayPosit(0x40) ; //设置显示位置为第二行第1个字符
m = 0 ;
while(b[m] != '\0')
{
LCD_WriteDate(b[m]) ; //显示第二行字符
m++ ;
}
}
/*******************************************************************/
/* */
/* DS18B20初始化 */
/* */
/*******************************************************************/
DS18B20_Init(void)
{
DQ = 1 ; //DQ复位
Delay(8) ; //延时
DQ = 0 ; //将DQ拉低
Delay(90) ; //精确延时 大于 480us
DQ = 1 ; //拉高总线
Delay(8) ;
presence = DQ ; //如果 presence=0则初始化成功 presence=1则初始化失败
Delay(100) ;
DQ = 1 ;
return(presence) ; //返回presence
}
/*******************************************************************/
/* */
/* 读一个字节数据 */
/* */
/*******************************************************************/
ReadOneChar(void)
{
unsigned char i = 0 ;
unsigned char dat = 0 ;
for (i = 8 ; i > 0 ; i--)
{
DQ = 0 ;
dat >>= 1 ;
DQ = 1 ;
if(DQ)
dat |= 0x80 ;
Delay(4) ;
}
return (dat) ;
}
/*******************************************************************/
/* */
/* 写一个字节数据 */
/* */
/*******************************************************************/
WriteOneChar(unsigned char dat)
{
unsigned char i = 0 ;
for (i = 8 ; i > 0 ; i--)
{
DQ = 0 ;
DQ = dat&0x01 ;
Delay(5) ;
DQ = 1 ;
dat>>=1 ;
}
}
/*******************************************************************/
/* */
/* 读取温度数据 */
/* */
/*******************************************************************/
ReadTemperature(void)
{
DS18B20_Init() ;
WriteOneChar(0xCC) ; //跳过读序号列号的操作
WriteOneChar(0x44) ; //启动温度转换
DS18B20_Init() ;
WriteOneChar(0xCC) ; //跳过读序号列号的操作
WriteOneChar(0xBE) ; //读取温度寄存器
temp_data[0] = ReadOneChar() ; //读温度低8位
temp_data[1] = ReadOneChar() ; //读温度高8位
}
/*******************************************************************/
/* */
/* 温度数据转换和显示 */
/* */
/*******************************************************************/
TemperatureDisplay()
{
dis_data[4]=temp_data[0]&0x0f ; //temp_data[0]低4为有效
dis_data[3]=ditab[dis_data[4]]+0x30; //查表得小数位的值
dis_data[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);
dis_data[2]=dis_data[4]%10+0x30; //个位
dis_data[1]=(dis_data[4]/10)%10+0x30; //十位
dis_data[0]=dis_data[4]/100+0x30; //百位
if(dis_data[0]==0x30) //百位为0,不显示
{
dis_data[0]=0x20;
if(dis_data[1]==0x30) //十位为0,不显示
dis_data[1]=0x20 ;
}
LCD_DisplayPosit(0x48) ;
LCD_WriteDate(dis_data[0]) ; //百位数显示
LCD_DisplayPosit(0x49) ;
LCD_WriteDate(dis_data[1]) ; //十位数显示
LCD_DisplayPosit(0x4a) ;
LCD_WriteDate(dis_data[2]) ; //个位数显示
LCD_DisplayPosit(0x4c) ;
LCD_WriteDate(dis_data[3]) ; //小数位数显示
LCD_WriteMytab() ; //自定义字符(度的符号)写入CGRAM
Delay(5) ;
LCD_DisplayPosit(0x4d) ;
LCD_WriteDate(0x00) ; //显示自定义字符(度的符号)
}
/*******************************************************************/
/* */
/* DS18B20 OK 界面显示 */
/* */
/*******************************************************************/
void DS18B20_OkMenu ()
{
LCD_DisplayLine(dis_code1,dis_code2);
}
/*******************************************************************/
/* */
/* DS18B20 ERROR 界面显示 */
/* */
/*******************************************************************/
void DS18B20_ErrorMenu ()
{
LCD_DisplayLine(dis_code3,dis_code4);
}
/*******************************************************************/
/* */
/* 蜂鸣器响一声 */
/* */
/*******************************************************************/
void Beep()
{
unsigned char y ;
for (y=0 ;y<100 ;y++)
{
Delay(60) ;
BEEP=!BEEP ; //BEEP取反
}
BEEP=1 ; //关闭蜂鸣器
Delayms(20) ;
}
/*******************************************************************/
/* */
/* 温度高于上限时显示 */
/* */
/*******************************************************************/
void DisplayTHMenu()
{
uchar code dis_code5[ ] = {" TEMP>TH C "} ;
uchar code dis_code6[ ] = {" TEMP: . C "} ;
LCD_DisplayLine(dis_code5,dis_code6);
LCD_WriteMytab() ; //自定义字符写入CGRAM
Delay(5) ; //显示自定义字符
LCD_DisplayPosit(0x0D) ;
LCD_WriteDate(0x00) ;
Delay(5) ;
LCD_DisplayPosit(0x4d) ;
LCD_WriteDate(0x00) ;
display_TH[0] = TH/10+0x30;
display_TH[1] = TH%10+0x30;
LCD_DisplayPosit(0x0B) ;
LCD_WriteDate(display_TH[0]) ;
LCD_DisplayPosit(0x0C) ;
LCD_WriteDate(display_TH[1]) ;
}
/*******************************************************************/
/* */
/* 温度低于下限时显示 */
/* */
/*******************************************************************/
void DisplayTLMenu()
{
uchar code dis_code5[ ] = {" TEMP<TL C "} ;
uchar code dis_code6[ ] = {" TEMP: . C "} ;
LCD_DisplayLine(dis_code5,dis_code6);
LCD_WriteMytab() ; //自定义字符写入CGRAM
Delay(5) ; //显示自定义字符
LCD_DisplayPosit(0x0D) ;
LCD_WriteDate(0x00) ;
Delay(5) ;
LCD_DisplayPosit(0x4d) ;
LCD_WriteDate(0x00) ;
display_TL[0] = TL/10+0x30;
display_TL[1] = TL%10+0x30;
LCD_DisplayPosit(0x0B) ;
LCD_WriteDate(display_TL[0]) ;
LCD_DisplayPosit(0x0C) ;
LCD_WriteDate(display_TL[1]) ;
}
/*******************************************************************/
/* */
/* 扫描设置键 */
/* */
/*******************************************************************/
void SetKeyScan()
{
if(S1==0)
{
Delay(1000);
if(S1==0)
{
Keyset_Flag = 1;
Delay(200);
}
}
}
/*******************************************************************/
/* */
/* 扫描处理键 */
/* */
/*******************************************************************/
unsigned char KeyworthScan()
{
unsigned char key_s;
key_s = 0x00;
key_s |= S1;
key_s <<= 1;
key_s |= S2;
key_s <<= 1;
key_s |= S3;
return key_s;
}
/*******************************************************************/
/* */
/* 温度上限设置界面上限值显示 */
/* */
/*******************************************************************/
void DisplayTH()
{
display_TH[0] = TH/10+0x30;
display_TH[1] = TH%10+0x30;
LCD_DisplayPosit(0x4b) ;
LCD_WriteDate(display_TH[0]) ;
LCD_DisplayPosit(0x4c) ;
LCD_WriteDate(display_TH[1]) ;
}
/*******************************************************************/
/* */
/* 温度上限设置界面显示 */
/* */
/*******************************************************************/
void SetTHMenu()
{
uchar code dis_code5[ ] = {" SET THE TH ? "} ;
uchar code dis_code6[ ] = {" NOW TH = C "} ;
LCD_DisplayLine(dis_code5,dis_code6);
LCD_WriteMytab() ;
Delay(10) ;
LCD_DisplayPosit(0x4d) ;
LCD_WriteDate(0x00) ;
}
/*******************************************************************/
/* */
/* 温度上限值设置时显示 */
/* */
/*******************************************************************/
void SetTH()
{
uchar key_v = 0x07;
uchar a = 1;
SetTHMenu();
DisplayTH();
while(a==1)
{
uchar key;
key = KeyworthScan();
if(key!=key_v)
{
Delayms(10);
key = KeyworthScan();
DisplayTH();
if(key!=key_v)
{
key_v = key;
if(key_v==0x05)
{
TH++;
if(TH>99)TH=99;
Keyset_Flag = 2;
}
else if(key_v==0x06)
{
TH--;
if(TH<0)TH=0;
Keyset_Flag = 2;
}
else if(key_v==0x03&&Keyset_Flag == 2)
{
a = 0;
}
}
}
}
}
/*******************************************************************/
/* */
/* 温度下限设置界面显示 */
/* */
/*******************************************************************/
void SetTLMenu()
{
uchar code dis_code5[ ] = {" SET THE TL ? "} ;
uchar code dis_code6[ ] = {" NOW TL = C "} ;
LCD_DisplayLine(dis_code5,dis_code6);
LCD_WriteMytab() ;
Delay(10) ;
LCD_DisplayPosit(0x4d) ;
LCD_WriteDate(0x00) ;
}
/*******************************************************************/
/* */
/* 温度下限设置界面下限值显示 */
/* */
/*******************************************************************/
void DisplayTL()
{
display_TL[0] = TL/10+0x30;
display_TL[1] = TL%10+0x30;
LCD_DisplayPosit(0x4b) ;
LCD_WriteDate(display_TL[0]) ;
LCD_DisplayPosit(0x4c) ;
LCD_WriteDate(display_TL[1]) ;
}
/*******************************************************************/
/* */
/* 温度下限值设置时显示 */
/* */
/*******************************************************************/
void SetTL()
{
uchar key_v = 0x07;
uchar a=1;
SetTLMenu();
DisplayTL();
while(a==1)
{
uchar key_s;
key_s = KeyworthScan();
if(key_s!=key_v)
{
Delayms(10);
key_s = KeyworthScan();
DisplayTL();
if(key_s!=key_v)
{
key_v = key_s;
if(key_v==0x05)
{
TL++;
if(TL>99)TL=99;
Keyset_Flag = 3;
}
else if(key_v==0x06)
{
TL--;
if(TL<0)TL=0;
Keyset_Flag = 3;
}
else if(key_v==0x03&&Keyset_Flag == 3)
{
a=0;
}
}
}
}
}
/*******************************************************************/
/* */
/* 温度上下限设置 */
/* */
/*******************************************************************/
void SetTH_TL()
{
SetTH();
Delay(100);
SetTL();
Keyset_Flag=0;
DS18B20_OkMenu();
}
/*******************************************************************/
/* */
/* 主函数 */
/* */
/*******************************************************************/
void main()
{
do
{
if((presence==0)&&(dis_data[4]<TH)&&(dis_data[4]>=TL)) //温度正常
{
DS18B20_OkMenu() ;
while((dis_data[4]<TH)&&(dis_data[4]>=TL))
{
ReadTemperature() ;
TemperatureDisplay() ;
BEEP_Flag=0;
RED_Light=1;
SetKeyScan();
if(Keyset_Flag==1)
{
SetTH_TL();
Delayms(500);
}
}
}
if((presence==0)&&(dis_data[4]>=TH)) //温度高于上限
{
DisplayTHMenu();
while(dis_data[4]>=TH)
{
ReadTemperature() ;
TemperatureDisplay() ;
if(BEEP_Flag==0)Beep();
BEEP_Flag=1;
RED_Light=0;
SetKeyScan();
if(Keyset_Flag==1)
{
SetTH_TL();
Delayms(500);
}
}
}
if((presence==0)&&(dis_data[4]<TL)) //温度低于下限
{
DisplayTLMenu();
while(dis_data[4]<TL)
{
ReadTemperature() ;
TemperatureDisplay() ;
if(BEEP_Flag==0)Beep();
BEEP_Flag=1;
RED_Light=0;
SetKeyScan();
if(Keyset_Flag==1)
{
SetTH_TL();
Delayms(500);
}
}
}
}
while(!presence);
DS18B20_ErrorMenu() ; //未检测到DS18B20
do
{
DS18B20_Init() ;
if(BEEP_Flag==0)Beep();
BEEP_Flag=1;
}
while(presence);
}
/*******************************************************************/
复制代码
所有资料51hei提供下载:
多功能数字温度表.rar
(35.25 KB, 下载次数: 17)
2018-11-30 09:56 上传
点击文件名下载附件
多功能数字温度表
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1