2021年上半年单片机测试参考答案

2021年上半年单片机测试题

#include "reg52.h"

typedef unsigned int uint;
typedef unsigned char uchar;

#define dynamic_digital P0 //定义段选IO

sbit SRA = P2^2;
sbit SRB = P2^3;
sbit SRC = P2^4;

sbit k1 = P1^0; //set 设置
sbit k2 = P1^1; //puls +
sbit k3 = P1^2; //minus -
sbit k4 = P1^3; //finish 退出 
sbit k5 = P1^4; //switch 切换
sbit k6 = P1^5; //start 计时
sbit k7 = P1^6; //stop 暂停
sbit k8 = P1^7; //reset 重置

uint time = 0;          //定时器0的计数值(单位:50ms)
//-------------------------------23:59:50
char hour = 23;         //时钟单位
char minute = 59;       //时钟单位
char second = 50;       //时钟单位

uint time_stopwatch = 0;                    //定时器1的计数值(单位:2ms)

uchar minute_stopwatch = 0;             //秒表的分钟单位(min)
uchar second_stopwatch = 0;             //秒表的秒钟单位(s)
uchar microsecond_stopwatch = 0;    //秒表的毫秒单位(最小10ms)

uchar mode = 0;             //时钟设置标志位:set hour/minute
uchar function = 0;     //功能选择:         时钟/秒表
uchar flag = 0;             //秒表设置标志位:start/stop/reset

