单元训练10:定时器实现秒表功能

蓝桥杯 小蜜蜂 单元训练10:定时器实现秒表功能

/*
 * @Description:
 * @Author: fdzhang
 * @Email: zfdc@qq.com
 * @Date: 2024-08-15 21:58:53
 * @LastEditTime: 2024-08-16 18:32:58
 * @LastEditors: fdzhang
 */

#include "stc15f2k60s2.h"

#define LED(x)                 \
    {                          \
        P2 = P2 & 0x1f | 0x80; \
        P0 = x;                \
        P2 &= 0x1f;            \
    }
// y7c 111,0xE0
#define SEG(x)                 \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1f | 0xE0; \
        P2 &= 0x1f;            \
    }
// y6c 110,0xC0
#define COM(x)                 \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1f | 0xC0; \
        P2 &= 0x1f;            \
    }

typedef unsigned char uint8_t;

typedef struct swInfo // 使用结构体将需要的分、秒、毫秒记录
{
    uint8_t min10; // 分10位
    uint8_t min1;  // 分个位
    uint8_t sec10; // 秒10位
    uint8_t sec1;  // 秒个位
    uint8_t ms10;  // 毫秒10位
    uint8_t ms1;   // 毫秒个位
} StructStopWatch;

StructStopWatch stopWatchTimer;

StructStopWatch setStopWatch(uint8_t min10, uint8_t min1, uint8_t sec10, uint8_t sec1, uint8_t ms10, uint8_t ms1)
{
    StructStopWatch stopWatchTimer;
    stopWatchTimer.min10 = min10;
    stopWatchTimer.min1 = min1;
    stopWatchTimer.sec10 = sec10;
    stopWatchTimer.sec1 = sec1;
    stopWatchTimer.ms10 = ms10;
    stopWatchTimer.ms1 = ms1;
    return stopWatchTimer;
}

uint8_t com1 = 0x01; // 定义数码管的8个口
uint8_t com2 = 0x02;
uint8_t com3 = 0x04;
uint8_t com4 = 0x08;
uint8_t com5 = 0x10;
uint8_t com6 = 0x20;
uint8_t com7 = 0x40;
uint8_t com8 = 0x80;

sbit s4 = P3 ^ 3; // 定义按键
sbit s5 = P3 ^ 2;

code unsigned char Seg_Table[] =
    {
        0xc0, // 0
        0xf9, // 1
        0xa4, // 2
        0xb0, // 3
        0x99, // 4
        0x92, // 5
        0x82, // 6
        0xf8, // 7
        0x80, // 8
        0x90, // 9
        0xBF  // 符号"-"
};

// typedef unsigned int uint32_t; //如果要长计数,需要用到32位定义
uint8_t timerCounter = 0;
uint8_t counter50ms = 0;
uint8_t counter1s = 0;
uint8_t counter1min = 0;
uint8_t counter1h = 0;

void Timer0_Init(void) // 5毫秒@12MHz
{
    AUXR |= 0x80; // 定时器时钟1T模式
    TMOD &= 0xF0; // 设置定时器模式
    TL0 = 0xA0;   // 设置定时初始值
    TH0 = 0x15;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    // TR0 = 1;      // 定时器0开始计时 //因为题目要求可以暂停,所以一开始不要打开
    ET0 = 1; // 使能定时器0中断
    EA = 1;
}
// 使用STC - ISP中的延时计算器生成,
// 不想再使用定时器1生成时间间隔了,有些麻烦。
// 注意,延时500us会有重影
void Delay1ms() //@12.000MHz 使用STC-ISP中的延时计算器生成
{
    unsigned char i, j;
    i = 2;
    j = 239;
    do
    {
        while (--j)
            ;
    } while (--i);
}

void oneSegShow(uint8_t comX, uint8_t showNum) // 单数码管显示
{
    COM(comX);
    SEG(Seg_Table[showNum]);
}
void min10Seg1(uint8_t min10) // 1管显示分10位
{
    oneSegShow(com1, min10);
}
void min1Seg2(uint8_t min1) // 2管显示分个位
{
    oneSegShow(com2, min1);
}
void dashSeg3() // 3管显示符号-
{
    oneSegShow(com3, 10);
}
void sec10Seg4(uint8_t sec10) // 4管显示秒10位
{
    oneSegShow(com4, sec10);
}
void sec1Seg5(uint8_t sec1) // 5管显示秒个位
{
    oneSegShow(com5, sec1);
}
void dashSeg6() // 6管显示符号-
{
    oneSegShow(com6, 10);
}
void ms10Seg7(uint8_t ms10) // 7管显示毫秒10位
{
    oneSegShow(com7, ms10);
}
void ms1Seg8(uint8_t ms1) // 8管显示毫秒个位
{
    oneSegShow(com8, ms1);
}
// 全部显示方式之一
void segsAllSequenceDisplay(StructStopWatch stopWatchTimer)
{
    min10Seg1(stopWatchTimer.min10);
    Delay1ms();
    min1Seg2(stopWatchTimer.min1);
    Delay1ms();
    dashSeg3();
    Delay1ms();
    sec10Seg4(stopWatchTimer.sec10);
    Delay1ms();
    sec1Seg5(stopWatchTimer.sec1);
    Delay1ms();
    dashSeg6();
    Delay1ms();
    ms10Seg7(stopWatchTimer.ms10);
    Delay1ms();
    ms1Seg8(stopWatchTimer.ms1);
    Delay1ms();
}

