蓝桥杯第七届省赛模拟试题--“温度记录器”

题目要求

功能简述
设备按照用户通过按键设定的时间间隔自动采集并存储温度数据,并具有采集完成提醒、数码管显示等功能,系统硬件部分主要由按键电路、电源供电电路、 RTC 时钟、传感器电路和显示电路组成。 系统框图如图 1 所示:
蓝桥杯第七届省赛模拟试题--“温度记录器”_第1张图片
单总线驱动程序、 DS1302 芯片驱动程序、 CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生号命名,并保存在计算机上的考生文件夹中(文件夹名为考生准考证号,文件夹位于Windows 桌面上)。
设计任务及要求
1. 数码管显示
1.1 设备上电后,自动进入参数设置界面(图 1) 此时,通过按键 S4 切换 4 个温度采集间隔时间,分别为 1 秒、 5 秒、 30 秒和 60 秒;
蓝桥杯第七届省赛模拟试题--“温度记录器”_第2张图片
按下按键 S5,确认采集间隔时间,并退出参数设置界面(图 1),进入时钟显示界面(图 2)并开始采集温度。
蓝桥杯第七届省赛模拟试题--“温度记录器”_第3张图片
要求: 时钟显示界面(图 2)下,提示符 1、 2 以 1 秒为间隔闪烁
1.2 当设备按照用户设定的采集间隔采集到 10 个数据后,指示灯 L1 闪烁提示本次温度采集已经完成,此时进入数码管温度采集显示界面(图 3):
蓝桥杯第七届省赛模拟试题--“温度记录器”_第4张图片
此时,按下 S6, L1 熄灭,按照时间先后顺序,切换显示设备内存储的温度数据;按下 S7 按键进入参数设置界面(图 1),待用户输入温度采集间隔之后,可以进行下一次的温度采集工作。
说明: 索引指的是当前显示的温度按照采集时间先后顺序的编(00-09)。
2. 温度检测功能
使用 DS18B20 温度传感器完成温度测量功能。
3. RTC
使用 DS1302 时钟芯片完成 RTC 的相关功能。
4. 设备工作模式说明
(1) 默认 RTC 时间: 23 时 59 分 50 秒;
(2) 默认温度数据采集间隔为 1 秒;
(3) 设备处在不同的显示界面下,与该界面无关的按键操作无效;
(4) 温度数据最大存储容量: 10 个
5. 电路原理图设计
使用基本阻容元器件、集成运算放大器设计硬件电路,完成如下功能:
已知某种类型的传感器输出 4-20mA 电流信号,设计电路将电流信号转换为 0V-5V的电压信号。简述所设计电路的工作原理,并绘制出电路原理图。

程序代码

主函数

#include<stc15f2k60s2.h>
#include "ds1302.h"
#include "onewire.h"


typedef unsigned char uchar;
typedef unsigned int uint;

uchar code SMG_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar code SMG_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

uchar time_display[8];			 //时间显示界面
uchar temp_display[8];			 //温度显示界面
uchar set_display[8];			//参数设置界面
uchar temperature[10];			//温度数据
uchar mode;					   //设置采集时间间隔
uchar time_nop[]={1,5,30,60};				   //时间间隔
uchar caiji_count=0;			   //采集次数计数
uchar mode_flag=0;			   //显示界面选择
uchar shuju_count;			   //数据
uchar suoyin_count;			   //索引
uchar real_nop;

bit blink_flag;				  //闪烁
bit caiji_flag;				  //采集标志
bit led_flag;				 //led闪烁

void Timer0Init();
char Key_init();
void delayms(uchar ms);

