设计分段计时功能的秒表

3、分段计时功能的秒表 (25分)设计一个具有分段计时功能的秒表,要求精度为10ms。
(1)实现秒表功能,从0计时到10s,于LCD显示,显示两位小数,到10s
后显示10.00;(使用定时器)(5分)
(2)设计开始及结束键,当开始键按下时,计时开始并通过LCD显示,当结束键按下时.计时结束,通过串口向上位机发送当前时间。(到达10s时计时自动停止)。(5分)
(3)设计暂停键,当按下时,计时暂停,再次按下时计时从当前时间继续。(5 分)
(4)设计分段计时键,当按下时,计时不停止,但是会记录当前时间,待结束键按下或到达计时间后,向上位机发送分段计时次数。同时,上位机可通过串口多次查询分段计时的时间,如发送字符1',单片机向上位机发送第一次分段计时的时间。(10分)

1.实现秒表功能,从0计时到10s,于LCD显示,显示两位小数,到10s后显示10.00;(使用定时器)

#include <reg52.h>

sbit key_start = P3^0;   // 开始键
sbit key_pause = P3^1;   // 暂停键
sbit key_stop = P3^2;    // 停止键

unsigned char code table[] = "0123456789"; // 数码管字符表

unsigned char second;   // 秒数
unsigned char ms;       // 毫秒数
bit pause_flag = 0;     // 暂停标志位

void display(unsigned char num)   // 数码管显示函数
{
    unsigned char shiwei, gewei;    // 十位和个位数字

    shiwei = num / 10;              // 取十位数字
    gewei = num % 10;               // 取个位数字

    P0 = 0;                         // 段码位清零
    P2 = 0x01;                      // 第一位数码管选通
    P0 = table[shiwei];             // 显示十位数字
    delay(1);                       // 延时一段时间
    P2 = 0x02;                      // 第���位数码管选通
    P0 = table[gewei];              // 显示个位数字
    delay(1);                       // 延时一段时间
}

void timer0() interrupt 1          // 定时器0中断服务函数
{
    TH0 = (65536-10000)/256;        // 重新赋值定时器初值,实现10ms的定时
    TL0 = (65536-10000)%256;

    if (!pause_flag)                // 如果不是暂停状态
    {
        ms++;                       // 毫秒数加1
        if (ms == 100)              // 如果毫秒数达到100
        {
            second++;               // 秒数加1
            ms = 0;                 // 毫秒数清零
        }
        if (second == 100)          // 如果秒数达到100
        {
            second = 0;             // 秒数清零
        }
    }

    if (second == 10 && ms == 0)    // 到达10s
    {
        display(100);               // 在数码管上显示10.00
        TR0 = 0;                    // 关闭定时器0
    }
    else                            // 没有到达10s
    {
        display(second);            // 在数码管上显示秒数
        P2 = 0x04;                  // 第三位数码管选通
        P0 = 0x80;                  // 小数点显示
        delay(1);                   // 延时一段时间
        display(ms/10);             // 在数码管上显示毫秒数的十位数字
        P2 = 0x08;                  // 第四位数码管选通
        P0 = table[ms%10];          // 在数码管上显示毫秒数的个位数字
        delay(1);                   // 延时一段时间
    }
}

void delay(unsigned int i)         // 延时函数,i为延时时间
{
    unsigned int j, k;
    for (j = i; j > 0; j--)
        for (k = 112; k > 0; k--);
}

void main()
{
    TMOD = 0x01;                    // 定时器0工作在模式1
    TH0 = (65536-10000)/256;        // 定时器初值
    TL0 = (65536-10000)%256;
    TR0 = 1;                        // 启动定时器0
    ET0 = 1;                        // 允许定时器0中断
    EA = 1;                         // 允许总中断

    while (1)
    {
        if (second == 10 && ms == 0)    // 到达10s
        {
            break;
        }
    }
}

2.设计开始及结束键,当开始键按下时,计时开始并通过LCD显示,当结束键按下时.计时结束,通过串口向上位机发送当前时间。(到达10s时计时自动停止)

#include <reg52.h>
#include <stdio.h>

