找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3201|回复: 1
打印 上一主题 下一主题
收起左侧

带串口通信的温度监测仪器课程设计报告

[复制链接]
跳转到指定楼层
楼主
ID:344917 发表于 2018-6-29 15:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

单片机与嵌入式系统课程设计
院    系:自动化学院
题    目:带串口通信的温度监测仪器设计
专 业 班 别:自动化155
提 交 日 期: 2018年5月

带串口通信的温度监测仪器设计

摘要:本设计采用的主控芯片是ATMEL公司的AT89C51单片机,数字温度传感器是DALLAS公司的DS18B20。本设计用数字传感器DS18B20测量温度,测量精度高,传感器体积小,使用方便。所以本次设计的数字温度计在工业、农业、日常生活中都有广泛的应用。


随着现代信息技术的飞速发展和传统工业改造的逐步实现,能够独立工作的温度检测和显示系统应用于诸多领域。单片机技术已经广泛应用社会生活的各个领域,已经成为一种非常实用的技术。51单片机是最常用的一种单片机。本次设计的数字温度计采用的是DS18B20数字温度传感器,DS18B20是一种可组网的高精度数字式温度传感器,并可使测量电路变得简单、可靠。

1 总体功能

基本实现串口通信程序,实现当仪器通过串口接收到字符“A”时,仪器通过串口发送内容格式为“DD.DTDDU”的字符串,其中第1-4位“DD.D”为采集的温度,第5位为字符“T”,为温度标识,第6-7位“DD”为温度上限值,第8位为字符“U”,为温度上限值标识。

2 硬件设计

图 1 硬件图

放置器件有1个AT89C51单片机,1个DS18B20温度传感器,1个COMPIM串口,1个RESPACK-8,1个Buzzer,1个LED-GREEN,1个CRYSTAL,5个10k电阻和5个按钮,3个1nF电容。

AT89C51单片机: 4k 字节Flash 闪速存储器,128字节内部RAM,32 个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

VCC:供电电压。

GND:接地。

P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P0口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的低八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须接上拉电阻。

P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为低八位地址接收。

P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

P3口也可作为AT89C51的一些特殊功能口,如下表所示:

口管脚 备选功能

P3.0 RXD(串行输入口)

P3.1 TXD(串行输出口)

P3.2 /INT0(外部中断0)

P3.3 /INT1(外部中断1)

P3.4 T0(计时器0外部输入)

P3.5 T1(计时器1外部输入)

P3.6 /WR(外部数据存储器写选通)

P3.7 /RD(外部数据存储器读选通)

P3口同时为闪烁编程和编程校验接收一些控制信号。

RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的低位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

/EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:来自反向振荡器的输出。

采用集成芯片DS18B20:DS18B20是DALLAS公司生产的一线式数字温度传感器,每一片芯片内部都有一个全球惟一的64 位编码,在多路测温时就是通过匹配这个编码(ID)来确定下一步对那一个温度传感器进行操作,故在同一总线上可以挂接多个传感器芯片。该芯片具有三引脚TO-92小体积封装形式,DS18B20数字温度计是DALLAS公司生产的1-Wire器件,即单总线器件,具有线路简单,体积小等特点。DS18B20数字温度传感器接线方便,在不同的场合当中其“封装”形式多样,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。故DS18B20的体积小,使用方便,封装形式多样等优点,使其特别适合在一些空间比较小以及温度变化的速度比较缓慢的环境中工作。

图 2 DS18B20的封装形式

DS18B20的64位ROM的结构开始8位是产品类型的编号,接着是每个器件的惟一的序号,共有48位,最后8位是前面56位的CRC检验码,这也是多个DS18B20可以采用一线进行通信的原因。温度报警触发器TH和TL,可通过软件写入户报警上下限。

DS18B20温度传感器的内部存储器还包括一个高速暂存RAM和一个非易失性的可电擦除的EEPRAM。高速暂存RAM的结构为8字节的存储器,结构如图2-3所示。

图 3 DS18B20的高速暂存RAM的结构

头2个字节包含测得的温度信息,第3和第4字节TH和TL的拷贝是易失的,每次上电复位时被刷新。第5个字节,为配置寄存器,它的内容用于确定温度值的数字转换分辨率,DS18B20工作时寄存器中的分辨率转换为相应精度的温度数值。

当DS18B20接收到温度转换命令后,开始启动转换。转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1、2字节。单片机可以通过单线接口读出该数据,读数据时低位在先,高位在后,数据格式以0.0625℃/LSB形式表示。

3 单片机程序设计(宋体,小四,加粗)

3.1 主程序

  1. <font color="rgb(0, 0, 0)"><font face="Calibri"><font style="font-size: 12pt">void main()
  2. {
  3.               int temp;
  4.               int datas1[] = {0, 0, 0, 0, 0};

  5.               UsartConfiguration();
  6.               LcdInit();                                          //初始化LCD1602
  7.               LcdWriteCom(0x85);              //写地址 80表示初始地址
  8.               LcdWriteData('C');
  9.               SETTEMP=32;
  10.               datas1[0]=SETTEMP/10;
  11.                             datas1[1]=SETTEMP%10;
  12.                             LcdWriteCom(0x80+0x40+9);
  13.                             LcdWriteData(datas1[0]+'0');            
  14.                             LcdWriteCom(0x80+0x40+10);
  15.                             LcdWriteData(datas1[1]+'0');            
  16.               while(1)
  17.               {
  18.                             temp=Ds18b20ReadTemp();
  19.                             LcdDisplay(temp);
  20.                             Delay1ms(1000);//1s钟刷一次
  21.                             if(k1==0)
  22.                             {
  23.                             Delay1ms(10);
  24.                             SETTEMP=SETTEMP+1;
  25.                             Delay1ms(1000);//1s钟刷一次
  26.                             datas1[0]=SETTEMP/10;
  27.                             datas1[1]=SETTEMP%10;
  28.                             LcdWriteCom(0x80+0x40+9);
  29.                             LcdWriteData(datas1[0]+'0');            
  30.                             LcdWriteCom(0x80+0x40+10);
  31.                             LcdWriteData(datas1[1]+'0');                                         
  32.                             }
  33.                             if(k2==0)
  34.                             {
  35.                             Delay1ms(10);
  36.                             SETTEMP=SETTEMP-1;
  37.                             datas1[0]=SETTEMP/10;
  38.                             datas1[1]=SETTEMP%10;
  39.                             LcdWriteCom(0x80+0x40+9);
  40.                             LcdWriteData(datas1[0]+'0');            
  41.                             LcdWriteCom(0x80+0x40+10);
  42.                             LcdWriteData(datas1[1]+'0');            
  43.                             }
  44.               }
  45. }</font></font></font>
复制代码

3.2 各程序模块

3.2.1 温度采集程序模块

使用DS18B20温度传感器进行测量,其中1引脚接地,2引脚接AT89C51的P3.7引脚,3引脚接电源。

图 4 温度采集模块

#include"temp.h"

void Ds18b20WriteByte(unsigned char dat)

{

              unsigned int i,j;

              for(j=0;j<8;j++)

              {

                            DSPORT=0;                                          //每写入一位数据之前先把总线拉低1us

                            i++;

                            DSPORT=dat&0x01; //然后写入一个数据,从最低位开始

                            i=6;

                            while(i--); //延时68us,持续时间最少60us

                            DSPORT=1;              //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值

                            dat>>=1;

              }

}

unsigned char Ds18b20ReadByte()

{

              unsigned char byte,bi;

              unsigned int i,j;            

              for(j=8;j>0;j--)

              {

                            DSPORT=0;//先将总线拉低1us

                            i++;

                            DSPORT=1;//然后释放总线

                            i++;

                            i++;//延时6us等待数据稳定

                            bi=DSPORT;              //读取数据,从最低位开始读取

                            /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/

                            byte=(byte>>1)|(bi<<7);                                                                                    

                            i=4;                            //读取完之后等待48us再接着读取下一个数

                            while(i--);

              }                                                      

              return byte;

}

void  Ds18b20ChangTemp()

{

              Ds18b20Init();

              Delay1ms(1);

              Ds18b20WriteByte(0xcc);                            //跳过ROM操作命令                           

              Ds18b20WriteByte(0x44);                  //温度转换命令

}

void  Ds18b20ReadTempCom()

{            

              Ds18b20Init();

              Delay1ms(1);

              Ds18b20WriteByte(0xcc);              //跳过ROM操作命令

              Ds18b20WriteByte(0xbe);              //发送读取温度命令

}

int Ds18b20ReadTemp()

{

              int temp=0;

              unsigned char tmh,tml;

              Ds18b20ChangTemp();                                                        //先写入转换命令

              Ds18b20ReadTempCom();                                          //然后等待转换完后发送读取温度命令

              tml=Ds18b20ReadByte();                            //读取温度值共16位,先读低字节

              tmh=Ds18b20ReadByte();                            //再读高字节

              temp=tmh;

              temp<<=8;

              temp|=tml;

              return temp;

}

3.2.2 液晶显示和声光报警程序模块

使用LM016L液晶进行显示,其中1引脚VSS接地,2引脚VDD和3引脚VEE接电源。4引脚RS接单片机AT89C51的P2.6引脚, 5引脚RW接单片机AT89C51的P2.5,引脚6 E接单片机AT89C51的P2.7引脚,7引脚到14引脚即D0到D7分别接P0.0到P0.7。

图 5 液晶显示模块
放置一个led-green和buzzer,接线如下。

图 6 报警模块

void LcdDisplay(int temp)               //lcd显示

{

                unsigned char i, datas[] = {0, 0, 0, 0, 0}; //定义数组

                            float tp;


                LcdWriteCom(0x80);                            //写地址 80表示初始地址

                            tp=temp;

                            temp=tp*0.0625*100+0.5;            

                            if((temp/100)>(SETTEMP-1))

                            {

                                          beep=0;

                            }

                            else

                            {

                            beep=1;

                            }

                            //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点

                            //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就

                            datas[1] = temp % 10000 / 1000;

                            datas[2] = temp % 1000 / 100;

                            datas[3] = temp % 100 / 10;

                            datas[4] = temp % 10;



                            str[0]=datas[1]+'0';

                            str[1]=datas[2]+'0';

                            str[2]='.';

                            str[3]=datas[3]+'0';

                            str[4]='T';

                            str[5]=SETTEMP/10+'0';

                            str[6]=SETTEMP%10+'0';

                            str[7]='U';

                            LcdWriteCom(0x80);                            //写地址 80表示初始地址

                            LcdWriteData('t');            

                            LcdWriteCom(0x81);                            //写地址 80表示初始地址

                            LcdWriteData('e');            

                            LcdWriteCom(0x82);                            //写地址 80表示初始地址

                            LcdWriteData('m');

                            LcdWriteCom(0x83);                            //写地址 80表示初始地址

                            LcdWriteData('p');            

                            LcdWriteCom(0x84);                            //写地址 80表示初始地址

                            LcdWriteData(':');                           

                            LcdWriteCom(0x85);                            //写地址 80表示初始地址

                            LcdWriteData('0'+datas[1]); //十位

                            LcdWriteCom(0x86);                            //写地址 80表示初始地址

                            LcdWriteData('0'+datas[2]); //个位

                            LcdWriteCom(0x87);                            //写地址 80表示初始地址

                            LcdWriteData('.');                             //显示 ‘.’

                            LcdWriteCom(0x88);                            //写地址 80表示初始地址

                            LcdWriteData('0'+datas[3]); //显示小数点

                            LcdWriteCom(0x89);                            //写地址 80表示初始地址

                            LcdWriteData('C'); //显示小数点

                            LcdWriteCom(0x80+0x40);                            //写地址 80表示初始地址

                            for(i=0;i<=8;i++)

                                                        {

                                                                      LcdWriteData(CNCHAR);

                                                        }

                            LcdWriteCom(0x80+0x40+13);

                            LcdWriteData('C');                           

//                            datas1[0]=SETTEMP/10;

//                            datas1[1]=SETTEMP%10;

//                            LcdWriteCom(0x80+0x40+9);

//                            LcdWriteData(datas1[0]+'0');            

//                            LcdWriteCom(0x80+0x40+10);

//                            LcdWriteData(datas1[1]+'0');            

                            LcdWriteCom(0x80+0x40+11);

                            LcdWriteData('.');            

                            LcdWriteCom(0x80+0x40+12);

                            LcdWriteData('0');            

}

3.2.4 串口通信程序模块

将AT89C51的TXD连接COMPIM的TXD, AT89C51的RXD连接COMPIM的RXD,实现数据的接受发送。

图 7 串口模块

              //串口配置

              SCON &= (uint8_t)((uint8_t)( ~( UART_MODE | UART_RX )));              //清SM0 SM1 REN

              SCON |= (uint8_t)( UART_8BAUDRATE_VOLATILE | UART_RX );


              //TIM1配置

              TMOD &= (uint8_t)((uint8_t)( ~TIM1_MODE ));

              TMOD |= TIM1_MODE_2;              //8位自动重装

              PCON = 0x00;

              TH1 = 0xFD;                                                        //波特率默认配置为9600

              TL1 = 0xFD;


              TI = 1;                                                                      //清发送标志                                                                                   

              TR1 = 1;                                                        //使能定时器

}

uint8_t drv_uart_rx_bytes( uint8_t* RxBuffer )

{

              uint8_t l_RxLength = 0;

              uint16_t l_UartRxTimOut = 0x7FFF;


              while( l_UartRxTimOut-- )                            //在超时范围内检测数据

              {

                            if( 0 != RI )                                                        //检测是否接收到数据

                            {

                                          RI = 0;                                                                      //清标志位                           

                                          *RxBuffer = SBUF;                            //读数据

                                          RxBuffer++;

                                          l_RxLength++;

                                          l_UartRxTimOut = 0x7FFF;//重置超时检测

                            }

              }

              return l_RxLength;                                          //等待超时,数据接收完成

}

4仿真测试分析

基本实现串口通信程序,实现当仪器通过串口接收到字符“A”时,仪器通过串口发送内容格式为“DD.DTDDU”的字符串,其中第1-4位“DD.D”为采集的温度,第5位为字符“T”,为温度标识,第6-7位“DD”为温度上限值,第8位为字符“U”,为温度上限值标识。

且AT89C51单片机双击加入hex文件,双击串口进行设置,如波特率,串口号,校验位等,使用虚拟串口软件虚拟串口线,用串口调试助手进行仿真调试。

图 8 仿真框图

5.结语

软件设计中,把程序按功能分模块的话能提高编程效率,把问题一一解决,同时使问题简单化。

总的来说,自己从这次独立的课程设计中收获了一些知识与经验,一些从书本中学之不来的东西,不是说理论无用,而这恰恰是在理论的土壤中开出的花朵,是在理论的肩膀望见的更宽广的道路!成功来之不易,自主动手动脑实践,小小的成果亦能带来硕大的喜悦!


完整的Word格式文档51黑下载地址:

单片机.docx (351.45 KB, 下载次数: 31)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:976016 发表于 2021-11-28 19:17 | 只看该作者
可惜只有word,谁能分享下工程文件吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表