void main()
{
   uchar key_val;
   P2=0XA0;P0=0X00;	 
   P2=0X80;P0=0Xff;
   Timer0Init();
   DS1302_init();

   temp_display[0]=0x40;  temp_display[3]=0x00;
   temp_display[4]=0x00;  temp_display[5]=0x40;

   set_display[0]=0x00;	  set_display[1]=0x00;  set_display[2]=0x00;
   set_display[3]=0x00;
   set_display[4]=0x00;	  set_display[5]=0x40;
   while(1)
   {
      
	  DS1302_read();
	  time_display[0]=SMG_duan[TIME[2]/16];
	  time_display[1]=SMG_duan[TIME[2]%16];
	  time_display[3]=SMG_duan[TIME[1]/16];
	  time_display[4]=SMG_duan[TIME[1]%16];
	  time_display[6]=SMG_duan[TIME[0]/16];
	  time_display[7]=SMG_duan[TIME[0]%16];

	  	  
	    key_val=Key_init();
	   switch(key_val)
	   {
	     case 4: 
				if(mode_flag==0)
				{
				  mode++;
				  if(mode==4)
				  mode=0;
				}
		        break;
		 case 5:
				
				if(mode_flag==0)
				{
				  real_nop=time_nop[mode];
				  mode_flag=1;		  
				}
		        break;
		 case 6:
				if(mode_flag==2)
				{
				  led_flag=0;
				  suoyin_count++;
				  if(suoyin_count==10)
				  suoyin_count=0;
				  P2=0X80;P0=0XFF;P2=0X00;
				}
				break;
		 case 7:
				if(mode_flag==2)
				{
		          mode_flag=0;
				}
		        break;
	   }
	  	  
		 set_display[6]=SMG_duan[time_nop[mode]/10];
	     set_display[7]=SMG_duan[time_nop[mode]%10];
	  
	  if(caiji_flag)
	  {
	     caiji_flag=0;
		 if(caiji_count<10)
		 {
		   ET0=0;
		   temperature[caiji_count]=temp_get();
		   ET0=1;
		 }
		 else
		 {
		   led_flag=1;
		   mode_flag=2;
		   caiji_count=0;				   //要置零,数据个数最大为10
		 }
		 caiji_count++;
	  }
	  temp_display[1]=SMG_duan[suoyin_count/10]; 
	  temp_display[2]=SMG_duan[suoyin_count%10];
	  temp_display[6]=SMG_duan[temperature[suoyin_count]%100/10];
	  temp_display[7]=SMG_duan[temperature[suoyin_count]%10];  
   }
}

#define key_input P3
#define key_state_0  0  		//判断是否按下
#define key_state_1  1 			//判断是否为抖动
#define key_state_2  2 			//判断是否弹起 
char Key_init() 
{ 
    static char key_state = 0; 
    char key_press, key_return = 0;
	uchar key_mask=0x0f; 
    key_press = key_input&key_mask; 
    switch (key_state) 
     { 	
       case key_state_0:     
             if (key_press!=key_mask)
             key_state = key_state_1; 
             break; 	 
       case key_state_1:    
             if (key_press!=key_mask) 
               { 
			  	 if(key_press==0x0e) key_return = 7;  //S7
				 if(key_press==0x0d) key_return = 6;  //S6
				 if(key_press==0x0b) key_return = 5;  //S5
				 if(key_press==0x07) key_return = 4;  //S4
  	             key_state = key_state_2;  
               }  
            else 
   	          key_state = key_state_0;  
            break;  
       case key_state_2: 
            if (key_press==0x0f) 
			key_state = key_state_0; 
            break; 
     } 
     return key_return; 
} 

void Timer0Init()		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}

void Timer0() interrupt 1
{
   uchar i;
   static uint SMG_count=0,blink_count=0,mode_count=0;
   SMG_count++; 
   blink_count++;
   
   if(SMG_count==3)
   {
	  SMG_count=0;
	  P2=0XC0;P0=0X00;P2=0X00;
	  P2=0XC0;P0=SMG_wei[i];

	  if(mode_flag==0)
	  {
		P2=0XE0;P0=~set_display[i];P2=0X00;
	  }
	  if(mode_flag==1)
	  {
	    P2=0XE0;P0=~time_display[i];P2=0X00;
	  }
	  if(mode_flag==2)
	  {
		P2=0XE0;P0=~temp_display[i];P2=0X00;
	  }
	  i++;
	  if(i==8)
	  i=0;
   }

   if(blink_count==1000)				  //1s
   {
	 blink_count=0;
	 blink_flag=~blink_flag;
	 if(blink_flag)
	 {
	    time_display[2]=0x40;  time_display[5]=0x40;
	 }
	 else
	 {
	    time_display[2]=0x00;  time_display[5]=0x00;
	 }

	 if(led_flag==1)
	 {
	    if(blink_flag)
		{
		  P2=0X80;P0=0XFE;P2=0X00;
		}
		else
		{
		  P2=0X80;P0=0XFf;P2=0X00;
		}
	 }
   }

   if(mode_flag==1)
   {
      mode_count++;
      if(mode_count==real_nop*1000)
      {
	    mode_count=0;	
	    caiji_flag=1;					   //开始采集温度		
      }	  
   }
}

