经过几个小时的奋战,我终于又把蓝桥杯的第八届省赛的题给做出来了!开心!
不过呢我已经做出来几天了,只是一直没有贴在博客里。今天刚好无聊我就贴上来了!
话不多说,我们进入正题
我们先来看下题目吧。
1.1 使用 CT107D 单片机竞赛板,完成“电子钟”功能的程序设计与调试;
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”;
1.3 Keil 工程文件以准考证号命名,完成设计后,提交完整、可编译的 Keil工程文件到服务器。
1)关闭蜂鸣器、继电器等无关外设;
2)设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒。
1)按键 S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭,时、分、秒的调整需注意数据边界属性。
2)按键 S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置功能,数码管显示当前设定的闹钟时间。
3)按键 S5 定义为“加”按键,在“时钟设置”或“闹钟设置”状态下,每次按下该按键当前选择的单元(时、分或秒)增加 1 个单位。
4)按键 S4 定义为“减”按键,在“时钟设置”或“闹钟设置”状态下,每次按下该按键当前选择的单元(时、分或秒)减少 1 个单位。
5)按键功能说明:按键 S4、S5 的“加”、“减”功能只在“时钟设置”或“闹钟设置”状态下有效;在 “时钟显示”状态下,按下 S4 按键,显示温度数据,松开按键,返回“时钟显示”界面。
1)指示灯 L1 以 0.2 秒为间隔闪烁,持续 5 秒钟;
2)闹钟提示状态下,按下任意按键,关闭闪烁提示功能。
在这里我大致说一下我的思路。
这个很简单的。时间显示23:59:50
这里时间芯片用的DS13B02,这款芯片我就不用多说了,大家都知道怎么个用法。
时钟的初始化我们需要把23:59:50先写入DS18B20,然后才能正常的从所设置的时间开始显示。
然后就是闹钟的初始化,我们这里直接在定义闹钟的变量的时候就直接给他赋值为0。
我们在这里用到的温度芯片是DS18B20,关于这款芯片我就不多说了,请大家看我的下面这篇文章。
赶紧点我吧!
按键识别我这里用到的是状态机扫描。关于状态机扫描的话大家也可以参考我下面这篇文章
赶快点我阅读吧
数码管显示,我相信在座各位都掌握得如火纯情了。我也就不多说了!
在这里我分享一下我在设计、和码代码的过程中所遇到的难点。
由于我也很少用状态机扫描来搞键盘,都是最近才用起来的,用过几次就感觉领悟了其中的奥秘了。下面我说一下几个注意事项。
我们在判断状态的时候一定要判断完!不要写到一半就开跑了。并且,该清零的时候就要清零。
把键盘的程序放定时器中断里,每隔10ms执行一次。
对于温度的读取。这个真的是玄学问题。在我单独弄他的时候,必须把中断关了才能让他执行,不然温度读取不了,但是我放在这个大程序里却不用关中断都没问题!真的是玄学问题!
在这里我分享的是主程序,其他导入的模块我就不分享了,网上都能找到的。
#include
#include
#include
#include
#include
#define uint unsigned int
#define uchar unsigned char
#define smg_wei XBYTE[0xc000]
#define smg_duan XBYTE[0xe000]
#define buzz XBYTE[0xa000]
#define LED XBYTE[0x8000]
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
//数码管段码存储
uchar code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
//数码管位码存储
uchar code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//数码管显示缓存
uchar smg_count[]={0xff,0xff,0xbf,0xff,0xff,0xbf,0xff,0xff};
//时间缓存
uchar time_count[]={0x23,0x59,0x50};
//温度缓存
uchar team_count[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc6};
//调整时间数字缓存
uchar set_time_count[]={0x00,0x00,0x00};
uchar flag_S7 = 0,g = 0,flag_set_time = 0,flag_S6 = 0,i = 0;
uint flag_time = 0;
bit flag_alarm = 0;
uint flag_LED_time = 0;
uchar flag_LED1 = 0,flag1_alarm = 0;
//延迟1ms程序
void Delay1ms(uint t) //@12.000MHz
{
unsigned char i, j;
while(t--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
//定时器初始化程序
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
//TR0 = 1; //定时器0开始计时
ET0 = 1; //开启定时器0中断
EA = 1; //打开总中断
}
//数码管显示
void smg_display()
{
static uchar i = 0;
smg_duan = 0xff;
smg_wei = wei[i];
smg_duan = *(smg_count + i);
if(++i == 8)
i = 0;
}
//时间取值
void read_time()
{
uchar *p;
p = read_ds1302();
smg_count[0] = duan[(time_count[0] = *p)>>4];
smg_count[1] = duan[time_count[0]&0x0f];
smg_count[3] = duan[(time_count[1] = *(p + 1))>>4];
smg_count[4] = duan[time_count[1]&0x0f];
smg_count[6] = duan[(time_count[2] = *(p + 2))>>4];
smg_count[7] = duan[time_count[2]&0x0f];
smg_count[2] = smg_count[5] = 0xbf;
}
//读取当前温度值以及处理
uint flag_team = 0;
void read_team()
{
static uchar team;
if(flag_team >= 100)
{
//TR0 = 0;
team = rd_temperature();
//TR0 = 1;
flag_team = 0;
}
smg_count[0] = smg_count[1] = smg_count[2] = smg_count[3] = smg_count[4] = 0xff;
smg_count[7] = team_count[7];
if(team == 85 || team == 0)
{
smg_count[5] = 0xbf;
smg_count[6] = 0xbf;
return;
}
smg_count[5] = team_count[5] = duan[team/10];
smg_count[6] = team_count[6] = duan[team%10];
//strcpy(smg_count,team_count);
}
//键盘处理程序
uchar flag2_but = 0;
void button()
{
if(flag_alarm == 0)
{
static uchar flag1_but = 0;
uchar x = P3;
x = x & 0x0f;
switch(flag1_but)
{
case 0:
if(x != 0x0f)
{
flag1_but = 1;
}
else
{
//P3 = 0xff;
flag1_but = 0;
}
break;
case 1:
if(x != 0x0f)
{
switch(x)
{
case 0x07:
switch(flag_S7) //时钟设置
{
case 1:
if(flag_S7)
{
if(time_count[0] == 0x00)
{
time_count[0] = 0x24;
}
time_count[0]--;
if((time_count[0]&0x0f) == 0x0f)
{
time_count[0] &= 0xf0;
time_count[0] |= 0x09;
}
}
break;
case 2:
if(time_count[1] == 0x00)
{
time_count[1] = 0x60;
}
time_count[1]--;
if((time_count[1]&0x0f) == 0x0f)
{
time_count[1] &= 0xf0;
time_count[1] |= 0x09;
}
break;
case 3:
if(time_count[2] == 0x00)
{
time_count[2] = 0x60;
}
time_count[2]--;
if((time_count[2]&0x0f) == 0x0f)
{
time_count[2] &= 0xf0;
time_count[2] |= 0x09;
}
}
switch(flag_S6) //闹钟设置键盘处理
{
case 1:
if(flag_S6)
{
if(set_time_count[0] == 0x00)
{
set_time_count[0] = 0x24;
}
set_time_count[0]--;
if((set_time_count[0]&0x0f) == 0x0f)
{
set_time_count[0] &= 0xf0;
set_time_count[0] |= 0x09;
}
}
break;
case 2:
if(set_time_count[1] == 0x00)
{
set_time_count[1] = 0x60;
}
set_time_count[1]--;
if((set_time_count[1]&0x0f) == 0x0f)
{
set_time_count[1] &= 0xf0;
set_time_count[1] |= 0x09;
}
break;
case 3:
if(set_time_count[2] == 0x00)
{
set_time_count[2] = 0x60;
}
set_time_count[2]--;
if((set_time_count[1]&0x0f) == 0x0f)
{
set_time_count[2] &= 0xf0;
set_time_count[2] |= 0x09;
}
}
g = 4;break;
case 0x0b:
switch(flag_S7)
{
case 1:
time_count[0]++;
if((time_count[0]&0x0f) >= 0x0a)
{
time_count[0] += 0x10;
time_count[0] &= 0xf0;
}
if(time_count[0] == 0x24)
time_count[0] = 0x00;
break;
case 2:
time_count[1]++;
if((time_count[1]&0x0f) >= 0x0a)
{
time_count[1] += 0x10;
time_count[1] &= 0xf0;
}
if(time_count[1] == 0x60)
time_count[1] = 0x00;
break;
case 3:
time_count[2]++;
if((time_count[2]&0x0f) >= 0x0a)
{
time_count[2] += 0x10;
time_count[2] &= 0xf0;
}
if(time_count[2] == 0x60)
time_count[2] = 0x00;
}
switch(flag_S6)
{
case 1:
set_time_count[0]++;
if((set_time_count[0]&0x0f) >= 0x0a)
{
set_time_count[0] += 0x10;
set_time_count[0] &= 0xf0;
}
if(set_time_count[0] == 0x24)
set_time_count[0] = 0x00;
break;
case 2:
set_time_count[1]++;
if((set_time_count[1]&0x0f) >= 0x0a)
{
set_time_count[1] += 0x10;
set_time_count[1] &= 0xf0;
}
if(set_time_count[1] == 0x60)
set_time_count[1] = 0x00;
break;
case 3:
set_time_count[2]++;
if((set_time_count[2]&0x0f) >= 0x0a)
{
set_time_count[2] += 0x10;
set_time_count[2] &= 0xf0;
}
if(set_time_count[2] == 0x60)
set_time_count[2] = 0x00;
}
g = 5;break;
case 0x0d:
if(flag_S7 == 0)
{
g = 6;
flag_S6++;
}
break;
case 0x0e:if(flag_S6 == 0)
{
g = 7;
flag_S7++;
}
break;
default:g = 0;break;
}
flag1_but = 2;
}
else
{flag1_but = 0;break;}
case 2:
if(x == 0x0f)
{
flag1_but = 0;
}
break;
}
}
//flag2_but = 0;
}
//数码管闪烁以及调整时间
void tiao_time()
{
static uchar cc1 = 0,cc2 = 0;
switch(flag_S7)
{
case 1:
if(flag_time <= 1000)
{
smg_count[0] = 0xff;
smg_count[1] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[0] = duan[time_count[0]>>4];
smg_count[1] = duan[time_count[0]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
case 2:
if(cc1 == 0)
{
smg_count[0] = duan[time_count[0]>>4];
smg_count[1] = duan[time_count[0]&0x0f];
cc1++;
}
if(flag_time <= 1000)
{
smg_count[3] = 0xff;
smg_count[4] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[3] = duan[time_count[1]>>4];
smg_count[4] = duan[time_count[1]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
case 3:
if(cc2 == 0)
{
smg_count[3] = duan[time_count[1]>>4];
smg_count[4] = duan[time_count[1]&0x0f];
cc2++;
}
if(flag_time <= 1000)
{
smg_count[6] = 0xff;
smg_count[7] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[6] = duan[time_count[2]>>4];
smg_count[7] = duan[time_count[2]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
default:
set2_ds1302(time_count[0],time_count[1],time_count[2]);
cc1 = cc2 = 0;
flag_S7 = 0;
}
}
//进入闹钟程序时闪烁程序
void set_tiao_time()
{
static uchar cc1 = 0,cc2 = 0;
switch(flag_S6)
{
case 1:
if(flag_time <= 1000)
{
smg_count[0] = 0xff;
smg_count[1] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[0] = duan[set_time_count[0]>>4];
smg_count[1] = duan[set_time_count[0]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
case 2:
if(cc1 == 0)
{
smg_count[0] = duan[set_time_count[0]>>4];
smg_count[1] = duan[set_time_count[0]&0x0f];
cc1++;
}
if(flag_time <= 1000)
{
smg_count[3] = 0xff;
smg_count[4] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[3] = duan[set_time_count[1]>>4];
smg_count[4] = duan[set_time_count[1]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
case 3:
if(cc2 == 0)
{
smg_count[3] = duan[set_time_count[1]>>4];
smg_count[4] = duan[set_time_count[1]&0x0f];
cc2++;
}
if(flag_time <= 1000)
{
smg_count[6] = 0xff;
smg_count[7] = 0xff;
}
if(flag_time > 1000 && flag_time < 2000)
{
smg_count[6] = duan[set_time_count[2]>>4];
smg_count[7] = duan[set_time_count[2]&0x0f];
}
if(flag_time > 2000)
flag_time = 0;
break;
default:
//set2_ds1302(time_count[0],time_count[1],time_count[2]);
flag_set_time = 0;
g = 0;
i = 0;
cc1 = cc2 = 0;
flag_S6 = 0;
}
}
//设置闹钟程序
void alarm_clock()
{
if(i == 0)
{
smg_count[0] = duan[set_time_count[0]>>4];
smg_count[1] = duan[set_time_count[0]&0x0f];
smg_count[3] = duan[set_time_count[1]>>4];
smg_count[4] = duan[set_time_count[1]&0x0f];
smg_count[6] = duan[set_time_count[2]>>4];
smg_count[7] = duan[set_time_count[2]&0x0f];
smg_count[2] = smg_count[5] = 0xbf;
i++;
}
set_tiao_time();
}
void main()
{
Timer0Init();
buzz = 0x00;
LED = 0xff;
set_ds1302(23,59,50);
P3 = 0xff;
TR0 = 1;
while(1)
{
if(flag_S7 == 0)
read_time();
if((set_time_count[0] == time_count[0]) && (set_time_count[1] == time_count[1]) && (set_time_count[2] == time_count[2]))
{
flag_alarm = 1;
flag1_alarm = time_count[2];
}
// if(flag_alarm == 1)
// {
// if((S4 == 0) || (S5 == 0) || (S6 == 0) || (S7 == 0))
// {
// flag_alarm = 0;
// flag_LED1 = 0;
// flag_LED_time = 0;
// LED = 0xff;
// }
// }
if(flag_S7 != 0)
tiao_time();
while(g == 4 && S4 == 0 && flag_S7 == 0)
read_team();
while(g == 6)
{
flag_set_time = 1;
while(flag_set_time)
alarm_clock();
}
if((flag_alarm == 1) && (flag_LED_time <= 5000)) //(flag_alarm == 1) && (
{
if(flag_LED1 <= 20)
{
LED = 0xfe;
}
else
{
LED = 0xff;
}
}
}
}
//定时器0中断服务函数
void timer0() interrupt 1
{
static uchar flag_but = 0;
flag_but++;
flag_team++;
flag_time++;
if(flag_alarm == 1)
{
flag_LED1++;
flag_LED_time++;
if(flag_LED1 >= 41)
{
flag_LED1 = 0;
}
P3 |= 0x0f;
if((flag_LED_time >= 5000) || ((P3 &0x0f) != 0x0f))
{
flag_alarm = 0;
flag_LED1 = 0;
flag_LED_time = 0;
LED = 0xff;
}
}
if(flag_but == 10)
{
P3 |= 0x0f;
button();
flag_but = 0;
}
smg_display();
}
OK,分享得差不多了,来做个总结吧。这个程序我觉得是我个人一次质的飞跃。为什么呢?
因为这个程序我没有一处用到了延迟程序,这大大得提升了程序的可读性和有效代码的量。这是我很开的一件事。
欢迎来我的博客看看哦!
卿枫博客