Chen_HDF 2024-05-02 20:54 采纳率: 0%
浏览 8
已结题

AT89C51控制8位八段数码管显示时钟。

img

img

img

img

img

img

模拟电路图如图所示:
启动仿真后数码管显示初始时间:假设12-34-56
按下一拖三的开关P10,可以选择调节时,还是分还是秒。按一下调时,按两下调分钟,按三下调秒。按4下回到时。调整时的时候只有时的两位数显示,其他不显示,同理分和秒也是一样的。
如果按一下的情况下再按P11,则对应钟表数加一。
按下 P12后退出调整。数码管显示全部时间。并秒闪烁加一,跟真实的时间一样增加。
接线要和图片中一样。

img

  • 写回答

7条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-02 20:54
    关注

    引自免费微信小程序:皆我百晓生

    为了实现您的需求,我们首先需要明确几个关键点:

    1. 时钟初始化:在程序开始时,设定一个初始时间(例如12小时34分56秒)。
    2. 按键控制逻辑:P10键用于切换调整模式(时、分、秒),P11键用于递增当前被调整的时间单位,P12键用于确认调整并使秒开始闪烁计数。
    3. 数码管显示:根据当前时间和调整模式,动态显示相应的数字,并处理秒的闪烁效果。
    4. 硬件连接:确保硬件连接与Proteus中的设计相匹配,这里主要关注P10、P11、P12以及数码管的控制。

    硬件连接确认

    • AT89C51的P0口通过上拉电阻连接到数码管的段选线(a~g, dp)。
    • P2口的部分引脚(如P2.0至P2.7)可能用于控制数码管的位选线,具体取决于您实际的数码管连接方式。
    • P10、P11、P12分别用于调整模式选择、时间增加和退出调整模式。

    软件实现步骤

    1. 初始化设置

    #include<reg51.h>
    
    unsigned char DispCode[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0-9,A,b,C,d,E,F
                                   0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //G,H,I,J,K,L,.,-, 
    
    unsigned char Time[3] = {12, 34, 56}; // 初始时间为12:34:56
    char AdjustMode = 0; // 0-时,1-分,2-秒,用于记录当前调整的模式
    bit FlashFlag = 0; // 用于控制秒的闪烁
    
    void Delay(unsigned int i);
    void DisplayTime();
    void IncTime(char mode);
    
    void main()
    {
        // 初始化
        P0 = 0xff; // 确保段选线默认为高电平
        P2 = 0x01; // 假设先点亮第一个数码管
    
        while(1)
        {
            // 检查调整模式按键P10
            if(P10 == 0) // 按下P10
            {
                Delay(10); // 去抖动
                if(P10 == 0)
                {
                    AdjustMode = (AdjustMode + 1) % 3; // 循环切换调整模式
                    Delay(200); // 模式切换后等待一段时间
                }
            }
    
            // 检查时间增加按键P11
            if(P11 == 0)
            {
                Delay(10); // 去抖动
                if(P11 == 0)
                {
                    IncTime(AdjustMode); // 根据当前模式递增时间
                }
            }
    
            // 检查退出调整模式按键P12
            if(P12 == 0)
            {
                Delay(10); // 去抖动
                if(P12 == 0)
                {
                    FlashFlag = 1; // 开启秒闪烁,模拟真实时间计数
                }
            }
    
            DisplayTime(); // 显示当前时间
        }
    }
    

    2. 显示时间函数

    void DisplayTime()
    {
        static unsigned char digit = 0; // 记录当前显示的数码管位
        static unsigned char secDisplay = Time[2]; // 用于处理秒的闪烁
    
        // 根据FlashFlag控制秒的显示是否闪烁
        if(FlashFlag && digit == 2) // 秒位且允许闪烁
        {
            if(_crol_(0x80, digit)) // 使用闪烁标志控制显示
                P0 = DispCode[secDisplay];
            else
                P0 = 0xff; // 关闭该位显示
        }
        else
        {
            P0 = DispCode[Time[digit]]; // 正常显示
        }
    
        P2 = 0x01 << digit; // 位选,点亮对应的数码管
        digit = (digit + 1) % 4; // 循环显示所有位
    
        // 控制数码管刷新频率
        Delay(5);
    }
    
    void IncTime(char mode)
    {
        Time[mode]++;
        if(mode == 0 && Time[mode] > 23) Time[mode] = 0; // 时钟调整
        if(mode == 1 && Time[mode] > 59) Time[mode] = 0; // 分钟调整
        if(mode == 2 && Time[mode] > 59) Time[mode] = 0; // 秒钟调整
    }
    

    3. 延时函数

    void Delay(unsigned int i)
    {
        while(i--)
        {
            _nop_(); _nop_(); _nop_(); _nop_();
            _nop_(); _nop_(); _nop_(); _nop_();
        }
    }
    

    注意事项

    • 以上代码是一个基础框架,具体细节(如去抖动、数码管硬件接口等)需根据实际硬件电路进行调整。
    • 确保硬件连接与代码中对端口的操作相匹配。
    • 数码管的段选线控制和位选线控制应根据实际连接方式进行调整。
    • 实际应用中可能还需要考虑低功耗设计、时间准确性等问题。
    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月2日
  • 创建了问题 5月2日

悬赏问题

  • ¥15 使用ESP8266连接阿里云出现问题
  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角