晓飛飛 发表于 2025-6-15 10:36:52

简简单单用 8H4K64TL 做个段码时钟

大概思路如下:

[*]用 8H4K64TL 驱动0.8英寸的白色LED数码管,数码管型号为8402AW,为共阴极4位8段结构,跳秒冒号占用第二位的DP,其余位DP无功能
[*]PWM3差分输出直驱4KHz的压电蜂鸣器,虽然响度有所欠缺,但做闹钟也能凑合用了,胜在功耗很低
[*]片外SD3078RTC芯片,产生2Hz中断提供刷秒信号,预留外部32.768KHz晶体后续开发精简版
[*]四路功能按键,暂时用于设置时间,后续用于闹钟之类的
[*]TP4057充电,1200mAh长条电池,充一次电续航一周没问题,目前LED亮度调至最低显示效果尚可。
[*]ECJ22091一键开关机

PS:做LED单色点阵和段码一定一定要加半透明盖板,用薄的灰黑色亚克力效果就不错,参考如下视频。
803







晓飛飛 发表于 2025-6-15 10:43:03

主函数代码如下:
void main(void)
{
        EAXSFR();
        GPIO_config();       
        LED_config();
        Timer0_Init();
        RTC_Init();
        Ext_Init();
        EA = 1;
        LEDCTRL |= 0x80;//启动段码
        while(1)
        {               
                switch(work_mode)
                {
                        case 0: //正常模式
                                if(RTC_flag)//显示小时和分钟,冒号跳秒
                                {
                                        RTC_flag = 0;
                                        ReadDate();
                                        i_hour = date_buf & 0x3F;
                                        i_min = date_buf & 0x7F;       
                                        if(i_hour & 0xf0)        COM0_DC_L = SEG_tab;//十位的零消隐
                                        else COM0_DC_L = 0x00;
                                        if(dot)COM1_DC_L = SEG_tab | 0x80;//刷冒号
                                        else       COM1_DC_L = SEG_tab;
                                        COM2_DC_L = SEG_tab;
                                        COM3_DC_L = SEG_tab;                       
                                }
                                if(key_flag)
                                {
                                        key_flag = 0;
                                        if(key_value == set) //如果按下设置键,进入调小时模式,加载调整值
                                        {
                                                work_mode = 1;
                                                set_hour = BCD2HEX(i_hour);//转成HEX格式才能正常十进制进位
                                                set_min = BCD2HEX(i_min);
                                        }
                                }
                                break;

                        case 1: //调整小时模式
                                show_hour = HEX2BCD(set_hour);//设置值需转成BCD格式才能正常显示
                                show_min = HEX2BCD(set_min);
                                if(RTC_flag)//显示小时和分钟,冒号跳秒
                                {
                                        RTC_flag = 0;                               
                                        if(dot)
                                        {
                                                if(show_hour & 0xf0)        COM0_DC_L = SEG_tab;
                                                else COM0_DC_L = 0x00;
                                                COM1_DC_L = SEG_tab | 0x80;;                                       
                                        }
                                        else
                                        {
                                                COM0_DC_L = 0;
                                                COM1_DC_L = 0x80;       
                                        }
                                        COM2_DC_L = SEG_tab;
                                        COM3_DC_L = SEG_tab;                       
                                }
                                if(key_flag)
                                {
                                        key_flag = 0;
                                        switch(key_value)
                                        {
                                                case set://暂时认为是设置键
                                                        date_set = set_hour | 0x80;
                                                        work_mode = 2;
                                                        break;
                                                case add:
                                                        if(set_hour<24) set_hour++;
                                                        if(set_hour >= 24) set_hour = 0;
                                                        break;
                                                case sub:
                                                        if(set_hour == 0) set_hour = 23;
                                                        else if(set_hour>0) set_hour--;
                                                        break;
                                                case ok:
                                                        date_set = 0x00;       
                                                        date_set = HEX2BCD(set_min);
                                                        date_set = HEX2BCD(set_hour);                                                       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        WriteDate();
                                                        work_mode = 0;
                                                        break;
                                                default:
                                                        break;
                                        }
                                }                               
                                break;
                        case 2: //调整分钟模式
                                show_hour = HEX2BCD(set_hour);
                                show_min = HEX2BCD(set_min);
                                if(RTC_flag)//显示小时和分钟,冒号跳秒
                                {
                                        RTC_flag = 0;
                                        if(show_hour & 0xf0)        COM0_DC_L = SEG_tab;
                                        else COM0_DC_L = 0x00;
                                        COM1_DC_L = SEG_tab | 0x80;;                                               
                                        if(dot)
                                        {
                                                COM2_DC_L = SEG_tab;
                                                COM3_DC_L = SEG_tab;                                       
                                        }
                                        else
                                        {
                                                COM2_DC_L = 0;
                                                COM3_DC_L = 0;       
                                        }
                                }
                                if(key_flag)
                                {
                                        key_flag = 0;
                                        switch(key_value)
                                        {
                                                case set://暂时认为是设置键
                                                        work_mode = 0;
                                                        break;
                                                case add:
                                                        if(set_min<60) set_min++;
                                                        if(set_min >= 60) set_min = 0;
                                                        break;
                                                case sub:
                                                        if(set_min == 0) set_min = 59;
                                                        else if(set_min>0) set_min--;
                                                        break;
                                                case ok:
                                                        date_set = 0x00;       
                                                        date_set = HEX2BCD(set_min);
                                                        date_set = HEX2BCD(set_hour);                                       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        date_set = date_buf;       
                                                        WriteDate();
                                                        work_mode = 0;
                                                        break;
                                                default:
                                                        break;
                                        }
                                }       
                                break;
                        default:
                                break;
                }
        }
}



sugrqbgp 发表于 2025-6-15 17:10:28

功耗怎么样

晓飛飛 发表于 2025-6-15 17:27:56

sugrqbgp 发表于 2025-6-15 17:10
功耗怎么样

电池4V时的平均电流是6.5mA左右,作为LED主动发光显示的来说,我觉得功耗算是非常低了。

晓飛飛 发表于 2025-6-19 10:52:21

sugrqbgp 发表于 2025-6-15 17:10
功耗怎么样

1200mAh的电池充满电后使用5天了,电压从4.15V掉到了3.78V,我估计再坚持两天问题不大。
而且这个电池有可能存在虚标,实际容量应该是1000mAh左右。

ercircle 发表于 2025-6-19 11:23:28

貌似没电压检测,电池会不会过放呢

晓飛飛 发表于 2025-6-19 12:24:55

ercircle 发表于 2025-6-19 11:23
貌似没电压检测,电池会不会过放呢

电路没有使用LDO,可以通过采集单片机15通道反推电池电压,如果欠压了就开启周期性低功耗模式,另外,电池有保护板,支持欠压关闭,可以作为最后的保障。

晓飛飛 发表于 2025-7-18 23:14:05

哪个才是心头好
页: [1]
查看完整版本: 简简单单用 8H4K64TL 做个段码时钟