基于51单片机串口通信的实时温度

发布者:学海星空最新更新时间:2015-03-11 来源: 51hei关键字:51单片机  串口通信  实时温度 手机看文章 扫描二维码
随时随地手机看文章
测试环境:Keil μVision4

测试芯片:STC89C52RC
所需器件:DS18B20 
//
//Created by XD on 03/04/14
//
#include //调用51单片机的头文件
#include //这个头文件里有_nop()_;函数的定义 
//---------------------------------------
//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);    
        }
}

关键字:51单片机  串口通信  实时温度 引用地址:基于51单片机串口通信的实时温度

上一篇:基于单片机的光伏发电实时监测系统设计
下一篇:基于12864液晶的程序代码显示本人姓名及专业

推荐阅读最新更新时间:2024-03-16 13:54

ADC0832模数转换51单片机程序与电路图
#include AT89x51.h #include intrins.h #define uint unsigned int #define uchar unsigned char //******************adc0832****************************// sbit CS=P2^3; //使能。 sbit CLK=P2^2;// 时钟 sbit DO=P2^1; // 数据输出 sbit DI=P2^0;//数据输入 char CC = 11001001 ; uchar tab ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
[单片机]
ADC0832模数转换<font color='red'>51单片机</font>程序与电路图
采用89C51单片机设计的喷油校泵台调速系统方案
1 引言 燃油喷射系统的性能直接影响柴油机的工作过程和性能指标,是柴油机改善排放、降低油耗和提高性能的关键部分。传统的内燃机车柴油喷油校泵台主要用于喷油泵的磨合及性能试验,其驱动部分采用晶闸管电磁转差离合器无级调速系统,控制和显示喷油泵的主轴转速。由于采用分离元件,测试灵敏度低,设定调整不方便且故障率高。目前,国外喷油校泵台采用微机控制及数显系统。为此,按国际标准采用89C51单片机设计了一种新型的校泵台调速系统,能够实时控制主轴转速测试和调节,并将相关测量数据传输给上位PC机进行显示,从而提高测试灵敏度。 2 系统结构设计   该系统设计采用转速单闭环凋速系统,如图1所示。驱动电路由晶闸管和电机构成,而控制电路则由转
[单片机]
采用89C<font color='red'>51单片机</font>设计的喷油校泵台调速系统方案
30-基于51单片机出租车计价器(霍尔测速)
具体实现功能 系统由AT89C52单片机+霍尔传感器模块+LCD1602液晶屏+DS1302时钟模块+AT24C02掉电存储模块+直流电机+按键模块+电源构成。 具体功能: 1、无乘客模式:显示当前时间; 2、切换到乘客模式:可以显示起步价(三公里内)、单价(三公里后)、总价(元)、里程和乘车时间,可以按照里程或计时两种模式收费; 3、里程模式收费:在高速情况下,按照起步价和里程单价收费 4、计时收费模式:在低速情况下,按照计时时间和时间单价收费 5、按清零键,计价器可清除计价。 6、可以设置白天和夜晚的起步价、单价,可以设置计时模式的单价; 7、根据当前时间,白天和夜晚的收费不同。 液晶显示的
[单片机]
30-基于<font color='red'>51单片机</font>出租车计价器(霍尔测速)
有害气体红外感应及语音警示控制系统的设计
0引言 利用红外感应系统感应附近有无有害气体,当红外感应系统感受到有有害气体接近时,送出持续一段时间的高电平;单片机通过开启中断,启动语音芯片,单片机通过串口通信,从上位机提取的有害气体参数提示给附近人体,并经过与安全值的比较判定当前环境是否安全。对语音芯片的使用,先将必要的文字、数字信息录制进去,放音时,通过单片机自动寻址,把实时参数读取出来。为便于以后系统改进或移植到其他系统,可设计录音、放音电路,通过切换录制不同内容。系统设计友好、方便,给人的信息也更加直接。 1系统总体设计方案 在气体浓度是现有可利用的数据的基础上,考虑了系统的衔接性和可移植性。系统总体方案见图1。 本系统分为四大模块:核心控制模块、语
[单片机]
51单片机C语言程序(一)发光二极管
程序(一)点亮第一个发光二极管 #include reg52.h void main() { P1=0xfe; while(1); } 程序(二)让第一个发光二极管闪烁 #include reg52.h sbit led1=P1^0; void main() { unsigned int i; while(1) { i=50000; led1=0; while(i--); i=50000; led1=1; while(i--); } } 程序(三) //第一个发光二极管以间隔2000ms闪烁 #include reg52.h #define uint unsigned int #de
[单片机]
51单片机设计方案TOP10(三)
0 引言   对目前所有兼容lntel 8031指令系统的单片机,统l称为51单片机。Intel的8031单片机是51单片机的始祖。8031单片机是目前应用最广泛的8位单片机之一。随着Flash rom技术的发展,它也得到了不断的发展,广泛应用于工业测控系统中ATMEL公司的AT89系列,是8031单片机中最有代表性的型号。51单片机是基础入门的一个单片机,也是应用最广泛的一种,在目前乃至今后很长的一段时问内。51系列的兼容机型都将占有大量的市场。   控制系统传统的设计思想和设计方法,因51单片机的应用从根本上得到了改变。现在正在用单片机通过软件的方法,来实现采用硬件电路实现的大部分控制功能,智能化的数字计算控制、模糊控制和自适
[模拟电子]
<font color='red'>51单片机</font>设计方案TOP10(三)
51单片机简易电子称程序
这是我的单片机设计,主要是使用压力传感器、HX711模块和51单片机做的,附件里包含了电子称的原理图和源代码 这个简易电子称共有三个模式: 模式1:进行普通的物体测量; 模式2:计价模式; 模式3:累计测量模式; 此外,除了可以用按键进行模式的切换,还可通过上位机发送指令进行模式的切换。 此次课程设计主要是针对51单片机的基础知识的运用,其中主要运用了以下知识点:对矩阵按键、LED灯、蜂鸣器、AD转换、LCD12864、 定时器0、定时器1、外部中断0、外部中断1、串口(使用到定时器2,所以在烧录时芯片请用STC89C52)等。 简易介绍 基于51单片机设计的简易电子称,性能比较简单,共分为3个模式,模式一是用于重物的测量,
[单片机]
<font color='red'>51单片机</font>简易电子称程序
基于51单片机的超声波测距系统的研究与设计
  在日常生产生活中,很多场合如汽车倒车、机器人避障、工业测井、水库液位测量等需要自动进行非接触测距。超声波是指频率大于20 kHz的在弹性介质中产生的机械震荡波,其具有指向性强、能量消耗缓慢、传播距离相对较远等特点,因此常被用于非接触测距。由于超声波对光线、色彩和电磁场不敏感,因此超声波测距对环境有较好的适应能力,此外超声波测量在实时、精度、价格也能得到很好的折衷。   为此,文中尝试以单片机AT89S52为核心,利用一对40 kHz压电超声传感器设计一款体积较小、价格低廉、精度较高、具有温度补偿、实时LCD显示和报警的超声波测距仪。   1 超声波测距原理   超声波传感器分机械方式和电气方式两类,它实际上是一种换能器,
[单片机]
基于<font color='red'>51单片机</font>的超声波测距系统的研究与设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多每日新闻
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved