1、 开放性试验 课 程 设 计 成绩评定表 设计课题 : 基于89C52的数字温度传感器设计 学院名称 : 电气工程学院 专业班级 : 小组成员: 指导教师 : 指导教师意见: 成绩:
2、 签名: 年 月 目录 一 系统概述 2 二 总体框图 3 三 硬件设计 3 3.1AT89C52简介 3 3.2 12864液晶简介 4 3.2.1液晶显示模块概述 4 3.2.2模块引脚说明 5 3.2.3接口时序 6 3.3数字温度传感器DS1820 7 3.4时钟芯片 9 四 软件设计 10 附录 程序及系统原理图 11 一 系统概述 本系统是以89C52单片机为控制器的
3、数字温度采集显示报警系统,可以实现对当前温度温度的实时采集并传送到12864液晶屏上显示,并可设置温度高低报警值,其中主要采用的芯片有AT89C52微控制器芯片,DS1302实时时钟芯片,DS18B20温度传感器,12864液晶显示芯片。其中温度传感器将当前的温度采集并送入微控制器中,再由微控制器将数据传递给12864液晶显示。 二 总体框图 三 硬件设计 3.1AT89C52简介 AT89C52是一种带8K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多
4、功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C52是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。 主要特性: ·与MCS-51 兼容 ·4K字节可编程闪烁存储器 ·寿命:1000写/擦循环 ·数据保留时间:10年 ·全静态工作:0Hz-24Hz ·三级程序存储器锁定 ·128*8位内部RAM ·32可编程I/O线 ·两个16位定时器/计数器 ·5个中断源 ·可编程串行通道 ·低功耗的闲置和掉电模式 ·片内振荡器和时钟电路 管脚说明: VCC:供电电压。 GND:接地。
5、P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。 P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。 P2口:P2口为一个内部上拉电阻的8
6、位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。 P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输
7、入。作为输入,由于外部下拉为低电平,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脚两个机器周期的高电
8、平时间。 3.2 12864液晶简介 3.2.1液晶显示模块概述 JM12864M-2汉字图形点阵液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。 主要技术参数和显示特性: 电源:VDD 3.3V~+5V(内置升压电路,无需负压); 显示内容:128列× 64行 显示颜色:黄绿 显示角度:6:00钟直视 LCD类型:STN 与MCU接口:8位或4位并行/3位串行 配置LED背光 多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等 二、外形尺寸 外观尺寸:93
9、×70×12.5mm 视域尺寸:73×39mm 外形尺寸图 外形尺寸 3.2.2模块引脚说明 128X64HZ 引脚说明 引脚号 引脚名称 方向 功能说明 1 VSS - 模块的电源地 2 VDD - 模块的电源正端 3 V0 - LCD驱动电压输入端 4 RS(CS) H/L 并行的指令/数据选择信号;串行的片选信号 5 R/W(SID) H/L 并行的读写选择信号;串行的数据口 6 E(CLK) H/L 并行的使能信号;串行的同步时钟 7 DB0 H/L 数据0 8 DB1 H/L 数据1 9 DB2
10、 H/L 数据2 10 DB3 H/L 数据3 11 DB4 H/L 数据4 12 DB5 H/L 数据5 13 DB6 H/L 数据6 14 DB7 H/L 数据7 15 PSB H/L 并/串行接口选择:H-并行;L-串行 16 NC 空脚 17 /RET H/L 复位 低电平有效 18 NC 空脚 19 LED_A (LED+5V) 背光源正极 20 LED_K (LED-OV) 背光源负极 逻辑工作电压(VDD):4.5~5.5V 电源地(GND):0V 工作温度(Ta):-10℃
11、 ~60℃(常温) / -20℃~70℃(宽温) 3.2.3接口时序 模块有并行和串行两种连接方法(时序如下): 8位并行连接时序图 MPU写资料到模块 MPU从模块读出资料 汉字显示坐标 X坐标 Line1 80H 81H 82H 83H 84H 85H 86H 87H Line2 90H 91H 92H 93H 94H 95H 96H 97H Line3 88H 89H 8AH 8BH 8CH 8DH 8EH 8FH Line4 98H 99H 9AH
12、9BH 9CH 9DH 9EH 9FH 3.3数字温度传感器DS1820 一 单线数字温度计DSl820介绍 DSl820数字温度计提供9位(二进制)温度读数指示器件的温度信息经过单线接口送 入DSl820或从DSl820送出因此从主机CPU到DSl820仅需一条线(和地线)DSl820的电源可以由数据线本身提供而不需要外部电源因为每一个DSl820在出厂时已经给定了唯一的序号因此任意多个DSl820可以存放在同一条单线总线上这允许在许多不同的地方放置温度敏感器件DSl820的测量范围从-55到+125增量值为0.5可在l s(典型值)内把温度变换成数字 每一个
13、DSl820包括一个唯一的64位长的序号该序号值存放在DSl820内部的ROM(只读存贮器)中开始8位是产品类型编码(DSl820编码均为10H)接着的48位是每个器件唯一的序号最后8位是前面56位的CRC(循环冗余校验)码DSl820中还有用于贮 存测得的温度值的两个8位存贮器RAM编号为0号和1号1号存贮器存放温度值的符号如果温度为负()则1号存贮器8位全为1否则全为00号存贮器用于存放温度值的补码LSB(最低位)的1表示0.5将存贮器中的二进制数求补再转换成十进制数并除以2就得到被测温度值(-550125)DSl820的引脚如图226l所示每只D51820都可以设置成两种供电方式即数据
14、总线供电方式和外部供电方式采取数据总线供电方式可以节省一根导线但完成温度测量的时间较长采取外部供电方式则多用一根导线但测量速度较快。 (1)初始化 时序见图2.25-2主机总线to时刻发送一复位脉冲(最短为480us的低电平信号)接着在tl时刻释放总线并进入接收状态DSl820在检测到总线的上升沿之后等待15-60us接着DS1820在t2时刻发出存在脉冲(低电平持续60-240 us)如图中虚线所示 (2)写时间隙 当主机总线t o时刻从高拉至低电平时就产生写时间隙见图2253图2254从to时刻开始15us之内应将所
15、需写的位送到总线上DSl820在t后15-60us间对总线采样若低电平写入的位是0见图2253若高电平写入的位是1见图2254连续写2位间的间隙应大于1us (3)读时间隙 见图2255主机总线to时刻从高拉至低电平时总线只须保持低电平l 7ts之后在t1时刻将总线拉高产生读时间隙读时间隙在t1时刻后t 2时刻前有效t z距to为15捍s也就是说t z时刻前主机必须完成读位并在t o后的60尸s一120 fzs内释放总线 3.4时钟芯片 DS1302 是DALLAS 公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31 字节静态RAM 通过简 单的串行接口与单片机进
16、行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天 数和闰年的天数可自动调整时钟操作可通过AM/PM 指示决定采用24 或12 小时格式DS1302 与单片机之 间能简单地采用同步串行的方式进行通信仅需用到三个口线1 RES 复位2 I/O 数据线3 SCLK 串行时钟时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信DS1302 工作时功耗很 低保持数据和时钟信息时功率小于1mW DS1302 是由DS1202 改进而来增加了以下的特性双电源管脚用于主电源和备份电源供应Vcc1 为可 编程涓流充电电源附加七个字节存储器它广泛应用于电话传真便携式仪器以及
17、电池供电的仪器仪表等 产品领域下面将主要的性能指标作一综合 1.实时时钟具有能计算2100 年之前的秒分时日日期星期月年的能力还有闰年调整的能力 2.31 8 位暂存数据存储RAM 3.串行 I/O 口方式使得管脚数量最少 4.宽范围工作电压2.0 5.5V 5.工作电流 2.0V 时,小于300nA 6.读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式 7.8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配 8.简单 3 线接口 9.与 TTL 兼容Vcc=5V 10.可选工业级温度范围-40 +85 四 软件设计 程
18、序流程图如图4-1表示 图4-1.程序流程图 程序采用模块化编程 模块化编程即把单个功能的子程序进行单独建立,并对其子程序做出自己的头文件,其函数在主函数中调用即可,且不影响其他模块。编写模块化程序,可阅读性强,可移植性高 附录 程序及系统原理图 温度传感器子函数 #include "18b20.h" #include "delay.h" void delay(unsigned int i) { while(i--); } Init_DS18B20(void) { unsigned char x=0; DQ=1; delay(8)
19、 DQ=0; delay(80); DQ=1; delay(14); x=DQ; delay(20); } /*********************************/ ReadOneChar(void) { unsigned char i=0; unsigned char dat=0; for(i=0;i<8;i++) { DQ=0; dat>>=1; DQ=1; if(DQ) dat|=0x80; delay(4); } return(dat); } /************
20、/ WriteOneChar(unsigned char dat) { unsigned char i=0; for(i=0;i<8;i++) { DQ=0; DQ=dat&0x01; delay(5); DQ=1; dat>>=1; } } /**********************************/ ReadTemperature(void) { unsigned char a=0; unsigned char b=0; unsigned int t=0;
21、 float tt=0; Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0x44); Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0xbe); a=ReadOneChar(); b=ReadOneChar(); t=b; t<<=8; t=t|a; tt=t*0.0625; t=tt*10+0.5; return(t); } /***************************/ #ifndef __18B20_H__
22、
#define __18B20_H__
#include
23、 "; uchar hanzi2[]="高报警: 22.0 "; uchar hanzi3[]="低报警: 18.0 "; void delay_ms(uchar a) { uint i,j; for(i=a;i>0;i--) for(j=6245;j>0;j--); } /************************************************/ /******************************* //在12m晶振时延时50us ************************
24、/ void delayus(uchar t) { uint i,j; for(i=t;i>0;i--) for(j=19;j>0;j--); } /********************************/ void write_com(uchar com) { rs=0; rw=0; e=0; lcd_dat_port=com; delayus(1); e=1; delayus(10); e=0; delayus(2); } /*****************************
25、/ void write_data(uchar dat) { rs=1; rw=0; e=0; lcd_dat_port=dat; delayus(1); e=1; delayus(10); e=0; delayus(2); } /********************************/ void init() { uchar i; delay_ms(2); write_com(0x30); delayus(4); write_com(0x30); delayus(4); write_co
26、m(0x0c); delayus(4); write_com(0x01); delayus(240); write_com(0x06); delayus(10); /******************/ write_com(0x80); delay_ms(1); for(i=0;i<9;i++) { write_data(hanzi0[i]); } write_com(0x90); delay_ms(1); for(i=0;i<9;i++) { write_data(hanzi1[i]); }
27、
write_com(0x88);
delay_ms(1);
for(i=0;i<16;i++)
{
write_data(hanzi2[i]);
}
write_com(0x98);
delay_ms(1);
for(i=0;i<16;i++)
{
write_data(hanzi3[i]);
}
delay_1ms(10);
}
#ifndef __LCD12864_H__
#define __LCD12864_H__
#include
28、define lcd_dat_port P0 sbit rs=P3^5; sbit e=P3^4; sbit rw=P3^6; void write_com(uchar com); void write_data(uchar dat); void delay_ms(uchar a); void delayus(uchar t); void init(); void lcd_char_write(uchar x_pos,y_pos,lcd_dat); #endif 延时函数 #include "delay.h" void delayshu(void)
29、 { int k; for(k=0;k<1000;k++); } /**********************/ void lcd_delay(uint ms) { uint i; while(ms--) { for(i=0;i<250;i++) {;} } } /***************************************/ /**********************************/ void delay_1ms(uchar x) { uchar i=0,j=0; for(i=0;i<
30、x;i++)
{
for(j=0;j<113;j++)
{;}
}
}
#ifndef __DELAY_H__
#define __DELAY_H__
#include
31、/******************************************************************** 函 数 名:RTInputByte() 功 能:实时时钟写入一字节 说 明:往DS1302写入1Byte数据 (内部函数) 入口参数:d 写入的数据 返 回 值:无 设 计:zhaojunjie 日 期:2002-03-19 修 改: 日 期: *************************************
32、/ 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; } } /*********************************************
33、 函 数 名:RTOutputByte() 功 能:实时时钟读取一字节 说 明:从DS1302读取1Byte数据 (内部函数) 入口参数:无 返 回 值:ACC 设 计:zhaojunjie 日 期:2002-03-19 修 改: 日 期: ***********************************************************************/ uchar RTOutpu
34、tByte(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() 功
35、能:往DS1302写入数据 说 明:先写地址,后写命令/数据 (内部函数) 调 用:RTInputByte() , RTOutputByte() 入口参数:ucAddr: DS1302地址, ucData: 要写的数据 返 回 值:无 设 计:zhaojunjie 日 期:2002-03-19 修 改: 日 期: ***********************************************************************/ void W
36、1302(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() 功
37、 能:读取DS1302某地址的数据 说 明:先写地址,后读命令/数据 (内部函数) 调 用:RTInputByte() , RTOutputByte() 入口参数:ucAddr: DS1302地址 返 回 值:ucData :读取的数据 设 计:zhaojunjie 日 期:2002-03-19 修 改: 日 期: ***********************************************************************/ uch
38、ar 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); } /******************************************
39、 函 数 名:Set1302() 功 能:设置初始时间 说 明:先写地址,后读命令/数据(寄存器多字节方式) 调 用:W1302() 入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年 7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B 返 回 值:无 设 计:zhaojunjie 日 期:2002-03-19 修 改:
40、 日 期: ***********************************************************************/ void Set1302(uchar *pClock) { uchar i; uchar ucAddr = 0x80; EA = 0; W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/ for(i =3; i>0; i--) { W1302(ucAddr,*pClock); /*
41、 秒 分 时 日 月 星期 年 */ pClock++; ucAddr +=2; } W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/ EA = 1; } /******************************************************************** 函 数 名:Get1302() 功 能:读取DS1302当前时间 说 明: 调 用:R1302() 入口参数:ucCurtime: 保存当前时间地
42、址。当前时间格式为: 秒 分 时 日 月 星期 年 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 返 回 值:无 设 计:zhaojunjie 日 期:2002-03-19 修 改: 日 期: ***********************************************************************/ void Get1302(uchar ucC
43、urtime[])
{
uchar i;
uchar ucAddr = 0x81;
EA = 0;
for (i=0; i<3; i++)
{
ucCurtime[i] = R1302(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */
ucAddr += 2;
}
EA = 1;
}
#ifndef __DS1302_H__
#define __DS1302_H__
#include
44、efine nop() _nop_() sbit T_CLK = P3^2; /*实时时钟时钟线引脚 */ sbit T_IO = P2^4; /*实时时钟数据线引脚 */ sbit T_RST = P3^3; /*实时时钟复位线引脚 */ sbit ACC0 = ACC^0; sbit ACC7 = ACC^7; void RTInputByte(uchar d); uchar RTOutputByte(void); void W1302(uchar ucAddr, uchar ucDa); uchar R1302(uchar ucAddr); vo
45、id Set1302(uchar *pClock);
void Get1302(uchar ucCurtime[]);
#endif
主函数
#include "lcd12864.h"
#include "18b20.h"
#include "delay.h"
#include "ds1302.h"
#include
46、3]={0x00,0x00,0x09};/*格式为: 秒 分 时 日 月 星期 年 */ sbit WELA=P2^7; sbit beep=P2^3; uchar shuzi[]={"0123456789"}; uchar dian[]={"."}; uchar du[]={"c"}; void main() { uint i=0; P0=0XFF; delayshu(); WELA=1; delayshu(); WELA=0; Set1302(time_data_buff); init(); lcd_delay(10);
47、 while(1) { Get1302(time_data_buff); i=ReadTemperature(); delay_1ms(10); if(i>220|i<180)//报警温度,要乘以10 { beep=0; delay_1ms(200); beep=1; } //以下显示时间 write_com(0x83); write_data(mun_to_char[time_data_buff[2]/0x10]); delay_ms(1); write_data(mun_to_char[ti
48、me_data_buff[2]%0x10]); delay_ms(1); write_data(xiegang[0]); write_data(mun_to_char[time_data_buff[1]/0x10]); delay_ms(1); write_data(mun_to_char[time_data_buff[1]%0x10]); delay_ms(1); write_data(xiegang[0]); write_data(mun_to_char[time_data_buff[0]/0x10]); delay_ms(1);
49、 write_data(mun_to_char[time_data_buff[0]%0x10]); delay_ms(1); //以下显示温度 write_com(0x93); delay_ms(1); write_data(shuzi[i/100]); delay_1ms(10); write_data(shuzi[i%100/10]); delay_1ms(10); write_data(dian[0]); delay_1ms(10); write_data(shuzi[i%10]); delay_1ms(10);
50、 write_data(0xa1);//两行显示温度符号 write_data(0xe3);// write_data(du[0]); write_com(0x9e); write_data(0xa1); write_data(0xe3); write_data(du[0]); write_com(0x8e); write_data(0xa1); write_data(0xe3); write_data(du[0]); } } 系统原理图 1. 基于C8051F单片机直流电动机反馈控制系统