uint8_t arrayStatus;                                // 状态机显示方式
void segsAllShowFSM(StructStopWatch stopWatchTimer) // Finite state machine
{
    switch (arrayStatus)
    {
    case 0:
        min10Seg1(stopWatchTimer.min10);
        Delay1ms();
        arrayStatus = 1;
        break;
    case 1:
        min1Seg2(stopWatchTimer.min1);
        Delay1ms();
        arrayStatus = 2;
        break;
    case 2:
        dashSeg3();
        Delay1ms();
        arrayStatus = 3;
        break;
    case 3:
        sec10Seg4(stopWatchTimer.sec10);
        Delay1ms();
        arrayStatus = 4;
        break;
    case 4:
        sec1Seg5(stopWatchTimer.sec1);
        Delay1ms();
        arrayStatus = 5;
        break;
    case 5:
        dashSeg6();
        Delay1ms();
        arrayStatus = 6;
        break;
    case 6:
        ms10Seg7(stopWatchTimer.ms10);
        Delay1ms();
        arrayStatus = 7;
        break;
    case 7:
        ms1Seg8(stopWatchTimer.ms1);
        Delay1ms();
        arrayStatus = 0;
        break;

    default:
        arrayStatus = 0;
        break;
    }
}

uint8_t s4Status;
uint8_t falling;
uint8_t counterOnOff = 0;

uint8_t keyStatus;
uint8_t keyValue;

void readKey()
{
    switch (keyStatus)
    {
    case 0:
        if ((s4 == 0) | (s5 == 0))
        {
            keyStatus = 1;
            falling = 1;
            keyStatus = 1;
        }
        break;
    case 1:
        if (s5 == 0)
        {
            keyValue = 5;
        }
        else if (s4 == 0)
        {
            keyValue = 4;
        }
        if (falling)
        {
            counterOnOff = ~counterOnOff;
        }
        if ((s4 == 0) | (s5 == 0)) // 如果长按锁定在当前状态
        {
            falling = 0;
            keyStatus = 1;
        }
        else
            keyStatus = 2;
        break;
    case 2:
        if ((s4 == 1) && (s5 == 1))
            keyStatus = 0;
    default:
        keyStatus = 0;
        break;
    }
}
void keyScan()
{
    StructStopWatch swInfo;
    uint8_t ms10;
    uint8_t ms1;
    uint8_t sec10;
    uint8_t sec1;
    uint8_t min10;
    uint8_t min1;
    readKey();

    if (keyValue == 5)
    {

        timerCounter = 0; // 清零
        counter50ms = 0;
        counter1s = 0;
        counter1min = 0;
        counter1h = 0;

        ms10 = counter50ms / 10;
        ms1 = counter50ms % 10;
        sec10 = counter1s / 10;
        sec1 = counter1s % 10;
        min10 = counter1min / 10;
        min1 = counter1min % 10;

        swInfo = setStopWatch(min10, min1, sec10, sec1, ms10, ms1);
        segsAllShowFSM(swInfo);
    }
    else if (keyValue == 4)
    {
        ms10 = counter50ms / 10;
        ms1 = counter50ms % 10;
        sec10 = counter1s / 10;
        sec1 = counter1s % 10;
        min10 = counter1min / 10;
        min1 = counter1min % 10;

        swInfo = setStopWatch(min10, min1, sec10, sec1, ms10, ms1);
        segsAllShowFSM(swInfo);

        if (counterOnOff)
        {
            TR0 = 1; // open timer启动恢复
        }
        else
        {
            TR0 = 0; // pause timer//暂停
        }
    }
}
void main()
{
    LED(0xff); // 关闭LED
    COM(0xFF); // 关闭数码管

    // SEG(Seg_Table[0]);

    Timer0_Init();

    while (1)
    {
        keyScan();
    }
}

void Timer0_Isr(void) interrupt 1
{
    if (++timerCounter == 10) // 5毫秒为基本单位,50ms为一个计时单元
    {
        timerCounter = 0;
        if (++counter50ms == 20) // 1s
        {
            counter50ms = 0;       // 数码管显示的毫秒的数值
            if (++counter1s == 60) // 1min
            {
                counter1s = 0;           // 数码管显示的秒的数值
                if (++counter1min == 60) // 1h
                {
                    counter1min = 0; // 数码管显示的分的数值
                }
            }
        }
    }
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zfdc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值