蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)

编程部分是笔者自己编写,且已在板子上调试成功,免费分享给读者,如有不足忘指正。
使用的芯片为竞赛芯片IAP,并非练习芯片52。

功能简述
设备按照用户通过按键设定的时间间隔自动采集并存储温度数据,并具有采集完成提醒、数码管显示等功能,系统硬件部分主要由按键电路、电源供电电路、RTC 时钟、传感器电路和显示电路组成.

蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)_第1张图片
单总线驱动程序、DS1302 芯片驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生号命名,并保存在计算机上的考生文件夹中(文件夹名为考生准考证号,文件夹位于Windows 桌面上)
设计任务及要求

  1. 数码管显示
    1.1 设备上电后,自动进入参数设置界面(图 1)此时,通过按键 S4 切换 4 个温度
    采集间隔时间,分别为 1 秒、5 秒、30 秒和 60 秒;
    蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)_第2张图片
    要求:时钟显示界面(图 2)下,提示符 1、2 以 1 秒为间隔闪烁
    1.2 当设备按照用户设定的采集间隔采集到 10 个数据后,指示灯 L1 闪烁提示本
    次温度采集已经完成,此时进入数码管温度采集显示界面(图 3)
    蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)_第3张图片
    此时,按下 S6,L1 熄灭,按照时间先后顺序,切换显示设备内存储的温度数据;
    按下 S7 按键进入参数设置界面(图 1),待用户输入温度采集间隔之后,可以进行
    下一次的温度采集工作。
    说明:索引指的是当前显示的温度按照采集时间先后顺序的编号(00-09)。
  2. 温度检测功能
    使用 DS18B20 温度传感器完成温度测量功能。
  3. RTC
    使用 DS1302 时钟芯片完成 RTC 的相关功能。
  4. 设备工作模式说明
    (1)默认 RTC 时间:23 时 59 分 50 秒;
    (2)默认温度数据采集间隔为 1 秒;
    (3)设备处在不同的显示界面下,与该界面无关的按键操作无效;
    (4)温度数据最大存储容量:10 个

代码

main.c