DS1302时钟模块

#include "ds1302.h"

typedef unsigned char uchar;
typedef unsigned int uint;

uchar code Write_add[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
uchar code Read_add[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};

uchar TIME[]={0X50,0X59,0X23,0x00,0x00,0x00,0x19};

void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	_nop_();
	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;
		_nop_();
		SCK_CLR;
		_nop_();		
		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;
		_nop_();
		SCK_CLR;
		_nop_();
	}
	return dat;
}

/********************************************************************/ 
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;
	_nop_();			
	SCK_CLR;			
	_nop_();
	RST_SET;			
	_nop_();

	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
	Write_Ds1302_Byte(dat);	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/
	_nop_();
}

unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	_nop_();
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/
	_nop_();

	RST_SET;	/*启动DS1302总线,RST=1电平置高 */
	_nop_();	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
	temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
	RST_CLR;	/*停止DS1302总线*/
	_nop_();
	SD=0;
	_nop_();
	SD=1;
	_nop_();

	return temp;
}

void DS1302_init()
{
   uchar i;
   Ds1302_Single_Byte_Write(0x8e,0x00);
   for(i=0;i<7;i++)
   {
	  Ds1302_Single_Byte_Write(Write_add[i],TIME[i]);
   }
   Ds1302_Single_Byte_Write(0x8e,0x81);
}

void DS1302_read()
{
   uchar i;
   for(i=0;i<7;i++)
   {
	  TIME[i]=Ds1302_Single_Byte_Read(Read_add[i]);
   }
}

DS18B20温度传感器模块

#include "onewire.h"


void Delay500us();
void Delay15us();
void Delay60us();		
void Delay100us();

void Delay_OneWire(unsigned int t)
{
  while(t--);
}

void delayms(unsigned int ms)
{
  int i,j;
  for(i=0;i<=ms;i++)
   for(j=850;j>0;j--);
}

//DS18B20芯片初始化
bit Init_DS18B20(void)
{
	bit initflag = 0;
	Delay_OneWire(12);
	DQ = 0;
	Delay500us(); 
	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;
		Delay15us();
		DQ = dat&0x01;
		Delay60us();
		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;
		_nop_();
		_nop_();
		_nop_();
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay100us();
	}
	return dat;
}

void DS18b20()
{
   Init_DS18B20();
   delayms(1);
   Write_DS18B20(0xcc);
   Write_DS18B20(0x44);

   Init_DS18B20();
   delayms(1);
   Write_DS18B20(0xcc);
   Write_DS18B20(0xbe);
}

int temp_get()
{
   unsigned char low,high;
   unsigned char temp;

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

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

   return temp;
}

void Delay500us()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 6;
	j = 93;
	do
	{
		while (--j);
	} while (--i);
}

void Delay15us()		//@11.0592MHz
{
	unsigned char i;

	i = 39;
	while (--i);
}

void Delay60us()		//@11.0592MHz
{
	unsigned char i, j;

	i = 1;
	j = 162;
	do
	{
		while (--j);
	} while (--i);
}

void Delay100us()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 2;
	j = 15;
	do
	{
		while (--j);
	} while (--i);
}

以上就是代码全部内容,欢迎交流,通过学习~

你可能感兴趣的:(蓝桥杯)