职场文秘网

首页 > 演讲范文 > 开业致辞 / 正文

单片机课程设计报告基于单片机的温控系统

2020-11-09 06:01:06

 职业学院 机械与电子工程学院 基于单片机温控系统课程设计报告 班

 级

  电信班

 学生姓名

 学

 号

 指导教师

 时

 间

  2011

  目录

  摘

 要 I 1系统方案设计及组成 I 2系统设计 1 2.1温度传感器的工作原理与单片机的连接 1 2.2 DS1302原理及管脚 2 2.3单片机与报警电路 3 2.4显示电路 3 2.41基本操作时序 4 3系统软件设计 4

  摘

 要

 本课题主要介绍基于AT89C51单片机和DS18B20数字温度传感器的温度测量系统。该系统利用AT89C51单片机分别采集各个温度点的温度,实现温度显示、报警等功能以及用DS1302时钟芯片在液晶显示当前时间日期。直观,实用。它以AT89C51单片机为主控制芯片,采用数字温度传感器DS18B20实现温度的检测,测量精度可以达到0.5℃。该系统采用了1602显示模块,形象直观的显示测出的温度值。基于AT89C51单片机的单总线温度测控系统具有硬件组成简单、读数方便、精度高、测温范围广等特点,在实际工程中得到广泛应用。

 关键词:温度传感器;单片机;温度控制;DS1302;

 LCD

 1系统方案设计及组成 该方案使用了AT89C51单片机作为控制核心,以智能温度传感器DS18B20为温度测量元件,对各点温度进行检测,设置温度上下限,超过其温度值就报警。以及用DS1302时钟芯片在液晶显示当前时间日期。显示电路采用1602液晶模块显示,使用三极管,电阻和蜂鸣器组成的报警电路,按钮处理模块等。具有温度控制,实时时钟,报警等功能。

  89C52CPU

 控制模块 按键处理模块 温度采集模块

 报警电路

  LCD显示模块 DS1302时钟 采集模块

  图2-1温度控制系统方案框

  2系统设计 2.1温度传感器的工作原理与单片机的连接 温度传感器的单总线(1-Wire)与单片机的P2.7连接,P2.7是单片机的高位地址线。P2端口是一个带内部上拉电阻的8位双向I/O,其输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对该端口写“1”,可通过内部上拉电阻将其端口拉至高电平,此时可作为输入口使用,这是因为内部存在上拉电阻,某一引脚被外部信号拉低时会输出一个电流。

 如1所示:DS18B20与单片机的接口电路非常简单。DS18B20只有三个引脚,一个接地,一个接电源,一个数字输入输出引脚接单片机I/O口,电源与数字输入输出脚间需要接一个4.7K的电阻。

  图1温度传感器与单片机的连接图 DS18B20的工作原理 DS18B20的工作过程 a.初始化:

 DS18B20所有的数据交换都由一个初始化序列开始。由主机发出的复位脉冲和跟在其后的由DS18B20发出的应答脉冲构成。当DS18B20发出响应主机的应答脉冲时,即向主机表明它已处在总线上并且准备工作。

 b. ROM命令:

 ROM命令通过每个器件64-bit的ROM码,使主机指定某一特定器件(如果有多个器件挂在总线上)与之进行通信。DS18B20的ROM如表3-6所示,每个ROM命令都是8 bit长。

 c. 功能命令:

 主机通过功能命令对DS18B20进行读/写Scratchpad存储器,或者启动温度转换。

 DS18B20的信号方式 DS18B20采用严格的单总线通信协议,以保证数据的完整性。该协议定义了几种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。除了应答脉冲所有这些信号都由主机发出同步信号。总线上传输的所有数据和命令都是以字节的低位在前。

 a.初始化序列:复位脉冲和应答脉冲 b.读和写时序 在写时序期间,主机向DS18B20写入指令;而在读时序期间,主机读入来自DS18B20的指令。在每一个时序,总线只能传输一位数据。读/写时序如图3-4所示。

 写时序 存在两种写时序:“写1”和“写0”。主机在写1时序向DS18B20写入逻辑1,而在写0时序向DS18B20写入逻辑0。所有写时序至少需要60µs,且在两次写时序之间至少需要1µs的恢复时间。两种写时序均以主机拉低总线开始。

 读时序 DS18B20只能在主机发出读时序时才能向主机传送数据。所以主机在发出读数据命令后,必须马上产生读时序,以便DS18B20能够传送数据。所有读时序至少60µs,且在两次独立的读时序之间至少需要1µs的恢复时间。

 2.2 DS1302原理及管脚 1、DS1302引脚排列:如下图

 2、 DS1302的控制字节

   DS1302 的控制字如下图所示。

  控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。   3、数据输入输出(I/O)

   在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

 2.3单片机与报警电路 系统中的报警电路是由三极管,蜂鸣器,发光二极管和限流电阻组成,并与单片机的P2.3端口连接。当温度超过预设的最高温度或最低温度时,蜂鸣器发出响声。

  报警电路

 2.4显示电路 采用技术成熟,价格便宜的1602液晶显示器做为输出显示。本次设计使用的1602液晶显示器为5V电压驱动,带背光,可显示两行,每行16个字符,不能显示汉字,内置128个字符的ASCII字符集字库,只有并行接口,无串行接口。

 2.41基本操作时序 读状态

 输入:RS=L, R/W=H,E=H

  输出:D0~D7=状态字。

 读数据

 输入:RS=H, R/W=H,E=H

  输出:无。

 写指令

 输入:RS=L, R/W=L,D0~D7=指令码,E=高脉冲

 输出:D0~D7=数据。

 写数据

 输入:RS=H, R/W=L, ,D0~D7=数据,E=高脉冲

  输出:无

 2.5 按键处理模块

 按键处理可以调整当前准确时间,日期,可以调整所需要监控温度的上下限,达到温度的上下限是,蜂鸣器报警,如图所示就是按键的分布图

 还有在硬件上安装了两个继电器,当温度报警时,触发继电器控制外围电路

 3系统软件设计 本次软件是采用模块化编程,就是把程序中的函数,定义等代码进行分类,实际上是两个文件.C与.h,它们的文件名通常是相同的,.h文件用于声明与定义;.C文件用于函数的实现。采用模块化编程的好处是:

 1、 整个工程脉络清晰,代码规划合理。

 2、 程序模块化,有利于代码的积累,重复使用,快速建立工程 3、 可以将程序模块编译未LIB库文件,有利于源代码的保密。

 3.1主程序及流程图

 _MAIN_H_

 #ifndef _MAIN_H_

 #define _MAIN_H_

  #include “reg52.h“

 #include “INTRINS.H“

 #include “STRING.H“

 #include “Delay.h“

 #include “Lcd.h“

 #include “DS1302.h“

 #include “DS18B20.h“

 #include “Key.h“

 #include “DispMeau.h“

  #define uchar unsigned char

 #define uint unsigned int

 extern char DispFlag;

  extern uint

 LTemper;

 extern uint

 HTemper;

 extern uchar Temper[10];

 extern uchar Time[10];

 extern uchar Date[10];

 #endif

 _MAIN_C_

 #include “Main.h“

 char

 DispFlag;

 //允许显示标志 0:不允许 ,1:允许 uchar Temper[10]=““;

 //保存温度数据 uchar Time[10]=“

 :

 :

 “; //保存时分秒数据 uchar Date[10]=“

 “; //保存年月日数据

 uint

 LTemper=2000; uint

 HTemper=5000; //uchar TimeStatus=0;

 sbit bell=P2^3; sbit led1=P2^4; sbit led2=P2^5; sbit led3=P2^6;

 void WarnDisp(uint tpTmp) {

 if(tpTmp<=LTemper)

 {

  led1=1;

  led2=0;

  led3=0;

  bell=0;

 }

 else if(tpTmp>=HTemper)

 {

  led1=0;

  led2=0;

  led3=1;

  bell=0;

 }

 else

 {

  led1=0;

  led2=1;

  led3=0;

  bell=1;

 } } void main() {

 uint Tmp=0;

 Init1302();

  //初始化

 DS1302

  Int_lcd();

 //初始化 lcd

  ET0=1;

 // 时间中断0 允许中断

 EA=1;

 // 中断 允许

 TMOD=0x01;

  // 使用 时间0 记数

 TH0=(65536-15536)/256;

  //

  TL0=(65536-15536)%256;

  //

 TR0=1;

 // 允许记数0记数

  DispFlag=0;

  //不允许显示

 led1=0;

 led2=0;

 led3=0;

 bell=1;

 Tmp=readtmp();

  //取温度

 delay(40000);

 Tmp=readtmp();

  //取温度

 delay(40000);

 //TimeStatus = 0;

 while(1)

 {

  if(DispFlag==0)

  {

 //if(TimeStatus==0)

  //不在时间调整状态

 {

  DealTime(Time , Date); //获取需要显示的时间数据

 }

 DealKey();

 //按键处理

 Tmp=readtmp();

  //取温度

  WarnDisp(Tmp);

  //警报指示

  DealTemper(Tmp, Temper);

 //将温度值转化成显示数据

 DispFlag=1;

  //允许显示

  }

 } } void t(void) interrupt 1 using 0

 {

  TH0=(65536-15530)/256;

  TL0=(65536-15530)%256;

  if(DispFlag==1)

 {

 ScrDisp(0x80,Date);

  //显示 日期(位置,数据)

 ScrDisp(0xc0,Time);

 //显示 时间

  ScrDisp(0x89,Temper);

 //显示 温度

  DispFlag=0;

 } }

 3.2 各子程序及流程图 一、DS1302

 _DS1302_H_

 #ifndef _DS1302_H_

 #define _DS1302_H_

  #include “Main.h“

 void v_WTInputByte(unsigned char ucDa);

 unsigned char uc_RTOutputByte(void);

 void v_W1302(unsigned char ucAddr, unsigned char ucDa);

  unsigned char uc_R1302(unsigned char ucAddr);

 void Init1302(void);

 void DealTime(unsigned char *tpTime , unsigned char *tpDate);

 void SaveDate(unsigned char *tpDate);

 void SaveTime(unsigned char *tpTime);

  #endif

 _DS1302_C_

 #include “Main.h“

 sbit T_RST = P2^0; /*实时时钟复位线引脚 */ sbit T_IO

 = P2^1; /*实时时钟数据线引脚 */ sbit T_CLK = P2^2; /*实时时钟时钟线引脚 */

 sbit ACC0=ACC^0; sbit ACC7=ACC^7;

  /********************************************************************

 * * 名称: v_RTInputByte * 说明:

 * 功能: 往DS1302写入1Byte数据 * 调用: * 输入: ucDa 写入的数据

 * 返回值: 无 ***********************************************/ void v_WTInputByte(uchar ucDa)

 {

  uchar i;

 ACC= ucDa;

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

 {

  T_IO = ACC0; //*相当于汇编中的 RRC

 T_CLK = 1;

 T_CLK = 0;

  ACC =ACC>> 1;

  }

 } /***********************************************

 * * 名称: uchar uc_RTOutputByte * 说明:

 * 功能: 从DS1302读取1Byte数据 * 调用:

 * 输入:

 * 返回值: ACC ***********************************************/ uchar uc_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);

 } /***********************************************

 * * 名称: v_W1302 * 说明: 先写地址,后写命令/数据 * 功能: 往DS1302写入数据 * 调用: v_RTInputByte()

 * 输入: ucAddr: DS1302地址, ucDa: 要写的数据 * 返回值: 无 ***********************************************/ void v_W1302(uchar ucAddr, uchar ucDa) {

 T_RST = 0;

 T_CLK = 0;

 T_RST = 1;

 v_WTInputByte(ucAddr);

 /* 地址,命令 */

 v_WTInputByte(ucDa);

 /* 写1Byte数据*/

 T_CLK = 1;

 T_RST =0; }

 /*********************************************** 名称: uc_R1302 * 说明: 先写地址,后读命令/数据 * 功能: 读取DS1302某地址的数据 * 调用: v_RTInputByte() , uc_RTOutputByte() * 输入: ucAddr: DS1302地址 * 返回值: ucDa :读取的数据 *********************************************/ uchar uc_R1302(uchar ucAddr) {

 uchar ucDa;

 T_RST = 0;

 T_CLK = 0;

 T_RST = 1;

 v_WTInputByte(ucAddr);

 /* 地址,命令 */

 ucDa = uc_RTOutputByte();

  /* 读1Byte数据 */

 T_CLK = 1;

 T_RST =0;

 return(ucDa); }

 /*********************************************** * 名称: Init1302

 * 说明:

  * 功能: 初始化DS1302

  * 调用:

  * 输入:

  * 返回值: 无

 ***********************************************/ void Init1302(void) {

  v_W1302(0x8e,0x00);

 //控制写入WP=0

 v_W1302(0x90,0xa5); } //+48是为了转换为ACSII

 码 void DealTime(uchar *tpTime , uchar *tpDate) {

 uchar d;

 //时间处理

 tpTime[8] = 0x00;

 //数组结束符 '\0'

 tpDate[8] = 0x00;

 //数组结束符 '\0'

  d=uc_R1302(0x81);

  //读取时间 秒

  tpTime[6]=(d>>4&0x0f)+48; //处理十秒

 tpTime[7]=(d&0x0f)+48;

 //处理 秒

  d=uc_R1302(0x83);

  //读取时间 秒

  tpTime[3]=(d>>4&0x0f)+48; //处理十分

 tpTime[4]=(d&0x0f)+48;

 //处理 分

  d=uc_R1302(0x85);

  //读取 时

  tpTime[0]=(d>>4&0x0f)+48; //处理十时

  tpTime[1]=(d&0x0f)+48;

 //处理 时

  d=uc_R1302(0x8D);

  //读取 年

  tpDate[0]=(d>>4&0x0f)+48; //处理十年

 tpDate[1]=(d&0x0f)+48;

 //处理 年

  d=uc_R1302(0x89);

  //读取 月

  tpDate[3]=(d>>4&0x0f)+48; //处理十月

 tpDate[4]=(d&0x0f)+48;

 //处理 月

  d=uc_R1302(0x87);

  //读取 日

 tpDate[6]=(d>>4&0x0f)+48; //处理十日

 tpDate[7]=(d&0x0f)+48;

 //处理 日

 }

 void SaveDate(uchar *tpDate) {

 uchar y,m,d;

  y = (((tpDate[0]-48)<<4)&0xf0)+(tpDate[1]-48);

 m = (((tpDate[3]-48)<<4)&0xf0)+(tpDate[4]-48);

 d = (((tpDate[6]-48)<<4)&0xf0)+(tpDate[7]-48);

  v_W1302(0x8e,0x00);

 //控制写入WP=0

 v_W1302(0x90,0xa5);

  v_W1302(0x86,d);

 //日

 v_W1302(0x88,m);

 //月

  v_W1302(0x8c,y);

 //年

 }

 void SaveTime(uchar *tpTime) {

 uchar h,m,s;

  h = (((tpTime[0]-48)<<4)&0xf0)+(tpTime[1]-48);

 m = (((tpTime[3]-48)<<4)&0xf0)+(tpTime[4]-48);

 s = (((tpTime[6]-48)<<4)&0xf0)+(tpTime[7]-48);

  v_W1302(0x8e,0x00);

 //控制写入WP=0

 v_W1302(0x90,0xa5);

  v_W1302(0x80,s);

 //秒

 v_W1302(0x82,m);

 //分

 v_W1302(0x84,h);

 //时

  //delay(100); }

 二、DS18B20

 DS18B20读取温度过程 _DS18B20_H_

  #define _DS18B20_H_

  void reset(void);

 unsigned char readbyte(void);

 void writebyte(unsigned char indata);

 unsigned int readtmp(void);

 void DealTemper(unsigned int tpTemper, unsigned char *tpStr);

 #endif

 _DS18B20_C

 #include “Main.h“ sbit DQ=P3^7;

 /******************复位********************/ void reset(void) {

  uchar flag=0;

  DQ=1;

  delay_10us(1);

  DQ=0;

  delay_10us(70);

 //至少延时22us

  DQ=1;

  delay_10us(8);

  flag=DQ;

  delay_10us(15); }

 /****************读一字节*********************/ uchar readbyte(void) {

 uchar i,outdata=0;

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

  {

 DQ=1;

 delay_10us(1);

 DQ=0;

 outdata>>=1;

 //必须在15us内读取

 DQ=1;

 if(DQ)

  outdata|=0x80;

 delay_10us(4);

 }

  return(outdata); }

 /*****************写一字节********************/ void writebyte(uchar indata) {

  uchar i;

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

  {

  DQ=1;

  delay_10us(1);

  DQ=0;

  DQ=indata&0x01;

  //必须在15us内写入

  delay_10us(5);

  DQ=1;

  indata>>=1;

  }

  delay_10us(4); }

 /****************读温度***********************/ uint readtmp(void) {

 uint tmp;

 uchar tl,th,temp,temp1;

 reset();

 writebyte(0xcc); // 跳过序列号

 writebyte(0x44); // 启动温度转换

 reset();

 writebyte(0xCC);

 writebyte(0xBE); //读9个寄存器,前两个为温度

 tl=readbyte();

  //低位

 th=readbyte();

  //高位

 temp=tl&0x0f;

 //取低四位

 temp=temp*6.25;

 //小数部分

 tl>>=4;

 th<<=4;

 temp1=tl|th;

 //整数部分

 tmp=temp1*100+temp;

 //四位数,高两位为整数,低两位为小数

 delay(200);

 return (tmp); }

 /******************************************* 功能: 温度数据处理

 输入:

 uint tpTempe : 温度值 高字节为温度整位,低字节为温度小数位 uchar *tpStr : 把整形数据转化为显示数据输出:

 uchar *tpStr: 把整形数据转化为显示数据,并返回

 返回:无

 ***********************************************/ void DealTemper(uint tpTemper, uchar *tpStr) {

 tpStr[7] = 0x00;

 //数组结束符 '\0'

 tpStr[6] = 'C';

 tpStr[5] = 0xdf;

 //'度' 符号

  tpStr[4]=tpTemper%10+48;

 //取个位

 小数位第二位

  tpTemper/=10;

 tpStr[3]=tpTemper%10+48;

 //取十位

 小数位第一位

  tpStr[2]='.';

 //小数点

 tpTemper/=10;

 tpStr[1]=tpTemper%10+48;

 //取百位

  个位

 tpStr[0]=tpTemper/10+48;

 //取千位

  十位

 }

 三、LCD1602 _LCD_H_

 #ifndef _LCD_H_

 #define _LCD_H_

  void Int_lcd(void);

 //初始化

 unsigned char lcd_r_start(void);

 void lcd_w_cmd(unsigned char com);

 void lcd_w_dat(unsigned char dat);

 #endif

 _LCD_C_

 #include “Main.h“

 sbit RS=P3^4; sbit RW=P3^5; sbit E=P3^6;

 void Int_lcd(void) {

 lcd_w_cmd(0x3c);

  //设置工作方式

 lcd_w_cmd(0x0c);

 //设置光标

 lcd_w_cmd(0x01);

 //设置清屏

  lcd_w_cmd(0x06);

  //设置输入方式

 lcd_w_cmd(0x00);

 //设置初始显示位置

 }

 unsigned char lcd_r_start(void) {

 unsigned char s;

 RW=1;

 //RW=1,RS=0,读lcd状态

 delay1();

 RS=0;

 delay1();

 E=1;

 //E端时序

 从低到高再到低

  delay1();

 s=P1;

 //从lcd的数据口读状态

 E=0;

 delay1();

 RW=0;

 delay1();

 return(s);

 //返回读取的lcd状态字

 }

 void lcd_w_cmd(unsigned char com) {

 unsigned char i;

 do

 //查lcd忙操作

  {

  i=lcd_r_start();

 //调用读状态字函数

 i=i&0x80;

  //“与“操作屏蔽掉低7位

 delay(2);

 }

 while(i!=0);

 //lcd忙,继续查询,否则退出循环

  RW=0;

 delay1();

 RS=0;

 //RW=1,RS=0,写lcd命令字

 delay1();

 E=1;

  //E端时序

 delay1();

 P1=com; //将com中的命令字写入lcd数据口

 delay1();

 E=0;

 delay1();

 RW=1;

 delay(255); }

 void lcd_w_dat(unsigned char dat) {

 unsigned char i;

 do

  //查忙操作

 {

  i=lcd_r_start();

 //调用读状态字函数

  i=i&0x80;

 //“与“操作屏蔽掉低7位

  delay(2);

 }

 while(i!=0);

 RW=0;

 delay1();

 RS=1;

 //RW=1,RS=0,写lcd命令字

 delay1();

 E=1;

  //E端时序

 delay1();

 P1=dat; //将dat中的命令字写入lcd数据口

 delay1();

 E=0;

 delay1();

 RW=1;

 delay(255); }

  四.延时函数

 _DELAY_H

 #ifndef _DELAY_H_

 #define _DELAY_H_

  void delay_10us(unsigned int time);

 void delay(unsigned int t);

 void delay1(void);

 #endif

 _DELAY_C

 #include “Main.h“

 /******************10us延时***************************** 名称:

 delay_10us 功能:

 延时10us

  1---27us 2---37us 3---45us 4---56us 5---66us 6---76us 7---86us 10--115us 100---1ms **********************************************/ } void delay_10us(unsigned int time)

  {

 while(time--); }

 void delay(unsigned int t) {

 unsigned int n;

 n=0;

 while(n<t) n++;

 return;

 void delay1(void) {

 _nop_();

 _nop_();

 _nop_(); }

 五.按键控制

 _KEY_H_

 #ifndef _KEY_H_

 #define _KEY_H_

  unsigned char

 DealKey(void);

 #endif

 _KEY_C_

 #include “Main.h“

 sbit key1=P2^7;

 //调整时间 时 或 年 sbit key2=P3^0;

 //调整时间 分 或 月 sbit key3=P3^1;

 //保存时间 秒 或 日 sbit key4=P3^2;

 //确定保存/或进入菜单选择模式 sbit key5=P3^3;

 //取消

 uchar TimeStatus = 0;

 uchar GetKey(void) {

 if (0==key1)

 {

  if(TimeStatus == 0) return 0;

  delay(100);

 if (0==key1)

  {

 while(1)

 {

  if(1==key1)

  {

 delay(50);

 if(1==key1) break;

  }

 }

 return 1;

  }

 }

 else if (0==key2)

 {

  if(TimeStatus == 0) return 0;

  delay(100);

 if (0==key2)

  {

 while(1)

 {

  if(1==key2)

  {

 delay(50);

 if(1==key2) break;

  }

 }

 return 2;

  }

 }

 else if (0==key3)

 {

  if(TimeStatus == 0) return 0;

  delay(100);

 if (0==key3)

  {

 while(1)

 {

  if(1==key3)

  {

 delay(50);

 if(1==key3) break;

  }

 }

 return 3;

  }

 }

 else if (0==key4)

 {

  delay(100);

 if (0==key4)

  {

 while(1)

 {

  if(1==key4)

  {

 delay(50);

 if(1==key4) break;

  }

 }

 return 4;

  }

 }

 else if (0==key5)

 {

  delay(100);

 if (0==key5)

  {

 while(1)

 {

  if(1==key5)

  {

 delay(50);

 if(1==key5) break;

  }

 }

 return 5;

  }

 }

  return 0; }

 uchar SetDate(uchar *tpDate) {

 uchar DispFlag=0;

  ClrScr();

 DispSetDate(0x80);

 ScrDisp(0xc0,tpDate);

 while(1)

 {

  switch(GetKey())

  {

 case 0:

  break;

 case 1:

  //调整年

  if(tpDate[0]=='9')

  {

 if(tpDate[1]<'9')

 {

  tpDate[1]++;

 }

 else

 {

  tpDate[0] = '0';

  tpDate[1] = '0';

 }

  }

  else

  {

 if(tpDate[1]<'9')

 {

  tpDate[1]++;

 }

 else

 {

  tpDate[0]++;

  tpDate[1] = '0';

  }

  }

  DispFlag = 1;

  break;

 case 2:

  //调整月

  if (tpDate[3]<'1')

 {

  tpDate[4]++;

  if(tpDate[4]>'9')

  {

 tpDate[3]++;

 tpDate[4]='0';

  }

 }

 else

  {

  if (tpDate[3]=='1')

  {

 if(tpDate[4]<='1')

 {

  tpDate[4]++;

 }

 else

 {

  tpDate[3]='0';

  tpDate[4]='0';

 }

  }

  else

 {

 tpDate[3]='0';

 tpDate[4]='0';

 }

 }

 DispFlag = 1;

  break;

 case 3:

  //调整日

  if(tpDate[6]<'3')

  {

 tpDate[7]++;

 if(tpDate[7]>'9')

 {

  tpDate[6]++;

  tpDate[7]='0';

 }

  }

  else

  {

 if(tpDate[6]>='3')

 {

  if(tpDate[7]<'1')

  {

 tpDate[7]++;

  }

  else

  {

 tpDate[6]='0';

 tpDate[7]='0';

  }

 }

  }

 DispFlag = 1;

  break;

 case 4:

  SaveDate(tpDate);

  return 4;

 //保存时间

 break;

 case 5:

  return 5;

 //取消

  break;

 default:

  break;

  }

 if(DispFlag==1)

  {

 DispFlag = 0;

 ScrDisp(0xc0,tpDate);

  }

 } }

 uchar SetTime(uchar *tpTime) {

 uchar DispFlag=0;

  ClrScr();

 DispSetTime(0x80);

 ScrDisp(0xc0,tpTime);

 while(1)

 {

  switch(GetKey())

  {

 case 0:

  break;

 case 1:

  //调整时间 时 位

  if(tpTime[0]>='2')

  {

 if(tpTime[1]<'3')

 {

  tpTime[1]++;

 }

 else

 {

  tpTime[0] = '0';

  tpTime[1] = '0';

 }

  }

  else

  {

 if(tpTime[1]<'9')

 {

  tpTime[1]++;

 }

 else

 {

  tpTime[0]++;

  tpTime[1] = '0';

  }

  }

  DispFlag = 1;

  break;

 case 2:

  //调整时间 分 位

  if(tpTime[4]<'9')

  {

 tpTime[4]++;

  }

  else

  {

 if(tpTime[3]<'5')

 {

  tpTime[3]++;

  tpTime[4] = '0';

 }

 else

 {

  tpTime[3] = '0';

  tpTime[4] = '0';

  }

  }

  DispFlag = 1;

  break;

 case 3:

  if(tpTime[7]<'9')

  {

 tpTime[7]++;

  }

  else

  {

 if(tpTime[6]<'5')

 {

  tpTime[6]++;

  tpTime[7] = '0';

 }

 else

 {

  tpTime[6] = '0';

  tpTime[7] = '0';

  }

  }

  DispFlag = 1;

  break;

 case 4:

  SaveTime(tpTime);

  return 4;

 //保存时间

 break;

 case 5:

  return 5;

 //取消

  break;

 default:

  break;

  }

 if(DispFlag==1)

  {

 DispFlag = 0;

 ScrDisp(0xc0,tpTime);

  }

 } }

 uchar SetTMP(uchar LHmode,uint *tpTEMP) {

 uchar DispFlag=0;

 uchar tpTMP[10];

 uint

 tpTemper=0;

  ClrScr();

 switch(LHmode)

 {

  case 1:

 DispSetLTMP(0x80);

 break;

  case 2:

  default:

 DispSetHTMP(0x80);

 break;

 }

  DealTemper(tpTemper,tpTMP);

 ScrDisp(0xc0,tpTMP);

  while(1)

 {

  switch(GetKey())

  {

 case 0:

  break;

 case 1:

  //调整温度 整数 位

  if(tpTemper<10000) tpTemper += 100;

  else

 tpTemper

 = tpTemper%100;

  DispFlag = 1;

  break;

 case 2:

 //调整温度 小数 位

  if(tpTemper%100<99) tpTemper ++;

  else

  tpTemper

 = tpTemper/100*100;

  DispFlag = 1;

  break;

 case 3:

  break;

 case 4:

  *tpTEMP = tpTemper;

  return 1;

 //保存时间

 break;

 case 5:

  return 0;

 //取消

  break;

 default:

  break;

  }

 if(DispFlag==1)

  {

 DispFlag = 0;

 DealTemper(tpTemper,tpTMP);

 ScrDisp(0xc0,tpTMP);

  }

 }

 return 0; }

  uchar DealKey(void) {

 uchar MenuDeep=0;

  while(1)

 {

  switch(GetKey())

  {

 case 0:

  //TimeStatus = 0;

  break;

 case 1:

 //向上移动光标

 if(TimeStatus == 0) break;

  if(MenuDeep>0)

  {

 MenuDeep--;

 DispMeau(MenuDeep);

  }

  break;

 case 2:

 //向下移动光标

  if(TimeStatus == 0) break;

  if(MenuDeep<3)

  {

 MenuDeep++;

 DispMeau(MenuDeep);

  }

  break;

 case 3:

  break;

 case 4:

 //确定

  if(TimeStatus == 1)

  {

 switch(MenuDeep)

 {

  case 0:

 SetDate(Date);

 break;

  case 1:

 SetTime(Time);

 break;

  case 2:

  SetTMP(1,&LTemper);

 break;

  case 3:

 SetTMP(2,&HTemper);

 break;

 }

 TimeStatus = 0;

  }

  else

  {

 DispMeau(MenuDeep);

 TimeStatus = 1;

  }

  break;

 case 5:

 //取消

  TimeStatus = 0;

  break;

 default:

  break;

  }

 if(TimeStatus == 0) return 0;

 }

 return 0; }

  六.菜单显示

 功能:把菜单显示出来,人性化,易操作 _DISPMEAU_H_

 #ifndef _DISPMEAU_H_

 #define _DISPMEAU_H_

  void ScrDisp(unsigned char tpAddr , unsigned char

 *tpStr);

 void DispSetDate(unsigned char tpAddr);

 void DispSetTime(unsigned char tpAddr);

 void DispSetLTMP(unsigned char tpAddr);

 void DispSetHTMP(unsigned char tpAddr);

 void DispCursor(unsigned char tpAddr);

 void DispMeau(unsigned char tpDeep);

 void ClrScr(void);

 #endif

 _DISPMEAU_C_

 #include “Main.h“

 /******************************

 功能:把tpStr数组数据在tpAddr位置开始显示

 输入参数:

  uchar tpAddr : 显示起始位置

  uchar *tpStr : 显示内容

 输出:

  无

 返回:

 空 ************************************/ void ScrDisp(uchar tpAddr , uchar *tpStr) {

  uchar i,len;

  len = strlen((char*)tpStr);

  //获取显示内容字节数

 lcd_w_cmd(tpAddr);

  //设置显示位置

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

  //显示字符串

 {

  lcd_w_dat(tpStr[i]);

 } }

 void ClrScr(void)

 //清除屏幕 {

 ScrDisp(0x80,“

 “);

 ScrDisp(0xc0,“

 “);

 }

 void DispSetDate(uchar tpAddr) {

 ScrDisp(tpAddr,“Set Date

 “);

 }

 void DispSetTime(uchar tpAddr) {

 ScrDisp(tpAddr,“Set Time

 “);

 }

 void DispSetLTMP(uchar tpAddr) {

 ScrDisp(tpAddr,“Set Low

 TMP

 “);

 }

 void DispSetHTMP(uchar tpAddr) {

 ScrDisp(tpAddr,“Set High TMP

 “);

 }

 void DispCursor(uchar tpAddr) //显示尖头指示符号 {

 lcd_w_cmd(tpAddr);

 //设置显示位置

 lcd_w_dat(0x7f); }

 void DispMeau(uchar tpDeep) {

 //DispCursor(0x8d);

  switch(tpDeep/2)

 {

  case 0:

 DispSetDate(0x80);

 DispSetTime(0xc0);

 if(tpDeep%2==0) DispCursor(0x8d);

 else

  DispCursor(0xcd);

 break;

  case 1:

 DispSetLTMP(0x80);

 DispSetHTMP(0xc0);

 if(tpDeep%2==0) DispCursor(0x8d);

 else

  DispCursor(0xcd);

 break;

  default:

 break;

 } }

 

Tags: 单片机   课程设计   报告  

搜索
网站分类
标签列表