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