【藍橋杯單片機組第八屆初賽試題】— 基於單片機的電子鐘程序設計與調試

1、初賽試題

 1.1 基本要求

(1)使用 CT107D 單片機競賽板, 完成“電子鐘” 功能的程序設計與調試;
(2)設計與調試過程中,可參考組委會提供的“資源數據包”;
(3)Keil 工程文件以准考證號命名, 完成設計後, 提交完整、 可編譯的 Keil工程文件到服務器。

 1.2 硬件框圖

  1.3 功能描述

   1.3.1 初始化

 (1)關閉蜂鳴器、繼電器等無關外設;

 (2) 設備初始化時鐘爲 23 時 59 分 50 秒,鬧鐘提醒時間 0 時 0 分 0 秒。

   1.3.2 顯示功能

 (1)時間顯示格式

 (2)溫度顯示格式

   1.3.3 按鍵功能

 (1)按鍵 S7 定義爲“時鐘設置”按鍵,通過該按鍵可切換選擇待調整的時、分、秒, 當前選擇的顯示單元以 1 秒爲間隔亮滅, 時、分、秒的調整需注意數據邊界屬性。

 (2)按鍵 S6 定義爲“鬧鐘設置”按鍵,通過該按鍵可進入鬧鐘時間設置功能,數碼管顯示當前設定的鬧鐘時間。

 (3)按鍵 S5 定義爲“加”按鍵,在“時鐘設置”或“鬧鐘設置”狀態下,每次按下該按鍵當前選擇的單元(時、分或秒)增加 1 個單位。
 (4)按鍵 S4 定義爲“減”按鍵,在“時鐘設置”或“鬧鐘設置”狀態下,每次按下該按鍵當前選擇的單元(時、分或秒)減少 1 個單位。
 (5)按鍵功能說明:按鍵 S4、 S5 的“加”、“減” 功能只在“時鐘設置”或“鬧鐘設置”狀態下有效;在 “時鐘顯示”狀態下,按下 S4 按鍵,顯示溫度數據,鬆開按鍵,返回“時鐘顯示”界面。

 1.4 鬧鐘提示功能

 (1)指示燈 L1 以 0.2 秒爲間隔閃爍,持續 5 秒鐘;
 (2)鬧鐘提示狀態下,按下任意按鍵,關閉閃爍提示功能。
 

#include<stc15f2k60s2.h>
#include "intrins.h" 
#define uchar unsigned char
#define uint unsigned int
 
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
sbit DQ=P1^4;

uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF,0XC6};
uint f1,f2,f3,f4,f5,f6,f7,f8;
unsigned char time[]={50,59,23,0,0,0,0};
uchar tem;
uchar timeset=4;
uchar clockset=0;
uint H=0,M=0,S=0;
uchar show_tem=0;
uchar s4=0;
uchar n=0;
uint  count=0;
uchar led=0;
uchar led_show=0;

void Write_Ds1302_Byte(unsigned char dat);
unsigned char Read_Ds1302_Byte(void);
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
void ds1302_init();
void ds1302_timeget();

unsigned char temget(void);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
void Delay_OneWire(unsigned int t);


void Delay(unsigned char ms);	

void Time0_Init();

void keyscan();	