uchar DisplayData[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴:0~9 -

// 延时
void delay(uint i)
{
    while(i--);
}

/************************************************************
 数码管显示:位选 + 段选
 同时附带时钟设置时需要闪烁的效果
************************************************************/
void display_select(uchar pos,uchar dat) // 数码管位选
{
    switch (pos)
    {
        case 0: 
            SRA=0;SRB=0;SRC=0;  //000 第0号管
            break;
        case 1:
            SRA=1;SRB=0;SRC=0;  //001 第1号管
            break;
        case 2:
            SRA=0;SRB=1;SRC=0;  //010 第2号管
            break;
        case 3:
            SRA=1;SRB=1;SRC=0;  //011 第3号管
            break;
        case 4:
            SRA=0;SRB=0;SRC=1;  //100 第4号管
            break;
        case 5:
            SRA=1;SRB=0;SRC=1;  //101 第5号管
            break;
        case 6:
            SRA=0;SRB=1;SRC=1;  //110 第6号管
            break;
        case 7:
            SRA=1;SRB=1;SRC=1;  //111 第7号管
            break;  
    }
    if(mode==0) //正常亮
    {
        dynamic_digital = dat;
        delay(8);
        dynamic_digital = 0x00;
    }
    if(mode==1)     // 设置hour时,闪烁
        if(pos==0 || pos==1)
        {
            if(time<10)
            {
                dynamic_digital = dat;
                delay(8);
                dynamic_digital = 0x00;
            }
        }
        else    //正常亮
        {
            dynamic_digital = dat;
            delay(8);
            dynamic_digital = 0x00;
        }
    else if(mode==2)    // 设置minute时,闪烁
        if(pos==3 || pos==4)
        {
            if(time<10)         
            {
                dynamic_digital = dat;  
                delay(8);
                dynamic_digital = 0x00;     
            }
        }
        else    //正常亮
        {
            dynamic_digital = dat;
            delay(8);
            dynamic_digital = 0x00;
        }
    //delay(8);
    //dynamic_digital = 0x00;
    //delay(91);
}

// 显示时钟内容
void display()
{
    display_select(0,DisplayData[hour/10]);     //显示hour---------------------
    display_select(1,DisplayData[hour%10]);

    display_select(2,DisplayData[10]);              //显示分隔符'-'----------------

    display_select(3,DisplayData[minute/10]);   //显示minute-------------------
    display_select(4,DisplayData[minute%10]);

    display_select(5,DisplayData[10]);              //显示分隔符'-'----------------

    display_select(6,DisplayData[second/10]); //显示second-------------------
    display_select(7,DisplayData[second%10]);
}

// 显示秒表内容
void display_stopwatch()
{
    display_select(0,DisplayData[minute_stopwatch/10]);             //显示minute---------------------
    display_select(1,DisplayData[minute_stopwatch%10]);

    display_select(2,DisplayData[10]);                                              //显示分隔符'-'----------------

    display_select(3,DisplayData[second_stopwatch/10]);             //显示second-------------------
    display_select(4,DisplayData[second_stopwatch%10]);

    display_select(5,DisplayData[10]);                                              //显示分隔符'-'----------------

    display_select(6,DisplayData[microsecond_stopwatch/10]);    //显示microsecond-------------------
    display_select(7,DisplayData[microsecond_stopwatch%10]);
}

// 秒表功能
void stopwatch()
{
    // reset
    if(flag==0)
    {
        minute_stopwatch = 0;
        second_stopwatch = 0;
        microsecond_stopwatch = 0;  //单位是10ms
    }
    // start
    else if(flag==1)
    {
        microsecond_stopwatch = time_stopwatch/5;
        if(microsecond_stopwatch>=100)
        {
            time_stopwatch = 0;
            microsecond_stopwatch = 0;
            second_stopwatch++;
            if(second_stopwatch>=60)
            {
                second_stopwatch = 0;
                minute_stopwatch++;
                if(minute_stopwatch>=100)
                    minute_stopwatch = 0;
            }
        }
    }
}

/**************************************************************
    S1:时钟设置     S2:hour++       S3;minute++     S4:finish
    S5:时钟/秒表        S6:秒表计时 S7:秒表暂停     S8:秒表复位
***************************************************************/
void key_scan()
{
    if(k5==0)
    {
        delay(1000);
        if(k5==0)
            function = ~function;
        while(!k5);
    }

    if(function==0) //function=0    时钟模式
    {   
        flag = 0;   //  重置秒表设置标志位,方便下次使用

        if(k1==0)   // set 设置调节模式
        {
            delay(1000);
            if(k1==0)
                mode++;     
            if(mode>2)
                mode = 1;
            //led=~led;
            while(!k1);
        }

        if(mode!=0)
        {
            if(k2==0) // puls +1
            {
                delay(1000);
                if(k2==0)
                    if(mode==1) // 设置hour
                        hour++;
                    else if(mode==2)    //设置minute
                        minute++;
                while(!k2);
            }

            if(k3==0) // minus -1
            {
                delay(1000);
                if(k3==0)
                    if(mode==1) //设置hour
                        hour--;
                    else if(mode==2)    //设置minute
                        minute--;
                while(!k3);
            }

            if(k4==0) // back 退出设置模式
            {
                delay(1000);
                if(k4==0)
                    mode = 0;
                while(!k4);
            }
        }
    }   
    else    //function=1    秒表模式
    {
        mode = 0;   //  重置时钟模式,方便下次使用

        if(k6==0)   // start
        {
            delay(1000);
            if(k6==0)
                flag = 1;
            //led=~led;
            while(!k6);
        }

        if(k7==0)   //  stop
        {
            delay(1000);
            if(k7==0)
                flag = 2;
            while(!k7);
        }

        if(k8==0)   //  reset
        {
            delay(1000);
            if(k8==0)
                flag = 0;
            while(!k8);
      }
    }
}

//  定时器0初始化
void Timer0Init()
{
    TMOD|=0x01; //选择定时器0模式,工作方式:仅用TR0打开启动
    TH0=0x3C;   //给定时器0赋初值,定时50ms
    TL0=0xB0;
    ET0=1;      //打开定时器0中断允许
    EA=1;       //打开总允许
    TR0=1;      //打开定时器0
}

//  定时器1初始化
void Timer1Init()
{
    TMOD|=0x10; //选择定时器1模式,8位自动重装载,仅用TR1打开启动 
    TH1=0xF8;   //给定时器1赋初值,定时2ms
    TL1=0x30;
    ET1=1;      //打开定时器0中断允许
    EA=1;       //打开总允许
    TR1=1;      //打开定时器0
}

/********************************************************************
    完整实现试题所有功能
    两个定时器的使用仍然有一点瑕疵,如果使用定时器+DS1302可能会更好
********************************************************************/
void main()
{
    Timer0Init();       //定时器0初始化
    Timer1Init();       //定时器1初始化

    while(1)
    {
        key_scan();     //扫描按键变化
        if(function!=0)
        {
            mode = 0;    //重置时钟模式
            stopwatch(); //秒表
        }
    }
}

/****************************************************************
    定时器0中断
    功能:累计时钟数值,即使在秒表功能下,时钟仍然累计
****************************************************************/
void Time0() interrupt 1
{
    TH0=0x3C;   //  定时50ms
    TL0=0xB0;
    time++;
    //display();    //0.5ms
    if(time==20)    //定时1s
    {
        second++;
        time = 0;
        if(second>=60)
        {
            minute++;
            second = 0;
        }
        if(minute>=60) //   60分钟进1位
        {
            hour++;
            minute = 0;
        }
        else if(minute<0)
        {
            hour--;
            minute = 59;
        }
        if(hour>=24)    // 24小时进1位          
            hour = 0;
        else if(hour <0)
            hour = 23;
    }   
}

/****************************************************
    定时器1中断:数码管的定时显示
    功能:可防止数码管因长时间按住按键导致主线程
                卡在检测按键的while循环而熄灭
****************************************************/
void Time1() interrupt 3 
{
    TH1=0xF8;   //给定时器1赋初值,定时2ms
    TL1=0x30;

    if(flag==0)
        time_stopwatch = 0;
    if(function==0)
        display();
    else
    {
        if(flag==1)
            time_stopwatch++;
        display_stopwatch();
    }
}

文末链接为本题的分文件写法,更推荐使用分文件写法!

相关文件下载地址
©下载资源版权归作者所有;本站所有资源均来源于网络,仅供学习使用,请支持正版!

暂无评论

相关推荐

微信扫一扫,分享到朋友圈

2021年上半年单片机测试参考答案