【藍橋杯單片機組第六屆省賽】— “溫度記錄器”設計任務書

1、試題

(1)功能簡述
  設備按照用戶通過按鍵設定的時間間隔自動採集並存儲溫度數據,並具有采集完成提醒、數碼管顯示等功能,系統硬件部分主要由按鍵電路、電源供電電路、 RTC 時鐘、傳感器電路和顯示電路組成。 系統框圖如圖 1 所示:

  (2)設計任務及要求
     1. 數碼管顯示

     1.1 設備上電後,自動進入參數設置界面(圖 1) 此時,通過按鍵 S4 切換 4 個溫度採集間隔時間,分別爲 1 秒、 5 秒、 30 秒和 60 秒;

      按下按鍵 S5,確認採集間隔時間,並退出參數設置界面(圖 1),進入時鐘顯示界面(圖 2)並開始採集溫度。

      要求: 時鐘顯示界面(圖 2)下,提示符 1、 2 以 1 秒爲間隔閃爍

      1.2 當設備按照用戶設定的採集間隔採集到 10 個數據後,指示燈 L1 閃爍提示本次溫度採集已經完成,此時進入數碼管溫度採集顯示界面(圖 3):

      此時,按下 S6, L1 熄滅,按照時間先後順序,切換顯示設備內存儲的溫度數據;按下 S7 按鍵進入參數設置界面(圖 1),待用戶輸入溫度採集間隔之後,可以進行下一次的溫度採集工作。
      說明: 索引指的是當前顯示的溫度按照採集時間先後順序的編號(00-09)。
   2. 溫度檢測功能
   使用 DS18B20 溫度傳感器完成溫度測量功能。
   3. RTC
   使用 DS1302 時鐘芯片完成 RTC 的相關功能。
   4. 設備工作模式說明
(1) 默認 RTC 時間: 23 時 59 分 50 秒;
(2) 默認溫度數據採集間隔爲 1 秒;
(3) 設備處在不同的顯示界面下,與該界面無關的按鍵操作無效;
(4) 溫度數據最大存儲容量: 10 個

2、試題分析

 對於實時時鐘DS1302:要記得一些細節的改變(根據官方庫文件修改得來的):

另外又添加了實時時鐘初始化函數和讀取函數。

對於DS18B02(溫度獲取函數):


unsigned char get_wendu(){
unsigned char temp,high,low;
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);

low=Read_DS18B20();
high=Read_DS18B20();

temp=(low>>4)|(high<<4);

return temp;
}

3、代碼

 ds1302.c

#include "ds1302.h"
unsigned char time[]={50,59,23,0,0,0,0};
/********************************************************************/ 
/*單字節寫入一字節數據*/
void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	// 等價於if((addr & 0x01) ==1) 
		{
			SDA_SET;		//#define SDA_SET SDA=1 /*電平置高*/
		}
		else 
		{
			SDA_CLR;		//#define SDA_CLR SDA=0 /*電平置低*/
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}
/********************************************************************/ 
/*單字節讀出一字節數據*/
unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	  //等價於if(SDA_R==1)    #define SDA_R SDA /*電平讀取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}
	return dat;
}

/********************************************************************/ 
/*向DS1302 單字節寫入一字節數據*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST腳置低,實現DS1302的初始化*/
	SCK_CLR;			/*SCK腳置低,實現DS1302的初始化*/

	RST_SET;			/*啓動DS1302總線,RST=1電平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是寫操作,寫之前將最低位置零*/	
	Write_Ds1302_Byte((dat/10<<4)|(dat%10));	 /*寫入數據:dat*/
	RST_CLR;				 /*停止DS1302總線*/
}

/********************************************************************/ 
/*從DS1302單字節讀出一字節數據*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp,dat1,dat2;
	RST_CLR;			/*RST腳置低,實現DS1302的初始化*/
	SCK_CLR;			/*SCK腳置低,實現DS1302的初始化*/

	RST_SET;	/*啓動DS1302總線,RST=1電平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是讀操作,寫之前將最低位置高*/
	temp=Read_Ds1302_Byte(); /*從DS1302中讀出一個字節的數據*/
	
	dat1=temp/16;
	dat2=temp%16;
	temp=dat1*10+dat2;		
	SD=0;
	return temp;
}

void ds1302_init(){
unsigned char add,i;
add=0x80;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
  Ds1302_Single_Byte_Write(add,time[i]);
  add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);  
}

void ds1302_read(){
unsigned char add,i;
add=0x81;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
  time[i]=Ds1302_Single_Byte_Read(add);
  add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80); 
} 

 ds1302.h


#ifndef  __DS1302_H__
#define  __DS1302_H__

#include<stc15f2k60s2.h>
#include<intrins.h>
/********************************************************************/ 
sbit SCK=P1^7;		
sbit SD=P2^3;		
sbit RST=P1^3;
/********************************************************************/ 
/*復位腳*/
#define RST_CLR	RST=0	/*電平置低*/
#define RST_SET	RST=1	/*電平置高*/
/*雙向數據*/
#define SDA_CLR	SD=0	/*電平置低*/
#define SDA_SET	SD=1	/*電平置高*/
#define SDA_R	SD	/*電平讀取*/	
/*時鐘信號*/
#define SCK_CLR	SCK=0	/*時鐘信號*/
#define SCK_SET	SCK=1	/*電平置高*/
/********************************************************************/ 
#define ds1302_sec_addr			0x80		//秒數據地址
#define ds1302_min_addr			0x82		//分數據地址
#define ds1302_hr_addr			0x84		//時數據地址
#define ds1302_date_addr		0x86		//日數據地址
#define ds1302_month_addr		0x88		//月數據地址
#define ds1302_day_addr			0x8A		//星期數據地址
#define ds1302_year_addr		0x8C		//年數據地址

