杂谈

经过几个小时的奋战,我终于又把蓝桥杯的第八届省赛的题给做出来了!开心!
不过呢我已经做出来几天了,只是一直没有贴在博客里。今天刚好无聊我就贴上来了!
话不多说,我们进入正题

题目

我们先来看下题目吧。

一、基本要求

1.1 使用 CT107D 单片机竞赛板,完成“电子钟”功能的程序设计与调试;
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”;
1.3 Keil 工程文件以准考证号命名,完成设计后,提交完整、可编译的 Keil工程文件到服务器。

二、硬件框图

1.png

三、功能描述

3.1 初始化

1)关闭蜂鸣器、继电器等无关外设;
2)设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒。

3.2 显示功能

34AEBB75-0277-4AC1-A70D-1676606408C2.png

3.3 按键功能

1)按键 S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭,时、分、秒的调整需注意数据边界属性。
2F354A3E-197C-4F36-B8EA-E8E4972E4C58.png

2)按键 S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置功能,数码管显示当前设定的闹钟时间。
3)按键 S5 定义为“加”按键,在“时钟设置”或“闹钟设置”状态下,每次按下该按键当前选择的单元(时、分或秒)增加 1 个单位。
4)按键 S4 定义为“减”按键,在“时钟设置”或“闹钟设置”状态下,每次按下该按键当前选择的单元(时、分或秒)减少 1 个单位。
5)按键功能说明:按键 S4、S5 的“加”、“减”功能只在“时钟设置”或“闹钟设置”状态下有效;在 “时钟显示”状态下,按下 S4 按键,显示温度数据,松开按键,返回“时钟显示”界面。

3.4 闹钟提示功能

1)指示灯 L1 以 0.2 秒为间隔闪烁,持续 5 秒钟;
2)闹钟提示状态下,按下任意按键,关闭闪烁提示功能。

思路

在这里我大致说一下我的思路。

1、初始化

这个很简单的。时间显示23:59:50
这里时间芯片用的DS13B02,这款芯片我就不用多说了,大家都知道怎么个用法。
时钟的初始化我们需要把23:59:50先写入DS18B20,然后才能正常的从所设置的时间开始显示。
然后就是闹钟的初始化,我们这里直接在定义闹钟的变量的时候就直接给他赋值为0。

2、温度显示

我们在这里用到的温度芯片是DS18B20,关于这款芯片我就不多说了,请大家看我的下面这篇文章。

3、按键检测

按键识别我这里用到的是状态机扫描。关于状态机扫描的话大家也可以参考我下面这篇文章

4、数码管显示

数码管显示,我相信在座各位都掌握得如火纯情了。我也就不多说了!

难点汇总

在这里我分享一下我在设计、和码代码的过程中所遇到的难点。

1、状态机扫描

由于我也很少用状态机扫描来搞键盘,都是最近才用起来的,用过几次就感觉领悟了其中的奥秘了。下面我说一下几个注意事项。

Step.1

我们在判断状态的时候一定要判断完!不要写到一半就开跑了。并且,该清零的时候就要清零。

Step.2

把键盘的程序放定时器中断里,每隔10ms执行一次。

2、温度读取

对于温度的读取。这个真的是玄学问题。在我单独弄他的时候,必须把中断关了才能让他执行,不然温度读取不了,但是我放在这个大程序里却不用关中断都没问题!真的是玄学问题!

问题应该只有以上这些了,下面我就贴出来代码。有不懂得可以给我留言哟!

代码分享

#include <reg52.h>
#include <intrins.h>
#include <onewire.h>
#include <DS1302.h>
#include <absacc.h>

#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,分享得差不多了,来做个总结吧。这个程序我觉得是我个人一次质的飞跃。为什么呢?
因为这个程序我没有一处用到了延迟程序,这大大得提升了程序的可读性和有效代码的量。这是我很开的一件事。

最后,感谢观看。。。。。

Last modification:March 5th, 2020 at 10:06 pm
如果觉得我的文章对你有用,请随意赞赏