#include"STC15F2K60S2.h"
 #include"ds1302.h"
 #include"onewire.h"

 #define uchar unsigned char
 #define uint unsigned int

 bit blink;
 bit flag_wendu;

 uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
 uchar yi,er,san,si,wu,liu,qi,ba;	//yi---ba为1-8个数码管
 uchar flag_S4;	//标志位
 uchar samplemiao;	//采集间隔
 uchar flag_scan;  
 uchar shi,fen,miao; //时钟时分秒
 uchar wendu;		 //温度
 uchar samplewendu[10];	 //采集的10次温度记录在该数组
 uchar suoyin;       //索引

 void allinit(void);
 void Timer0Init(void);
 void timer0();
 void keyscan(void);
 void display1(uchar yi,uchar er);
 void display2(uchar san,uchar si);
 void display3(uchar wu,uchar liu);
 void display4(uchar qi,uchar ba);
 void delayms(uint ms);

 void main(void)
 {
 	allinit();
	Timer0Init();
	set_sfm(23,59,50);	  //默认RTC时间
	yi=11;er=11;san=11;si=11;wu=11;liu=10;qi=0;ba=1;  //设备上电后,自动进入参数设置界面
	while(1)
	{
		wendu=read_temperature();// 读温度
		shi=Read_Ds1302(0x85);  //读时间  
		fen=Read_Ds1302(0x83);
		miao=Read_Ds1302(0x81);
		keyscan();     //按键判断
		if(flag_scan==3) //关定时器
		{
			ET0=1;
			EA=1;
		}
		if(flag_wendu==1)//开始写温度索引显示
		{
			flag_wendu=0;
			flag_scan=5;
			qi=wendu/10;ba=wendu%10; 
			ET0=0;EA=0;
		}
		if(flag_scan==5)
		 {
		 	yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
		 	P2=0X80;P0=0XFE;
			delayms(100);
			P2=0X80;P0=0XFF;
			delayms(100);
		 }
		 if(flag_scan==2)	 
		 {
			flag_scan=0;  //下面为按照时间先后顺序,切换显示设备内存储的温度数据
			yi=10;er=suoyin/10;san=suoyin%10;si=11;wu=11;liu=10;qi=samplewendu[suoyin]/10;ba=samplewendu[suoyin]%10;
			suoyin++;  	  //索引值加1;
			if(suoyin==10) suoyin=0;	  //重新从第一个采集的温度显示
		 }
		display1(yi,er);
		display2(san,si);
		display3(wu,liu);
		display4(qi,ba);
	}
 }
 void allinit(void)	   //  初始化
 {
 	P2=0XA0;P0=0X00;
	P=0X80;P0=0XFF;
	P2=0XC0;P0=0XFF;
	P2=0XFF;P0=0XFF;
 }
 void Timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
 void timer0() interrupt 1 using 1
 {
 	uchar i,j,k;
	i++;j++;k++;
	if(i==200)
	{
		i=0;
		blink=!blink;	   //时钟显示界面下,提示符 1、2 以 1 秒为间隔闪烁
		if(blink==1)
		{
			san=10;liu=10;
		}
		else if(blink==0)
		{
			san=11;liu=11;
		}
	}
	if(j==1&&(flag_scan==3)&&samplemiao==1)	 //采集间隔1s 
	{
		uchar k;      //为什么让j=1,是为了方便多次记录温度,但这样写每次会有5ms的误差。
		//wendu=read_temperature();
		P2=0xa0;P0=0x00;
		samplewendu[k++]=wendu;		 //记录温度
		if(k==10) 
		{
			k=1;
			flag_wendu=1;
		}
	}
	if(j==200&&flag_scan==3&&samplemiao==1)  j=0;//5*200ms后j=0,即1s后再次记录温度
	if(k==1&&(flag_scan==3)&&samplemiao==5)	 //采集间隔5s
	{										 //30s,60s的没写,但类似1,5s编程
		uchar k;
		samplewendu[k++]=wendu;
		if(k==10) 
		{
			k=1;
			flag_wendu=1;
		}
	}
	if(k=1000&&flag_scan==3&&samplemiao==5)  k=0;//5*1000ms后k=0,即5s后再次记录温度
 }
 void keyscan(void)
 {
 	if(P30==0)		//S4按下
	{
		delayms(5);
		if(P30==0)
		{
			if(flag_scan==0)  //索引界面显示后
			{
				flag_scan=4;//参数切换
				yi=11;er=11;san=11;si=11;wu=11;liu=10;qi=0;ba=1;  //初始状态
				flag_S4=0;
			}
		}
		while(!P30);//按键弹起退出循环
	}
	else if(P31==0)
	{
		delayms(5);
		if(P31==0)		//S5按键按下
		{
			flag_scan=2;P2=0X80;P0=0XFF;
		}
		while(!P31);
	}
	else if(P32==0)	  //S6按下
	{
		delayms(5);
		if(P32==0)
		{
			flag_scan=3;	
			samplemiao=qi*10+ba; //记录采集间隔
			wendu=read_temperature();
			//wendu=30;
			suoyin=0;
			//samplewendu[0]=wendu;
		}
		while(!P32);
	}
	else if(P33==0)	   //S7按下
	{
		delayms(5);
		if(P33==0)
		{
			flag_scan=4; //进入参数显示界面
			flag_S4++;
		}
		while(!P33);
	}
	if(flag_scan==4)
	{
		EA=0;ET0=0;	  //定时器开始工作
		yi=11;er=11;san=11;si=11;wu=11;liu=10; 
		if(flag_S4==0) {qi=0;ba=1;}	//采集间隔显示1s
		if(flag_S4==1) {qi=0;ba=5;}	//5s
		if(flag_S4==2) {qi=3;ba=0;}	//30s
		if(flag_S4==3) {qi=6;ba=0;}	//60s
		if(flag_S4==4) {flag_S4=0;qi=0;ba=1;}  //60后再按一次重新从1开始
	}
	if(flag_scan==3)
	{
		yi=shi/16;er=shi%16;	//显示时间,时间读出来为16进制要转换成十进制
		si=fen/16;wu=fen%16;
		qi=miao/16;ba=miao%16;
	}
 }
 void display1(uchar yi,uchar er)
 {
 	P2=0XC0;P0=0X01;
	P2=0XFF;P0=tab[yi];
	delayms(1);

	P2=0XC0;P0=0X02;
	P2=0XFF;P0=tab[er];
	delayms(1);
 }
 void display2(uchar san,uchar si)
 {
 	P2=0XC0;P0=0X04;
	P2=0XFF;P0=tab[san];
	delayms(1);

	P2=0XC0;P0=0X08;
	P2=0XFF;P0=tab[si];
	delayms(1);
 }
 void display3(uchar wu,uchar liu)
 {
 	P2=0XC0;P0=0X10;
	P2=0XFF;P0=tab[wu];
	delayms(1);

	P2=0XC0;P0=0X20;
	P2=0XFF;P0=tab[liu];
	delayms(1);
 }
 void display4(uchar qi,uchar ba)
 {
 	P2=0XC0;P0=0X40;
	P2=0XFF;P0=tab[qi];
	delayms(1);

	P2=0XC0;P0=0X80;
	P2=0XFF;P0=tab[ba];
	delayms(1);

	P2=0XC0;P0=0XFF;
	P2=0XFF;P0=0XFF;
 }
 void delayms(uint ms)
 {
 	uint i,j;
	for(i=0;i0;j--);
	}
 }

onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include"STC15F2K60S2.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(50);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(50);
}

//从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(50);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(120);
  	DQ = 0;
  	Delay_OneWire(800);
  	DQ = 1;
  	Delay_OneWire(100); 
    initflag = DQ;     
  	Delay_OneWire(50);
  
  	return initflag;
}
unsigned char read_temperature(void)
{
	unsigned char temp;
	unsigned char low,high;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
    high=Read_DS18B20();
	low=Read_DS18B20();
	high=high<<4;
	low=low>>4;
	temp=temp|low;
	return temp;
}

ds1302.c

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include"STC15F2K60S2.h"
#include 
#include 

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位	

unsigned char shijian[]={0,30,8,0,0,0,0};

void Write_Ds1302_Byte(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302( unsigned char address,unsigned char dat )     
{
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=1;	
   	_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); 
 	Write_Ds1302_Byte(address);	
 	Write_Ds1302_Byte(dat);	/////////////////////////////////////////////////	
 	RST=0; 
}

unsigned char Read_Ds1302 ( unsigned char address )
{
 	unsigned char i,temp=0x00;/////////////////////////////////////
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	Write_Ds1302_Byte(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=0;
	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SCK=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SDA=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SDA=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	
	//dat1=temp/16;
	//dat2=temp%16;
//	temp=dat1*10+dat2;/////////////////////////////////////////////////////////////////
	
	return (temp);			
}
 void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
 {
 	Write_Ds1302(0x8e,0x00);
	Write_Ds1302(0x84,(shi/10)*16+shi%10);
	Write_Ds1302(0x82,(fen/10)*16+fen%10);
	Write_Ds1302(0x80,(miao/10)*16+miao%10);
	Write_Ds1302(0x8e,0x80);
 }

ds1302.h

蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)_第4张图片
onewire.h
蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2)_第5张图片

你可能感兴趣的:(蓝桥杯单片机设计第六届省赛温度记录器,题目与编程(IAP15单片机)(STC15F2K60S2))