#define ds1302_control_addr		0x8Ee		//寫保護命令字單元地址
#define ds1302_charger_addr		0x90 		//涓電流充電命令字地址			 
#define ds1302_clkburst_addr	0xBE		//日曆、時鐘突發模式命令字地址

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

/********************************************************************/ 
/*單字節寫入一字節數據*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/ 
/*單字節讀出一字節數據*/
extern unsigned char Read_Ds1302_Byte(void);
  
/********************************************************************/ 
/********************************************************************/ 
/*向DS1302單字節寫入一字節數據*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/ 
/*從DS1302單字節讀出一字節數據*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);

extern unsigned char time[];
extern void ds1302_init();
extern void ds1302_read();

#endif	 
/********************************************************************/
//		     	END FILE
/********************************************************************/

 onewire.c

#include "onewire.h"

//單總線延時函數
void Delay_OneWire(unsigned int t)
{
  t=12*t;
  while(t--);
}

//DS18B20芯片初始化
bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay_OneWire(80); 
	DQ = 1;
	Delay_OneWire(10); 
	initflag = DQ;    
	Delay_OneWire(5);
  
	return initflag;
}

//通過單總線向DS18B20寫一個字節
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//從DS18B20讀取一個字節
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

unsigned char get_wendu(){
unsigned char temp,high,low;
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);

low=Read_DS18B20();
high=Read_DS18B20();

temp=(low>>4)|(high<<4);

return temp;
}

 onewire.h

#ifndef _ONEWIRE_H
#define _ONEWIRE_H

#include "stc15f2k60s2.h"

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//IC引腳定義
sbit DQ = P1^4;

//函數聲明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char get_wendu();
#endif

 text.c

#include<stc15f2k60s2.h>
#include "ds1302.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int

uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar flag1=0;
uchar flag2=0;
uchar led=0;
uchar count=0;
uchar wendu=0;
uchar tt=0;
uchar caiji_wendu[10];
uchar n=0;
uchar jiange=0;
uchar f1,f2,f3,f4,f5,f6,f7,f8;

void delayms(uchar ms);
void delay();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void keyscan();
void allinit();
void Time0_init();

void main(){
ds1302_init();
allinit();
Time0_init();

while(1)
{	
    wendu=get_wendu();
	keyscan();
    switch(count)
	{
	  case 1:jiange=1;break;
	  case 2:jiange=5;break;
	  case 3:jiange=30;break;
	  case 4:jiange=60;count=0;break;
	}

	if(flag1==0)
	{
	  f1=11;f2=11;f3=11;f4=11;f5=11;f6=10;f7=jiange/10;f8=jiange%10;
	}

	if(flag1==1)
	 {
	    ds1302_read();
		if(time[0]%2==1)
		{
		  f1=time[2]/10;f2=time[2]%10;f3=10;
		  f4=time[1]/10;f5=time[1]%10;f6=10;
		  f7=time[0]/10;f8=time[0]%10;
		}
		else
		{
		  f1=time[2]/10;f2=time[2]%10;f3=11;
		  f4=time[1]/10;f5=time[1]%10;f6=11;
		  f7=time[0]/10;f8=time[0]%10;  
		}
	  }
	  display12(f1,f2);
	  display34(f3,f4);
	  display56(f5,f6);
	  display78(f7,f8);
   }
}


void keyscan(){
if(P30==0)		 //s7
{
  delayms(5);
  if(P30==0)
  {
    flag1=0;
  }
while(!P30);
}

 if(!P31==0)   //s6
{
  delayms(5);
  if(P31==0)
  {
    led=0;
  }
while(!P31);
}

  if(P32==0)	  //s5
{
  delayms(5);
  if(P32==0)
  {
    if(flag1==0)
	{
       flag1=1;
	   tt=0;
	   count=1; 
  }
}
}
 
 if(P33==0)	   //s4
{
   delayms(5);
   if(P33==0)
   {
      count++;
	}
while(!P33);
}

}

void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}

void delayms(uchar ms){
uchar i,j,k;
for(k=ms;k>0;k--)
{
   i=12;
   j=169;
   do
   {
     while(j--);
   }
   while(i--);
}
}

void delay(){
uchar i,j;
for(i=10;i>0;i--)
for(j=200;j>0;j--);
}

void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}

void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}

void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}

void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}

void Time0_init(){
TMOD=0X01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TR0=1;
EA=1;
ET0=1;
}

void Time0_service() interrupt 1
{
  TH0=(65536-5000)/256;
  TL0=(65536-5000)%256;
  tt++;
  if((tt==jiange*200)&&(flag1==1))
  {
    tt=0;
	caiji_wendu[n]=wendu;
	n++;
	if(n==10)
	{
	  n=0;
	  led=1;
	  flag1=2;
	  f1=10;f2=0;f3=0;
	  f4=11;f5=11;f6=10;
	  f7=caiji_wendu[0]/10;f8=caiji_wendu[0]%10;
	}
  }

  if((flag1==2)&&(tt==200))
	{
	  tt=0;
	  if(led==1)
	  {
	  if(flag2==0)
	  {
	    flag2=1;
		P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
		P00=0;
	  }
	  else if(flag2==1)
	  {
	    flag2=0;
		P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
		P00=1;
	  }
	 }
	 else if(led==0)
	 {
	   P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	   P00=1;
	   f1=10;f2=n/10;f3=n%10;
	   f4=11;f5=11;f6=10;
	   f7=caiji_wendu[n]/10;f8=caiji_wendu[n]%10;
	   n++;
	   if(n==10)
	   {
	     flag1=3;
		 n=0;
	   }
	 }
   }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章