测试芯片:STC89C52RC
所需器件:DS18B20
//
//Created by XD on 03/04/14
//
#include
#include
//---------------------------------------
//1602液晶相关I/O设置
sbit E = P1^2; //液晶E接口位定义,对位操作,要先进行位定义,因为AT89X52.h头文件里没有相关的位定义
sbit RW = P1^1;//液晶RW接口位定义,对位操作,要先进行位定义,因为AT89X52.h头文件里没有相关的位定义
sbit RS = P1^0;//液晶RS接口位定义,对位操作,要先进行位定义,因为AT89X52.h头文件里没有相关的位定义
//---------------------------------------
sbit DS18B20 = P2^0;//DS18B20接口定义
sbit LED = P2^7;
//---------------------------------------
//串口接收寄存器设置
unsigned char senddata;
unsigned char USARTbuf;//定义一个8位的变量来暂存串口接收内容
//---------------------------------------
//1602液晶寄存器设置
unsigned char DISbuf; //设置8位的unsigend char型寄存器用来暂存1602要显示的内容
//---------------------------------------
//DS18B20相关变量
unsigned char temp1;//小数部分
unsigned char temp2;//整数部分
unsigned char code table[16] = {0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};//小数部分显示的数组
//---------------------------------------
//名称:延时函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void Delay(unsigned int nTimeDelay)
{
unsigned int i;//定义无符号变量i
/*
*nTimeDelay自减一次,执行一次下面语句,直到nTimeDelay为0时,
*结束循环,一共执行下面语句nTimeDelay次,while语句的循环体只有一句for循环,其没有循环体。
*/
while (nTimeDelay--)
for (i = 0;i < 125;i++);
}
//---------------------------------------
//名称:复位DS18B20函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
bit Reset(void)
{
unsigned int i;//定义无符号整型变量,用于下面的时序延时
bit k;//定义bit型变量k,k=1为复位成功,k=0为复位失败
/*
*在初始化时序中,拉低DQ总线至少保持480μs的低电平信号
*/
DS18B20 = 0;
i = 200;
while(i > 0)
i--;
/*
*DS18B20 = 1,DQ总线由10K的上拉电阻拉到高电平,
*DS18B20在检测到总线的上升沿之后,
*等待15-60μs
*/
DS18B20 = 1;
i = 18;
while(i > 0)
i--;
/*
*将DQ总线的状态赋值给k,为1复位成功,为0复位失败
*发出一个60-240μs低电平信号构成的存在脉冲
*/
k = DS18B20;
i = 91;
while(i > 0)
i--;
return k;//返回DS18B20是否复位成功标志
}
//---------------------------------------
//名称:读一字节函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
unsigned char ReadByte(void)
{
unsigned int i;//定义无符号整型变量,用于下面的时序延时
unsigned char j,buf = 0;
for(j = 0;j < 8;j++) //接收8次还原一个字节数据
{
buf = buf >> 1;//接收前,先将接收缓冲区右移
DS18B20 = 0;//将DQ总线拉低并保持1μs-15μs,当总线控制器把数据线从高电平拉到低电平时,读时序开始。
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
DS18B20 = 1;//总线被释放,被10K的上拉电阻拉高,在总线控制器发出读时序后,
//DS18B20通过拉高或拉低总线上来传输1或0。当传输逻辑0结束后,总线将被释放,通过上拉电阻回到上升沿状态。
//从DS18B20输出的数据在读时序的下降沿出现后15μs内有效。
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
if(DS18B20 == 1) buf |= 0x80;//如果接收到数据为1,从最高位往右移
i = 12; //保持至少60μs
while(i > 0)//保持至少60μs
i--; //保持至少60μs
}
return buf; //接收缓冲区参数返回
}[page]
//---------------------------------------
//名称:写一字节函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void WriteByte(unsigned char dat)
{
unsigned int i;//定义无符号整型变量,用于下面的时序延时
unsigned char j;//定义一个无符号的字符型变量j
for(j = 0;j < 8;j++)//一个字节为8位,所以循环八次写操作
{
//传过来的要写的数据dat(这里的dat为形参,实际调用该函数时会发送来实参)
//与0x01做与运算,可以获得数据的最低位,如果if的表达式为真,说明数据的最低
//位为1,则进行写1操作,否则进行写0操作。
if(dat & 0x01)//进行写1操作
{
DS18B20 =0;//将DQ总线拉低并保持1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
_nop_(); //保持至少1μs-15μs
DS18B20 = 1;//总线被释放,被10K的上拉电阻拉高
i = 14; //延时操作,使DQ总线保持至少60μs的低电平
while(i > 0)//延时操作,使DQ总线保持至少60μs的低电平
i--; //延时操作,使DQ总线保持至少60μs的低电平
}
else //进行写0操作
{
DS18B20 = 0;//将DQ总线拉低并保持至少60μs
i = 14; //延时操作,使DQ总线保持至少60μs的低电平
while(i > 0)//延时操作,使DQ总线保持至少60μs的低电平
i--; //延时操作,使DQ总线保持至少60μs的低电平
DS18B20 = 1;//总线被释放,被10K的上拉电阻拉高
_nop_(); //保持至少1μs
_nop_(); //保持至少1μs
_nop_(); //保持至少1μs
_nop_(); //保持至少1μs
}
dat = dat >> 1;//传过来的要写的数据dat做右移一位运算,
//之后循环上面的程序8次,8次之后就可以将一个字节的数据写入DS18B20中
}
}
//---------------------------------------
//名称:DS18B20温度转换函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
bit Convert(void)
{
if(Reset() == 1) //复位DS18B20
{
WriteByte(0xcc); //写入跳过序列号命令字 Skip Rom
WriteByte(0x44); //写入温度转换命令字 Convert T
return 1; //启动温度转换成功
}
else
{
return 0; //启动温度转换失败
}
}
//---------------------------------------
//名称:转换结束处理函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void ReadFlash(void)
{
unsigned char Lsb,Msb;
if(Reset() == 1) //复位DS18B20
{
WriteByte(0xcc); //写入跳过序列号命令字 Skip Rom
WriteByte(0xbe); //写入读取数据令字 Read Scratchpad
Lsb = ReadByte(); //读出第一个字节暂存于LSB
Msb = ReadByte(); //读出第二个字节暂存于MSB
temp1 = Lsb & 0x0f; //temp1内装温度参数的小数部分
temp2 = (Lsb >> 4) | (Msb << 4);//temp2内装温度参数的整数部
}
else
{
temp1 = 0; //复位失败,温度参数清零
temp2 = 0; //复位失败,温度参数清零
}
}
//---------------------------------------
//名称:1602液晶忙检测函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_busy(void)
{
P0_7 = 1; //将P0.7置1,为读状态做准备
RS = 0; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
RW = 1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
E = 1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
while(P0_7 == 1); //由P0.7读入1,表示1602液晶忙,需要等待
E = 0; //读完以后,恢复E的电平
}
//---------------------------------------
//名称:1602写命令函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_Write_com(unsigned char combuf)
{
RS = 0; //选择指令寄存器
RW = 0; //选择写状态
P0 = combuf; //将命令字通过P0口送至DB
E = 1; //E高电平将命令字写入1602液晶
E = 0; //写完以后,恢复E的电平
}
//---------------------------------------
//名称:1602写命令函数(带忙检测)
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_Write_com_busy(unsigned char combuf)
{
LCD1602_busy(); //调用忙检测函数
LCD1602_Write_com(combuf); //调用忙检测函数
}[page]
//---------------------------------------
//名称:1602写数据函数(带忙检测)
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_Write_data_busy(unsigned char databuf)
{
LCD1602_busy(); //调用忙检测函数
RS = 1; //选择数据寄存器
RW = 0; //选择写状态
P0 = databuf; //将命令字通过P0口送至DB
E = 1; //E高电平将命令字写入1602液晶
E = 0; //写完以后,恢复E的电平
}
//---------------------------------------
//名称:1602液晶显示地址写函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_Write_address(unsigned char x,unsigned char y)
{
x &= 0x0f; //列地址限制在0-15间
y &= 0x01; //行地址限制在0-1间
if(y == 0) //如果是第一行
LCD1602_Write_com_busy(x | 0x80); //将列地址写入
else //如果是第二行
LCD1602_Write_com_busy((x + 0x40) | 0x80); //将列地址写入
}
//---------------------------------------
//名称:1602液晶初始化函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_init(void)
{
Delay(150); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay(50); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay(50); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x08); //显示功能关,无光标
LCD1602_Write_com_busy(0x01); //清屏
LCD1602_Write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动
LCD1602_Write_com_busy(0x0C); //显示功能开,无光标
}
//---------------------------------------
//名称:1602液晶指定地址显示函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
{
LCD1602_Write_address(x,y); //先将地址信息写入
LCD1602_Write_data_busy(buf); //再写入要显示的数据
}
//---------------------------------------
//名称:串口发送函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void UARTSendbyte(unsigned char bytebuf)
{
SBUF = bytebuf;//缓冲区装载要发送的字节
while(TI == 0);//等待发送完毕,TI标志位会置1
TI = 0;//清零发送完成标志位
}
//---------------------------------------
//名称:主函数
//作者:XD
//日期:2014-04-03
//---------------------------------------
void main(void) //主函数,单片机启动后就是从这个函数开始运行的
{
LCD1602_init(); //调用1602液晶初始化函数
//*****USART串口初始化*****
/*
* 串行口控制寄存器SCON
* D7--SM0 = 0;SM0 = 0;SM1 = 1;工作方式1
* D6--SM1 = 1;SM0 = 0;SM1 = 1;工作方式1
* D5--SM2 = 0;接收到单个字节,RI就置位
* D4--REN = 1;允许串行口接收
* D3--TB8 = 0;方式2和方式3时,为发送的第9位数据,也可以做奇偶校验位
* D2--RB8 = 0;方式2和方式3时,为发送的第9位数据;方式1时,为接收到的停止位
* D1--TI = 0;发送中断标志位,必须由软件清零
* D0--RI = 0;接收中断标志位,必须由软件清零
*/
SCON = 0x50;
TMOD|= 0x20;//定时器工作方式2
PCON|= 0x80;//波特率=定时器1溢出率/16
TH1 = 0xFD;//10位异步通信方式、1位起始位0、8位数据位和1位停止位1
TL1 = 0xF3;//波特率19200、11.0592MHz
TR1 = 1;
//**************************
while(1)//死循环
{
if(Convert() == 1)//启动转换
{
ReadFlash();//读取温度
if(temp2 > 99) temp2 = 99;//当温度超过99℃时,temp2被赋值99,限制最高测量温度为99摄氏度
if(temp1 > 15) temp1=0;
LCD1602_Disp(0,1,temp2 / 10 + '0'); //温度整数部分十位
LCD1602_Disp(1,1,temp2 % 10 + '0'); //温度整数部分个位
LCD1602_Disp(2,1,'.'); //.
LCD1602_Disp(3,1,table[temp1] + '0'); //温度小数A部分
LCD1602_Disp(4,1,0xdf); //.
LCD1602_Disp(5,1,0x43); //C
}
UARTSendbyte(temp2);
}
}
上一篇:基于单片机的光伏发电实时监测系统设计
下一篇:基于12864液晶的程序代码显示本人姓名及专业
推荐阅读最新更新时间:2024-03-16 13:54