void allinit();
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 main(){
allinit();
Time0_Init();
ds1302_init(); 
 
while(1){
ds1302_timeget();
tem=temget();

if(show_tem==0)
{     
    if(timeset==4)
	{ 
	    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 if(timeset==1)
	{
	  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=11;f2=11;f3=10;
       f4=time[1]/10;f5=time[1]%10;f6=10;
       f7=time[0]/10;f8=time[0]%10;
	  }
	 }

	 else if(timeset==2)
	 { 
	    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=10;
      f4=11;f5=11;f6=10;
      f7=time[0]/10;f8=time[0]%10;
	  }
	 }     
     
	 else if(timeset==3)
	 { 
	    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=10;
      f4=time[1]/10;f5=time[1]%10;f6=10;
      f7=11;f8=11;
	  }
	 }
     
	 if(clockset==4)
	 {
	   ds1302_timeget();

       f1=H/10;f2=H%10;f3=10;
	   f4=M/10;f5=M%10;f6=10;
	   f7=S/10;f8=S%10;
	 }
     else if(clockset==1)
	 {
	   if(time[0]%2==1)
	   { 
	     f1=H/10;f2=H%10;f3=10;
	     f4=M/10;f5=M%10;f6=10;
	     f7=S/10;f8=S%10;
	   }
	   else
	   {
	     f1=11;f2=11;f3=10;
	     f4=M/10;f5=M%10;f6=10;
	     f7=S/10;f8=S%10;

	   }
	 }
	 else if(clockset==2)
	 {
	   	 if(time[0]%2==1)
	   { 
	     f1=H/10;f2=H%10;f3=10;
	     f4=M/10;f5=M%10;f6=10;
	     f7=S/10;f8=S%10;
	   }
	   else
	   {
	     f1=H/10;f2=H%10;f3=10;
	     f4=11;f5=11;f6=10;
	     f7=S/10;f8=S%10;
	   }
	 }
	 else if(clockset==3)
	 {
	    if(time[0]%2==1)
	   { 
	     f1=H/10;f2=H%10;f3=10;
	     f4=M/10;f5=M%10;f6=10;
	     f7=S/10;f8=S%10;
	   }
	   else
	   {
	     f1=H/10;f2=H%10;f3=10;
	     f4=M/10;f5=M%10;f6=10;
	     f7=11;f8=11;
	   }
	 } 
}

else if(show_tem==1)
{
  f1=11;f2=11;f3=11;f4=11;f5=11;f6=tem/10;f7=tem%10;f8=12;
}

if((time[2]==H)&&(time[1]==M)&&(time[0]==S))
  {
    EA=1;
	ET0=1;
	led_show=1;
  }

keyscan();
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}

void keyscan()
{ 
   if(P30==0)
   {
      Delay(120);
	  if(P30==0)
	  {
	    if(led_show==0)
	    {
		   if(timeset==0)
		   {
		    timeset=4;clockset=0;
		   }
		   else if(timeset==4) timeset=1;
		   else if(timeset==1) timeset=2;
		   else if(timeset==2) timeset=3;
		   else if(timeset==3) timeset=4;
		}
		else if(led_show==1)
		{
		  led_show=0;
		  P2=0X80;
		  P0=0XFF;
		}
	   }
	while(!P30);
   }
   else if(P31==0)
   {
      Delay(120);
	 if(P31==0)
	 {
	   if(led_show==0)
	   {
	     if(clockset==0)
		 {
		   clockset=4;timeset=0;
		 }
	     else if(clockset==4) clockset=1;
	     else if(clockset==1) clockset=2;
	     else if(clockset==2) clockset=3;  
	     else if(clockset==3) clockset=4;
	   }
	  else if(led_show==1)
	  {
	     P2=0XA0;
	     P0=0XFF;
	     led_show=0;
	  }
	 }
	while(!P31);
  }


  else if(P32==0)
  {
     Delay(120);
	 if(P32==0)
	 {
	    if(led_show==0)
		{
		  if(timeset==1)
		  {
		     if(time[2]==23) time[2]=0;
			 else
			 time[2]++; ds1302_init(); 
		  }
		  else if(timeset==2)
		  {
		     if(time[1]==59) time[1]=0;
			 else
			 time[1]++; ds1302_init(); 
		  }
		  else if(timeset==3)
		  {
		     if(time[0]==59) time[0]=0;
			 else
			 time[0]++;   ds1302_init(); 
		  }
		  
		  else if(clockset==1)
		  {
		     if(H==23) H=0;
			 else
			 H++;
		  }
		  else if(clockset==2)
		  {
		     if(M==59) M=0;
			 else
			 M++;
		  }	
		   else if(clockset==3)
		  {
		     if(S==59) S=0;
			 else
			 S++;
		  }	   
	    }
		else if(led_show==1)
		{
		  led_show=0;
		  P2=0XA0;
		  P0=0XFF;
		}
	while(!P32);
  }
}

else if(P33==0)
{
    Delay(250);
	if(P33==0)
	{
	  s4=1;
	  if(timeset==4) show_tem=1;
	}

	if((s4==1)&&(P33==0))
	{
	   s4=0;
	   show_tem=0;
	   if(led_show==0)
	   {
	     if(timeset==1)
		   {
		      if(time[2]==0) time[2]=23;
			  else
			  {time[2]--;}
			   ds1302_init(); 
		   }
		 else if(timeset==2)
		   {
		      if(time[1]==0) time[1]=59;
		      else
		      {time[1]--;}
			   ds1302_init();
		   }
		 else if(timeset==3)
		   {
		    if(time[0]==0) time[0]=59;
			  else
			  {time[0]--;}
			   ds1302_init();
		   }
		 else if(clockset==1)
		   {
		      if(H==0) H=23;
			  else
			  H--;
		   }
		 else if(clockset==2)
		   {
		      if(M==0) M=59;
			  else
			  M--;
		   }
		 else if(clockset==3)
		   {
		      if(S==0) S=59;
			  else
			  S--;
		   }
	  }
	  else if(led_show==1)
	  {
	    led_show=0;
		P2=0XA0;
		P0=0XFF;
	  }
	} 
  }	      
}