sbit key_start = P3^0;   // 开始键
sbit key_pause = P3^1;   // 暂停键
sbit key_stop = P3^2;    // 停止键

unsigned char code table[] = "0123456789"; // 数码管字符表

unsigned char second;   // 秒数
unsigned char ms;       // 毫秒数
bit pause_flag = 0;     // 暂停标志位

void display(unsigned char num)   // 数码管显示函数
{
    unsigned char shiwei, gewei;    // 十位和个位数字

    shiwei = num / 10;              // 取十位数字
    gewei = num % 10;               // 取个位数字

    P0 = 0;                         // 段码位清零
    P2 = 0x01;                      // 第一位数码管选通
    P0 = table[shiwei];             // 显示十位数字
    delay(1);                       // 延时一段时间
    P2 = 0x02;                      // 第二位数码管选通
    P0 = table[gewei];              // 显示个位数字
    delay(1);                       // 延时一段时间
}

void timer0() interrupt 1          // 定时器0中断服务函数
{
    TH0 = (65536-10000)/256;        // 重新赋值定时器初值,实现10ms的定时
    TL0 = (65536-10000)%256;

    if (!pause_flag)                // 如果不是暂停状态
    {
        ms++;                       // 毫秒数加1
        if (ms == 100)              // 如果毫秒数达到100
        {
            second++;               // 秒数加1
            ms = 0;                 // 毫秒数清零
        }
        if (second == 100)          // 如果秒数达到100
        {
            second = 0;             // 秒数清零
        }
    }

    if (second == 10 && ms == 0)    // 到达10s
    {
        display(100);               // 在数码管上显示10.00
        TR0 = 0;                    // 关闭定时器0
    }
    else                            // 没有到达10s
    {
        display(second);            // 在数码管上显示秒数
        P2 = 0x04;                  // 第三位数码管选通
        P0 = 0x80;                  // 小数点显示
        delay(1);                   // 延时一段时间
        display(ms/10);             // 在数码管上显示毫秒数的十位数字
        P2 = 0x08;                  // 第四位数码管选通
        P0 = table[ms%10];          // 在数码管上显示毫秒数的个位数字
        delay(1);                   // 延时一段时间
    }
}

void delay(unsigned int i)         // 延时函数,i为延时时间
{
    unsigned int j, k;
    for (j = i; j > 0; j--)
        for (k = 112; k > 0; k--);
}

void main()
{
    TMOD = 0x01;                    // 定时器0工作在模式1
    TH0 = (65536-10000)/256;        // 定时器初值
    TL0 = (65536-10000)%256;
    TR0 = 0;                        // 关闭定时器0
    ET0 = 1;                        // 允许定时器0中断
    EA = 1;                         // 允许总中断

    while (1)
    {
        if (!key_start)             // 开始键按下
        {
            second = 0;             // 秒数清零
            ms = 0;                 // 毫秒数清零
            TR0 = 1;                // 启动定时器0
            printf("Start\r\n");    // 通过串口向上位机发送开始计时的信息
            break;
        }
    }

    while (1)
    {
        if (second == 10 && ms == 0)    // 到达10s
        {
            printf("Time: %d.%02d s\r\n", second, ms);    // 通过串口向上位机发送计时时间
            break;
        }
        if (!key_stop)              // 停止键按下
        {
            TR0 = 0;                // 关闭定时器0
            printf("Stop\r\n");     // 通过串口向上位机发送停止计时的信息
            break;
        }
    }
}

3.设计暂停键,当按下时,计时暂停,再次按下时计时从当前时间继续

#include <reg52.h>
#include <stdio.h>

sbit key_start = P3^0;   // 开始键
sbit key_pause = P3^1;   // 暂停键
sbit key_stop = P3^2;    // 停止键

unsigned char code table[] = "0123456789"; // 数码管字符表

unsigned char second;   // 秒数
unsigned char ms;       // 毫秒数
bit pause_flag = 0;     // 暂停标志位

