冲刺单片机设计与开发 4.3 驱动数码管 4.3.5练习提升2

4.3.5练习提升

1、固定使用2位数码管显示60s倒计时,高位数码管熄灭。

2、数码管最高位显示固定字符U,固定使用2位数码管显示60s倒计时,高位数码管熄灭。倒计时结束5s后,重新开始 倒计时。计时过程中指示灯L1点亮,L2熄灭,计时结束后L1熄灭,L2以0.1s为间隔切换亮灭状态。其余指示灯均处于 熄灭状态。

实例要求

/*
 * @Description:
 * @Author: fdzhang
 * @Email: zfdc@qq.com
 * @Date: 2024-08-19 07:55:08
 * @LastEditTime: 2024-08-19 11:45:44
 * @LastEditors: fdzhang
 */
#include "stc15f2k60s2.h"
#include "intrins.h"

typedef unsigned char uint8_t;

uint8_t Led2Info = 0xFD; // led 2 on
uint8_t ledInfo;

uint8_t basicTimerCounter = 0;   // 基础 计时计数
uint8_t Sec1TimerCounter = 0;    // 1s计数
uint8_t sec5GapTimerCounter = 0; // 间隔5s计数,实际达到6s
uint8_t boolCounterDot1s = 0;    // 达到0.1s
uint8_t boolCounter1s = 0;       // 达到1s
uint8_t boolCounter5sGap = 0;    // 达到5s

uint8_t secStatus = 0;
uint8_t countDownStatus = 0;

#define lightLED(x)            \
    {                          \
        P2 = P2 & 0x1f | 0x80; \
        P0 = x;                \
        P2 &= 0x1f;            \
    }
#define lightSEG(x)            \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1f | 0xe0; \
        P2 &= 0x1f;            \
    }
#define lightCOM(x)            \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1f | 0xc0; \
        P2 &= 0x1f;            \
    }
// 定义控制蜂鸣器
#define Buzz(x)                \
    {                          \
        P0 = x;                \
        P2 = P2 & 0x1F | 0xA0; \
        P2 &= 0x1F;            \
    }
#define L1 0xFE // 定义LED 1
#define L2 0xFD

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
        0x88, // A10
        0x83, // b11
        0xc6, // C12
        0xa1, // d13
        0x86, // E14
        0x8e, // F15
        0xc1, // 符号 U,16
        0xff  // all off,17
};
void Timer0_Init(void) // 5毫秒@12.000MHz
{
    AUXR |= 0x80; // 定时器时钟1T模式
    TMOD &= 0xF0; // 设置定时器模式
    TL0 = 0xA0;   // 设置定时初始值
    TH0 = 0x15;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时
    ET0 = 1;      // 使能定时器0中断
    EA = 1;
}

void Delay1ms() //@12.000MHz
{
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
        while (--j)
            ;
    } while (--i);
}

void lightL1() // 点亮L1
{
    lightLED(L1);
}
uint8_t blinkStatus;
void blinkL2() // L2闪烁
{
    ledInfo = Led2Info;
    switch (blinkStatus)
    {
    case 0:
        if (boolCounterDot1s) // 1秒翻转
        {
            lightLED(ledInfo);
            blinkStatus = 1;
            boolCounterDot1s = 0;
        }
        break;
    case 1:
        if (boolCounterDot1s)
        {
            ledInfo ^= ~Led2Info;
            lightLED(ledInfo);
            blinkStatus = 0;
            boolCounterDot1s = 0;
        }
        break;
    default:
        blinkStatus = 0;
        break;
    }
}
void showU() // 显示字符U
{
    lightCOM(0x01);
    lightSEG(Seg_Table[16]);
    Delay1ms();
    Delay1ms();
}

void showSec10(uint8_t sec10) // 秒10位显示
{
    lightCOM(0x40);
    lightSEG(Seg_Table[sec10]);
    Delay1ms();
}
void showSec1(uint8_t sec1) // 秒个位显示
{
    lightCOM(0x80);
    lightSEG(Seg_Table[sec1]);
    Delay1ms();
}

void showSeconds(uint8_t seconds)
{
    switch (secStatus)
    {
    case 0:
        showU();
        lightL1();
        secStatus = 1;
        break;
    case 1:
        showSec10(seconds / 10);
        secStatus = 2;
        break;
    case 2:
        showSec1(seconds % 10);
        secStatus = 0;
        break;
    default:
        secStatus = 0;
        break;
    }
}

void secCountDown(uint8_t seconds)
{
    switch (countDownStatus)
    {
    case 0: // 60s倒计时
        while (1)
        {
            showSeconds(seconds);
            if (boolCounter1s)
            {
                seconds--;
                boolCounter1s = 0;
                if (seconds == -1)
                    break;
            }
        }
        countDownStatus = 1;
        boolCounter5sGap = 0;
        break;
    case 1:
        if (!boolCounter5sGap) // 间隔5s,L2以0.1s切换亮灭
        {
            showU();
            blinkL2();
        }
        else
        {
            countDownStatus = 0;
        }
        break;
    }
}
void main()
{
    Timer0_Init();
    lightLED(0xff);
    while (1)
    {
        secCountDown(60);
    }
}

void Timer0_Isr(void) interrupt 1
{
    // 5毫秒@12.000MHz,0.1s,100ms,计20次
    if (basicTimerCounter++ == 20)
    {
        basicTimerCounter = 0;
        boolCounterDot1s = 1; // 0.1s
        // 5毫秒@12.000MHz,1s,1000ms,计200次
        // 0.1秒@12.000MHz,1s,10*0.1s,计10次
        if (Sec1TimerCounter++ == 10) // 1s
        {
            Sec1TimerCounter = 0;
            boolCounter1s = 1;
            if (sec5GapTimerCounter++ == 6) // 计到6秒,间隔5s
            {
                sec5GapTimerCounter = 0;
                boolCounter5sGap = 1;
            }
        }
    }
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zfdc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值