/*============================================================
运用1602液晶显现DS1302+S51时钟+温度显现 zhaojun 2007/06/29
==============================================================
声明:1. 1602驱动程序照搬 明皓 的,十分好用
2. DS1302驱动程序是参阅网友修正而来
NS1602R(16*2)模仿口线接线方法
衔接线图:
—————————————————
| LCM—–51 | LCM—–51 | LCM——51 |
| ———————————————– |
| DB0—–P0.0 | DB4—–P0.4 | RS——-P2.0 |
| DB1—–P0.1 | DB5—–P0.5 | RW——-P2.1 |
| DB2—–P0.2 | DB6—–P0.6 | E——–P2.2 |
| DB3—–P0.3 | DB7—–P0.7 | VLCD接1K电阻到GND |
—————————————————
DS1302 接线图
Vcc2 CLK I/O /RST
| | | |
—————
| 8 7 6 5 |
| DS1302 |
| |
| 1 2 3 4 |
—————
| | | |
VCC1 GND
1. 脚接+5V 2,3. 脚32768HZ晶振 4. 脚接地 5. 脚接S51的P1.2 6. 脚接S51的P1.1 7. 接S51的P1.0
8. 脚接后备电源,能够接老核算机主板上的3.6V电池,也能够经过二级管阻隔接一个大容量电解电容
电压在2.5V以上即可坚持
按键阐明:1. 共三个键,低电平有用
2. P1.4 和 P1.5 一起按:初始化
3. P1.6 端口按键:挑选要调整的项目
4. P1.5 端口按键:添加;P1.4端口按键:削减
[注:AT89S51运用12M晶振]
原理图:
源代码:
=================界说与声明=============================================================*/
#include “regx51.h”
#include “string.h”
#include “intrins.h”
#define uchar unsigned char
#define uint unsigned int
typedef unsigned char byte;
typedef unsigned int word;
//*********** 1602引脚界说引脚
#define LCM_RS P2_0 // 数据/指令挑选信号
#define LCM_RW P2_1 // 读/写挑选信号
#define LCM_E P2_2 // 使能信号
//*********** DS1302 时刻显现界说部分
sbit T_CLK=P1^0; //串行时钟输入
sbit T_IO =P1^1; //串行数据端口
sbit T_RST=P1^2; //复位端口
//*********** 18B20温度显现界说部分
sbit DQ=P3^3; //18B20 接P33口
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
#define LCM_Data P0 //显现数据端口
#define Busy 0x80 //用于检测LCM状况字中的Busy标识
uchar id,timecount; //全局变量
bit flag,sflag; //flag是时钟冒号闪耀标志,sflag是温度负号显现标志
bit sec,min,hour,year,mon,day,weekk; //闪耀标志位
//*********************函数声明
void Disp_line1(void); // 显现屏幕榜首行
void Disp_line2(void); // 显现屏幕第二行
void id_case1_key(); // id为1时的下一级挑选
void Set(uchar,uchar); // 依据挑选调整相应项目
void RTInputByte(uchar); /* 输入 1Byte */
uchar RTOutputByte(void); /* 输出 1Byte */
void W1302(uchar, uchar); // 向DS1302写入一个字节
uchar R1302(uchar); // 从DS1302读出一个字节
void Set1302(uchar * ); // 设置时刻
//******* 1602LCD驱动 **********************************************************
void WriteDataLCM(uchar WDLCM); //写数据
void WriteCommandLCM(uchar WCLCM,BuysC); //写指令
uchar ReadStatusLCM(void); //读状况
void LCMInit(void); //LCM初始化
void DisplayOneChar(uchar X, uchar Y, uchar DData); //按指定方位显现一个字符
void DisplayListChar(uchar X, uchar Y, uchar code *DData); //按指定方位显现一串字符
void Delay5Ms(void); //5ms延时
void Delay400Ms(void); //400ms延时
Read_Temperature(char,char);//温度显现
void mychar(void); //显现自界说字符
void adjust_res(char res); //res 别离等于 0x1f, 0x3f, 0x5f 温度读数分辨率别离对应
// 0.5, 0.25, 0.125
//初始化后设置为:07年07月04日 星期3 12点00分00秒
// 12:00:00 XX. C
// 07/07/04 Week.3
unsigned char inittime[7]={0x00,0x00,0x12,0x04,0x07,0x03,0x07};
// 秒 分钟 小时 日 月 星期 年
uchar code week[]={“Week.”};//星期显现
//========================= 主函数 =======================================================
/*****************************************************
函 数 名:main()
功 能:主函数
说 明:
进口参数:无
返 回 值:无
*****************************************************/
void main(void)
{
Delay400Ms(); //发动等候,等LCM讲入作业状况
LCMInit(); //LCM初始化
Delay5Ms(); //延时顷刻(可不要)
mychar(); //显现自界说字符
TMOD=0x01; //挑选守时方法
TH0=(65535-50000)/256;//取守时初值
TL0=(65535-50000)%256;
EA=1; //开中止
TR0=1;
ET0=1;
W1302(0x90,0xa5); //翻开充电二级管 一个二级管串联一个2K电阻
W1302(0x8e,0x80); //写保护,制止写操作
adjust_res(0x5f); //调整18B20的分辨率 0x1f:0.5; 0x3f:0.25; 0x5f:0.125
while(1)
{
if ((P1_4|P1_5)==0) // 初始化 一起按下P1_4、P1_5
{
Delay5Ms(); // 恰当延时,消除颤动
if ((P1_4|P1_5)==0) Set1302(inittime); // 显现初始值
}
if (P1_6==0) // 设置和挑选项目键
{
Delay5Ms(); // 恰当延时,消除颤动
if(P1_6==0){id++;if(id>7) id=0;} // 7个可调理项目循环调理
while(P1_6==0);
}
switch(id) // 跳转到对应的项目进行设置
{
case 0:
sec=0;
Disp_line1(); Disp_line2();
break;
case 1: //调理年
year=1;//设置年闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 2: //调理月
year=0;mon=1;//设置月闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 3: //调理日
mon=0;day=1;//设置日闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 4: //调理星期
day=0;weekk=1;//设置星期闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 5: //调理小时
weekk=0;hour=1;//设置小时闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 6: //调理分钟
hour=0;min=1;//设置分钟闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 7: //调理秒
min=0;sec=1;//设置秒钟闪耀标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
}
}
}
//================================== 守时中止 =============================================
/*****************************************************
函 数 名:void t0()
功 能:时刻作业时,冒号闪耀
说 明:T0中止进口,方法1
进口参数:无
返 回 值:无
*****************************************************/
void t0(void) interrupt 1 using 0
{
TH0=(65535-50000)/256; //取50ms守时初值
TL0=(65535-50000)%256;
timecount++;
if(timecount>9)
{
timecount=0; //计时到,从先开端
flag=~flag; //标志位取反
}
}
//==================================== 项目设置 ===========================================
/*****************************************************
函 数 名:void id_case1_key()
功 能:项目设置加减操控
说 明:P1.5和P1.4 <==> +和-
进口参数:无
返 回 值:无
*****************************************************/
//id为1时的下一级挑选
void id_case1_key()
{
if (P1_5==0) //P1_5有按下,则数值添加(+)
{
Delay5Ms(); //恰当延时,消除颤动
if(P1_5==0) Set(id,0); //依据挑选调整相应项目
if(id!=7) while(P1_5==0);
}
if (P1_4==0) //P1_4有按下,则数值削减(-)
{
Delay5Ms(); //恰当延时,消除颤动
if(P1_4==0) Set(id,1); //依据挑选调整相应项目
if(id!=7) while(P1_4==0);
}
}
/*****************************************************
函 数 名:void Set()
功 能:项目设置
说 明:sel_1=0时,数值加;sel_1=1时,数值减
进口参数:sel和sel_1
返 回 值:无
*****************************************************/
//依据挑选调整相应项目并写入DS1302
void Set(uchar sel,uchar sel_1)
{
signed char address,item;
signed char max,mini;
//偶数指令是写,奇数指令是读
//最大值与最小值约束
if(sel==7) {address=0x80; max=00;mini=0;} //秒
if(sel==6) {address=0x82; max=59;mini=0;} //分钟
if(sel==5) {address=0x84; max=23;mini=0;} //小时
if(sel==3) {address=0x86; max=31;mini=1;} //日
if(sel==2) {address=0x88; max=12;mini=1;} //月
if(sel==1) {address=0x8c; max=99;mini=0;} //年
if(sel==4) {address=0x8a; max=07;mini=1;} //星期
//先从1302中读出数据,把数据转化成十进制进行加减设置;后从先转化回来写入1302中
item=R1302(address+1)/16*10+R1302(address+1)%16;//从1302中读出1字节,再转化成十进制
if (sel_1==0) item++; else item–; //sel_1=0则加,sel_1=1则减
if(item>max) item=mini; //大于最大值,则赋最小值(循环)
if(item
W1302(0x8e,0x80); //写保护,制止写操作
}
//=======================================================================================
/*****************************************************
函 数 名:void Disp_line1()
功 能:显现时刻和温度 (XX:XX:XX XX.X C)
说 明:榜首行显现数据处理
进口参数:无
返 回 值:无
*****************************************************/
//屏幕显现榜首行: 时刻和温度显现
void Disp_line1(void)
{
Read_Temperature(10,0); //温度显现
//冒号闪耀
if(flag==0)
{DisplayOneChar(3,0,0x3a); DisplayOneChar(6,0,0x3a);}
else
{DisplayOneChar(3,0,0×20); DisplayOneChar(6,0,0×20);}
if(sec==1) //秒闪耀标志位
{
if(flag==1)
{
DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显现秒十位
DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显现秒个位
}
else
{
DisplayOneChar(7,0,0×20); //显现秒十位
DisplayOneChar(8,0,0×20); //显现秒个位
}
}
else
{
DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显现秒十位
DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显现秒个位
}
if(min==1) //分钟闪耀标志位
{
if(flag==1)
{
DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显现分钟十位
DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显现分钟个位
}
else
{
DisplayOneChar(4,0,0×20); //显现分钟十位
DisplayOneChar(5,0,0×20); //显现分钟个位
}
}
else
{
DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显现分钟十位
DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显现分钟个位
}
if(hour==1) //小时闪耀标志位
{
if(flag==1)
{
DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显现小时十位
DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显现小时个位
}
else
{
DisplayOneChar(1,0,0×20); //显现小时十位
DisplayOneChar(2,0,0×20); //显现小时个位
}
}
else
{
DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显现小时十位
DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显现小时个位
}
}
/*****************************************************
函 数 名:void Disp_line2()
功 能:显现日期和星期 (XX/XX/XX Week.X)
说 明:第二行显现数据处理
进口参数:无
返 回 值:无
*****************************************************/
// 屏幕显现第二行 日期和星期
void Disp_line2(void)
{
DisplayOneChar(3,1,0x2f); //显现固定字符
DisplayOneChar(6,1,0x2f);
DisplayListChar(10,1,week);
if(year==1) //年闪耀标志位
{
if(flag==1)
{
DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显现年十位
DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显现年个位
}
else
{
DisplayOneChar(1,1,0×20); //显现年十位
DisplayOneChar(2,1,0×20); //显现年个位
}
}
else
{
DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显现年十位
DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显现年个位
}
if(mon==1) //月闪耀标志位
{
if(flag==1)
{
DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显现月十位
DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显现月个位
}
else
{
DisplayOneChar(4,1,0×20); //显现月十位
DisplayOneChar(5,1,0×20); //显现月个位
}
}
else
{
DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显现月十位
DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显现月个位
}
if(day==1) //日闪耀标志位
{
if(flag==1)
{
DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显现日十位
DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显现日个位
}
else
{
DisplayOneChar(7,1,0×20); //显现日十位
DisplayOneChar(8,1,0×20); //显现日个位
}
}
else
{
DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显现日十位
DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显现日个位
}
if(weekk==1) //星期闪耀标志位
{
if(flag==1)
{
DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显现星期
}
else
{
DisplayOneChar(15,1,0×20); //显现星期
}
}
else
{
DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显现星期
}
}
//================================ LCM1602操控部分 =======================================
/*****************************************************
函 数 名:void WriteDataLCM()
功 能:向LCM1602中写入数据
说 明:将形参WDLCM中的数据写入LCM中
进口参数:WDLCM
返 回 值:无
*****************************************************/
//写数据
void WriteDataLCM(uchar WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;//写入数据到LCM
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高能够在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}
/*****************************************************
函 数 名:void WriteCommandLCM()
功 能:向LCM1602中写入指令
说 明:向LCM中写入指令;假如BuysC=0时,疏忽忙检测,假如BuysC=1时,不疏忽忙检测
进口参数:WCLCM,BuysC
返 回 值:无
*****************************************************/
//写指令
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时疏忽忙检测
{
if (BuysC) ReadStatusLCM(); //依据需要检测忙
LCM_Data = WCLCM; //写入指令
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
/*****************************************************
函 数 名:uchar ReadStatusLCM()
功 能:读状况
说 明:判别LCM的作业状况;也能够不必此函数,用一段延时程序替代
进口参数:无
返 回 值:LCM_Data
*****************************************************/
//读状况
uchar ReadStatusLCM(void)
{
LCM_Data = 0xFF; //LCM数据口先置1
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号.假如忙,则不履行
return(LCM_Data);//不忙回来读取数据
}
/*****************************************************
函 数 名:void LCMInit()
功 能:初始化LCM1602
说 明:LCM在作业前先要对显现屏初始化,不然模块无法正常作业
进口参数:无
返 回 值:五
*****************************************************/
//LCM初始化
void LCMInit(void)
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); // 三次显现方法设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0); // 0x38指令表明:8位数据显现方法,俩行多显现
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); // 显现方法设置,开端要求每次检测忙信号
WriteCommandLCM(0x08,1); // 封闭显现
WriteCommandLCM(0x01,1); // 显现清屏
WriteCommandLCM(0x06,1); // 显现光标移动设置
WriteCommandLCM(0x0C,1); // 显现开及光标设置
}
/*****************************************************
函 数 名:void DisplayOneChar()
功 能:按指定坐标中写入数据
说 明:X-横坐标,Y-纵坐标
进口参数:X,Y,DData
返 回 值:
*****************************************************/
//按指定方位显现一个字符
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
Y &= 0x01;
X &= 0x0F; //约束X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显现第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这儿不检测忙信号,发送地址码
WriteDataLCM(DData);
}
/*****************************************************
函 数 名:void DisplayListChar()
功 能:向指定坐标中写入字符串
说 明:X-横坐标,Y-纵坐标
进口参数:X,Y,*DData
返 回 值:
*****************************************************/
//按指定方位显现一串字符 ***本来的遇到空格0x20就不显现***
void DisplayListChar(uchar X, uchar Y, uchar code *DData)
{
uchar ListLength,j;
ListLength = strlen(DData);//strlen:读取字符串的长度
Y &= 0x1;
X &= 0xF; //约束X不能大于15,Y不能大于1
if (X <= 0xF) //X坐标应小于0xF
{
for(j=0;j
DisplayOneChar(X, Y, DData[j]); //显现单个字符
X++;//横坐标加1,纵坐标不变
}
}
}
//=================================== 自界说字符 ==========================================
/*****************************************************
函 数 名:void mychar()
功 能:自界说字符–CGRAM
说 明:LCM1602字符库中没有温度符号,自界说温度符号
进口参数:无
返 回 值:无
界说方法:1602中界说CGRAM的方法如下:
—————————————————————————
| CGRAM地址设置 | 自界说的代码 |
| DB7 DB6 | DB5 DB4 DB3 | DB2 DB1 DB0 | DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 |
| 0 1 | 0 0 0 | X X X | 0 0 0 0 * 0 0 0 |
| 0 1 | 0 0 1 | X X X | 0 0 0 0 * 0 0 1 |
| … | … | … | … … |
| 0 1 | 1 1 0 | X X X | 0 0 0 0 * 1 1 0 |
| 0 1 | 1 1 1 | X X X | 0 0 0 0 * 1 1 1 |
—————————————————————————
1. 1602共能界说8个5×8字符;
2. CGRAM地址设置: X X X–DB2 DB1 DB0对应写入地址,1~8行;
DB5 DB4 DB3对应自界说字符代码;DB7 DB6为指令码,不可变.
3. 自界说的代码: 高4位DB7 DB6 DB5 DB4为0000时它的低3位DB2 DB1 DB0对应于第1-8个,DB3为无关项。
4. 自界说的代码的DB2 DB1 DB0对应于CGRAM地址的DB5 DB4 DB3。
*****************************************************/
void mychar()
{
//———自界说字符代码–01H——————-
WriteCommandLCM(0x48,0); //第1行
WriteDataLCM(0x02);//
WriteCommandLCM(0x49,0); //第2行
WriteDataLCM(0x05);//
WriteCommandLCM(0x4a,0); //第3行 1——**–
WriteDataLCM(0x05);// 2—-**–**
WriteCommandLCM(0x4b,0); //第4行 3—-**–**
WriteDataLCM(0x02);// 4——**–
WriteCommandLCM(0x4c,0); //第5行 5———-
WriteDataLCM(0x00);// 6———-
WriteCommandLCM(0x4d,0); //第6行 7———-
WriteDataLCM(0x00);// 8———-
WriteCommandLCM(0x4e,0); //第7行
WriteDataLCM(0x00);//
WriteCommandLCM(0x4f,0); //第8行
WriteDataLCM(0x00);//
//———————————————–
}
//======================================= 延时函数部分 ====================================
/*****************************************************
函 数 名:void Delay5Ms()
功 能:5ms延时
说 明:软件消除按键颤动和恰当的延时
进口参数:无
返 回 值:无
*****************************************************/
//5ms延时
void Delay5Ms(void)
{
uint TempCyc = 5552; //放入延时数据
while(TempCyc–);
}
/*****************************************************
函 数 名:void Delay400Ms()
功 能:400ms延时
说 明:
进口参数:无
返 回 值:无
*****************************************************/
//400ms延时
void Delay400Ms(void)
{
uchar TempCycA = 5;
uint TempCycB;
while(TempCycA–)
{
TempCycB=7269;
while(TempCycB–);
};
}
//================================== 时钟芯片操控部分 ======================================
/*****************************************************
函 数 名:RTInputByte()
功 能:实时时钟写入一字节
说 明:往DS1302写入1Byte数据 (内部函数)
进口参数:d 写入的数据
返 回 值:无
*****************************************************/
void RTInputByte(uchar d)
{
uchar i;
ACC = d;
for(i=8; i>0; i–)
{
T_IO = ACC0; /*相当于汇编中的 RRC */
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/*****************************************************
函 数 名:RTOutputByte()
功 能:实时时钟读取一字节
说 明:从DS1302读取1Byte数据 (内部函数)
进口参数:无
返 回 值:ACC
设 计:zhaojun 日 期:2007-06-29
修 改: 日 期:
*****************************************************/
uchar RTOutputByte(void)
{
uchar i;
for(i=8; i>0; i–)
{
ACC = ACC >>1; /*相当于汇编中的 RRC */
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC); //回来读取值
}
/*****************************************************
函 数 名:W1302()
功 能:往DS1302写入数据
说 明:先写地址,后写指令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
进口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
*****************************************************/
void W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,指令 */
RTInputByte(ucDa); /* 写1Byte数据*/
T_CLK = 1;
T_RST = 0;
}
/******************************************************
函 数 名:R1302()
功 能:读取DS1302某地址的数据
说 明:先写地址,后读指令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
进口参数:ucAddr: DS1302地址
返 回 值:ucData :读取的数据
*******************************************************/
uchar R1302(uchar ucAddr)
{
uchar ucData;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,指令 */
ucData = RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST = 0;
return(ucData);
}
/*******************************************************
函 数 名:Set1302()
功 能:设置初始时刻
说 明:先写地址,后读指令/数据(寄存器多字节方法)
调 用:W1302()
进口参数:pClock: 设置时钟数据地址 格局为: 秒 分 时 日 月 星期 年
7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B
返 回 值:无
********************************************************/
void Set1302(uchar *pClock)
{
uchar i;
uchar ucAddr = 0x80;
W1302(0x8e,0x00); /* 操控指令,WP=0,写操作?*/
for(i =7; i>0; i–)
{
W1302(ucAddr,*pClock); /* 秒 分 时 日 月 星期 年 */
pClock++;
ucAddr +=2;
}
W1302(0x8e,0x80); /* 操控指令,WP=1,写保护?*/
}
//================================= 温度显现操控部分 ===============================================
/*****************************************************
函 数 名:void delay()
功 能:DS18B20延时
说 明:DS18B20时序延时
进口参数:useconds
返 回 值:无
*****************************************************/
//*********** 18B20驱动 **************************
//延时
void delay(word useconds)
{
for(;useconds>0;useconds–);
}
/*****************************************************
函 数 名:byte ow_reset()
功 能:DS18B20复位
说 明:DS18B20运用时先要复位
进口参数:无
返 回 值:presence
*****************************************************/
//复位
byte ow_reset(void)
{
byte presence;
DQ = 0; //拉低总线
delay(29); // 坚持 480us
DQ = 1; // 开释总线
delay(3); // 等候回复
presence = DQ; // 读取信号
delay(25); // 等候完毕信号
return(presence); // 回来 0:正常 1:不存在
}
/*****************************************************
函 数 名:byte read_byte()
功 能:从 1-wire 总线上读取一个字节
说 明:读总线上的数据有严厉的时序
进口参数:
返 回 值:value
*****************************************************/
byte read_byte(void)
{
byte i;
byte value = 0;
for (i=8;i>0;i–)
{
value>>=1;
DQ = 0;
DQ = 1;
delay(1);
if(DQ)value|=0x80;
delay(6);
}
return(value);
}
/*****************************************************
函 数 名:void write_byte()
功 能:向 1-WIRE 总线上写一个字节
说 明:写总线上的数据有严厉的时序
进口参数:val
返 回 值:无
*****************************************************/
void write_byte(char val)
{
byte i;
for (i=8; i>0; i–) // 一次写一位
{
DQ = 0; //
DQ = val&0x01;
delay(5); //
DQ = 1;
val=val/2;
}
delay(5);
}
/*****************************************************
函 数 名:Read_Temperature()
功 能:读取和显现温度
说 明:
进口参数:xx,yy
返 回 值:无
*****************************************************/
Read_Temperature(char xx,char yy)
{
uchar i,tl_temp;
uint x;
uchar ct[8];
union //共用体
{
byte c[2];
int x;
}temp;
ow_reset(); // DS18B20复位
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 转化温度
ow_reset();
write_byte(0xCC); // Skip ROM
write_byte(0xbe); // 读取寄存器
temp.c[1]=read_byte(); // 读出温度低8位
temp.c[0]=read_byte(); // 读出温度高8位
// 零下温度判别
sflag=0; //温度零下标志 0:零上,1:零下
if((temp.c[0]&0xf8)!=0x00)
{
sflag=1; // 零下标志方位1
temp.c[1]=~temp.c[1]; // 低8位取反
temp.c[0]=~temp.c[0]; // 高8位取反
tl_temp=temp.c[1]+1; // 低8位加1
temp.c[1]=tl_temp; // 核算后从头存入数组
if(tl_temp>255) temp.c[0]++; // 假如低8位大于255,向高8位进1
}
x=((temp.c[0]&0x07)*256+temp.c[1])*.625;
for(i=0;i<8;i++)
{
ct[i]=0;
}
i=0;
while(x/10)
{
ct[i]=x%10;
x=x/10;
i++;
}
ct[i]=x;
if(sflag==1) DisplayOneChar(xx-1,yy,0x2d);
else DisplayOneChar(xx-1,yy,0x20);
DisplayOneChar(xx, yy,ct[2]+0x30); // 显现温度十位数
DisplayOneChar(xx+1,yy,ct[1]+0x30); // 显现温度个位数
DisplayOneChar(xx+2,yy,0x2e); // 显现小数点
DisplayOneChar(xx+3,yy,ct[0]+0x30); // 显现温度小数位
DisplayOneChar(xx+4,yy,0x01); // 显现自界说字符
DisplayOneChar(xx+5,yy,0x43); // 显现字符”C”
}
/*****************************************************
函 数 名:void adjust_res()
功 能:温度分辨率调整
说 明:此函数能够对温度的显现进行精度调理.
进口参数:res
返 回 值:无
*****************************************************/
void adjust_res(char res) // res 别离等于 0x1f, 0x3f, 0x5f 温度读数分辨率别离对应
// 0.5, 0.25, 0.125
{
ow_reset(); // 复位
write_byte(0xcc); // 越过Rom
write_byte(0x4e); // 写暂存器
write_byte(0x02); // 写TH
write_byte(0x01); // 写TL
write_byte(res); // 温度转化分辨率设置
ow_reset(); // 复位
write_byte(0xcc); // 越过Rom
write_byte(0x48); // 把暂存器内容写到EPRam中
}
//==========================程序完毕======================================================