void display(unsigned char num)   // 数码管显示函数
{
    unsigned char shiwei, gewei;    // 十位和个位数字

    shiwei = num / 10;              // 取十位数字
    gewei = num % 10;               // 取个位数字

    P0 = 0;                         // 段码位清零
    P2 = 0x01;                      // 第一位数码管选通
    P0 = table[shiwei];             // 显示十位数字
    delay(1);                       // 延时一段时间
    P2 = 0x02;                      // 第二位数码管选通
    P0 = table[gewei];              // 显示个位数字
    delay(1);                       // 延时一段时间
}

void timer0() interrupt 1          // 定时器0中断服务函数
{
    TH0 = (65536-10000)/256;        // 重新赋值定时器初值,实现10ms的定时
    TL0 = (65536-10000)%256;

    if (!pause_flag)                // 如果不是暂停状态
    {
        ms++;                       // 毫秒数加1
        if (ms == 100)              // 如果毫秒数达到100
        {
            second++;               // 秒数加1
            ms = 0;                 // 毫秒数清零
        }
        if (second == 100)          // 如果秒数达到100
        {
            second = 0;             // 秒数清零
        }
    }

    if (second == 10 && ms == 0)    // 到达10s
    {
        display(100);               // 在数码管上显示10.00
        TR0 = 0;                    // 关闭定时器0
    }
    else                            // 没有到达10s
    {
        display(second);            // 在数码管上显示秒数
        P2 = 0x04;                  // 第三位数码管选通
        P0 = 0x80;                  // 小数点显示
        delay(1);                   // 延时一段时间
        display(ms/10);             // 在数码管上显示毫秒数的十位数字
        P2 = 0x08;                  // 第四位数码管选通
        P0 = table[ms%10];          // 在数码管上显示毫秒数的个位数字
        delay(1);                   // 延时一段时间
    }
}

void delay(unsigned int i)         // 延时函数,i为延时时间
{
    unsigned int j, k;
    for (j = i; j > 0; j--)
        for (k = 112; k > 0; k--);
}

void main()
{
    TMOD = 0x01;                    // 定时器0工作在模式1
    TH0 = (65536-10000)/256;        // 定时器初值
    TL0 = (65536-10000)%256;
    TR0 = 0;                        // 关闭定时器0
    ET0 = 1;                        // 允许定时器0中断
    EA = 1;                         // 允许总中断

    while (1)
    {
        if (!key_start)             // 开始键按下
        {
            second = 0;             // 秒数清零
            ms = 0;                 // 毫秒数清零
            TR0 = 1;                // 启动定时器0
            printf("Start\r\n");    // 通过串口向上位机发送开始计时的信息
            break;
        }
    }

    while (1)
    {
        if (!pause_flag && key_pause)   // 暂停键按下
        {
            TR0 = 0;                // 关闭定时器0
            pause_flag = 1;         // 设置暂停标志位
            printf("Pause\r\n");    // 通过串口向上位机发送暂停计时的信息
        }
        if (pause_flag && !key_pause)   // 暂停键松开
        {
            TR0 = 1;                // 启动定时器0
            pause_flag = 0;         // 清除暂停标志位
            printf("Resume\r\n");   // 通过串口向上位机发送恢复计时的信息
        }
        if (second == 10 && ms == 0)    // 到达10s
        {
            printf("Time: %d.%02d s\r\n", second, ms);    // 通过串口向上位机发送计时时间
            break;
        }
        if (!key_stop)              // 停止键按下
        {
            TR0 = 0;                // 关闭定时器0
            printf("Stop\r\n");     // 通过串口向上位机发送停止计时的信息
            break;
        }
    }
}

4.设计分段计时键,当按下时,计时不停止,但是会记录当前时间,待结束键按下或到达计时间后,向上位机发送分段计时次数。同时,上位机可通过串口多次查询分段计时的时间,如发送字符1',单片机向上位机发送第一次分段计时的时间

#include <reg52.h>
#include <stdio.h>

sbit key_start = P3^0;   // 开始键
sbit key_pause = P3^1;   // 暂停键
sbit key_stop = P3^2;    // 停止键
sbit key_split = P3^3;   // 分段计时键

unsigned char code table[] = "0123456789"; // 数码管字符表

unsigned char second;   // 秒数
unsigned char ms;       // 毫秒数
bit pause_flag = 0;     // 暂停标志位
unsigned char split_count = 0;  // 分段计时次数
unsigned