void Time0_Init(){

TMOD=0X01;	//定時器T0,工作方式2爲16爲定時/計數器;
TH0=(65536-5000)/256;  //高四位寄存器的值;
TL0=(65536-5000)%256;  //低四位寄存器的值;
TR0=1;	   //啓動定時器T0 ;
}

void Time_Service() interrupt 1
{
TH0=(65536-5000)/256;  //高四位寄存器的值;
TL0=(65536-5000)%256;  //低四位寄存器的值;
n++;
count++;
if(count==1000)
{
  count=0;
  EA=0;
  ET0=0;
  led_show=0;
  P2=0X80;
  P0=0XFF;
}
if((n==40)&&(led_show==1))
{
   n=0;
   if(led==0)
   {
     P2=0X80;
	 P0=0XFF;
	 led=1;
   }
   else if(led==1)
   {
   P2=0X80;
   P0=0XFE;
   led=0;
   }
 }
}


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

void ds1302_init(){
  unsigned char i,add;
  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_timeget(){
	unsigned char i,add;
	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);

}

void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
Delay(8);
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
Delay(8);
}
 
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
Delay(8);
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
Delay(8);
}
 
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
Delay(8);
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
Delay(8);
}
 
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
Delay(8);
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
Delay(8);
}

/*單字節寫入一字節數據*/
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=1;		//#define SDA_SET SDA=1 /*電平置高*/
		}
		else 
		{
			SDA=0;		//#define SDA_CLR SDA=0 /*電平置低*/
		}		 
		SCK=1;
		SCK=0;		
		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) 	  //等價於if(SDA_R==1)    #define SDA_R SDA /*電平讀取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK=1;
		SCK=0;
	}
	return dat;
}
 
/********************************************************************/ 
/*向DS1302 單字節寫入一字節數據*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 
 
	RST=0;			/*RST腳置低,實現DS1302的初始化*/
	SCK=0;			/*SCK腳置低,實現DS1302的初始化*/
 
	RST=1;			/*啓動DS1302總線,RST=1電平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是寫操作,寫之前將最低位置零*/	
	Write_Ds1302_Byte((dat/10<<4)|(dat%10));	 /*寫入數據:dat*/
	RST=0;				 /*停止DS1302總線*/
}
 
/********************************************************************/ 
/*從DS1302單字節讀出一字節數據*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	unsigned char dat1,dat2;
	RST=0;			/*RST腳置低,實現DS1302的初始化*/
	SCK=0;			/*SCK腳置低,實現DS1302的初始化*/
 
	RST=1;	/*啓動DS1302總線,RST=1電平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*寫入目標地址:addr,保證是讀操作,寫之前將最低位置高*/
	temp=Read_Ds1302_Byte(); /*從DS1302中讀出一個字節的數據*/		
	RST=0;	/*停止DS1302總線*/
	
	dat1=temp/16;
	dat2=temp%16;
	temp=10*dat1+dat2;
	SDA=0;
	
	return temp;
}



void Delay(unsigned char ms)	
{
	unsigned char i, j;
 
	_nop_();
	_nop_();
	i = ms;
	j = 15;
	do
	{
		while (--j);
	} while (--i);
}
 

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


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;
}

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);
}


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 temget(void)
{
	unsigned char low,high;
	unsigned char temp;
  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;
	
}


 

 

 




 

 

 

 

 

 

 

 

 

 

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