找回密码
 立即注册
查看: 177|回复: 5

AI8H4K64TL如何点亮数码管的小数点?

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:294
  • 最近打卡:2026-03-19 00:08:12
已绑定手机

3

主题

65

回帖

794

积分

高级会员

积分
794
发表于 2026-1-4 17:37:43 | 显示全部楼层 |阅读模式
求教各大佬:想用AI8H4K64TL触摸按键8段数码管测试板V1.1做一个万年历,需要把hhmmss-wyyyymmdd中的小数点点亮“hh.mm.ss-w.yyyy.mm.dd”,代码怎么写。
#include <AI8H.H>
#include <intrins.h>
#include <absacc.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>

// 引脚定义
#define                NTC                P06                //        0        高阻
#define                BUZ                P07                //        0        推挽

#define                COM0        P20                //        0        推挽
#define                COM1        P21                //        0        推挽
#define                COM2        P22                //        0        推挽
#define                COM3        P23                //        0        推挽
#define                COM4        P24                //        0        推挽
#define                COM5        P25                //        0        推挽
#define                COM6        P26                //        0        推挽
#define                COM7        P27                //        0        推挽

#define                RXD                P30                //        1        双向
#define                TXD                P31                //        1        推挽
#define                SCL                P32                //        1        双向
#define                SDA                P33                //        1        双向
#define                SEGC        P34                //        0        推挽
#define                SEGD        P35                //        0        推挽
#define                SEGE        P36                //        0        推挽
#define                CMP+        P37                //        0        高阻

#define                SEG0        P40                //        0        推挽
#define                SEG1        P41                //        0        推挽
#define                SEG2        P42                //        0        推挽
#define                SEG3        P43                //        0        推挽
#define                SEG4        P44                //        0        推挽
#define                SEG5        P45                //        0        推挽
#define                SEG6        P46                //        0        推挽
#define                SEG7        P47                //        0        推挽

#define                FOSC                        24000000UL                                //主时钟
#define                BAUD                        115200UL                                //波特率
#define                TMRF                        200UL                                        //定时器频率
#define                BRT                                (0x10000-FOSC/BAUD/4)        //波特率值
#define                TMR                                (0x10000-FOSC/TMRF/12)        //定时器值
#define                T_Buf_Len                64                                                //Uart1发送缓存长度
#define                R_Buf_Len                64                                                //Uart1接收缓存长度

// 时间结构体
typedef struct {
    unsigned char hour;
    unsigned char minute;
    unsigned char second;
    unsigned char week;      // 1-7 表示星期一到星期日
    unsigned int year;
    unsigned char month;
    unsigned char day;
} DateTime;

unsigned char                RP;                                                //Uart2接收指针
unsigned char                TP;                                                //Uart2发送指针
unsigned char                Uart_R_Len;                                //Uart2接收长度
unsigned char                Uart_T_Len;                                //Uart2发送长度
unsigned char xdata        R_Buf[R_Buf_Len];                //Uart2接收缓存
unsigned char xdata        T_Buf[T_Buf_Len];                //Uart2发送缓存
unsigned char code        Seg_Map[18]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x40,0x00};        //0~F,杠,空格
unsigned char                Seg_Buf[16];
unsigned char                LED_Buf[16];

bit blink_state = 0;
DateTime current_time;  // 当前时间
unsigned char time_update_flag = 0;  // 时间更新标志

// 初始化时间为2023年12月20日星期三 12:30:45(示例时间)
void Init_Time(void) {
    current_time.hour = 9;
    current_time.minute = 58;
    current_time.second = 00;
    current_time.week = 3;       // 星期三
    current_time.year = 2026;
    current_time.month = 01;
    current_time.day = 03;
}

// 判断是否为闰年
unsigned char Is_Leap_Year(unsigned int year) {
    return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}

// 获取月份的天数
unsigned char Get_Month_Days(unsigned int year, unsigned char month) {
    unsigned char days;

    switch(month) {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            days = 31;
            break;
        case 4: case 6: case 9: case 11:
            days = 30;
            break;
        case 2:
            days = Is_Leap_Year(year) ? 29 : 28;
            break;
        default:
            days = 30;
    }

    return days;
}

// 更新时间(每秒调用一次)
void Update_Time(void) {
    // 更新秒
    current_time.second++;
    if(current_time.second >= 60) {
        current_time.second = 0;
        current_time.minute++;

        if(current_time.minute >= 60) {
            current_time.minute = 0;
            current_time.hour++;

            if(current_time.hour >= 24) {
                current_time.hour = 0;
                current_time.day++;
                current_time.week++;

                if(current_time.week > 7) {
                    current_time.week = 1;  // 回到星期一
                }

                // 检查月份天数
                if(current_time.day > Get_Month_Days(current_time.year, current_time.month)) {
                    current_time.day = 1;
                    current_time.month++;

                    if(current_time.month > 12) {
                        current_time.month = 1;
                        current_time.year++;
                    }
                }
            }
        }
    }
}

// 将时间格式化为"hhmmss-wyyyymmdd"格式并存入Seg_Buf
void Format_Time_To_Seg(void) {
    // 格式: hhmmss-wyyyymmdd
    // 索引: 012345 7 89012345
    // Seg_Buf数组对应16个数码管位置

    // hh - 小时(2位)
    Seg_Buf[0] = current_time.hour / 10;    // 十位
    if(Seg_Buf[0] == 0) Seg_Buf[0] = 17;  // 显示空格
    Seg_Buf[1] = current_time.hour % 10;    // 个位

    // mm - 分钟(2位)
    Seg_Buf[2] = current_time.minute / 10;  // 十位
    Seg_Buf[3] = current_time.minute % 10;  // 个位

    // ss - 秒(2位)
    Seg_Buf[4] = current_time.second / 10;  // 十位
    Seg_Buf[5] = current_time.second % 10;  // 个位

    // 第6位显示 '-' (16对应杠)
    Seg_Buf[6] = 16;

    // w - 星期(1位,1-7)
    Seg_Buf[7] = current_time.week;         // 直接显示1-7

    // yyyy - 年(4位)
    Seg_Buf[8] = (current_time.year / 1000) % 10;     // 千位
    Seg_Buf[9] = (current_time.year / 100) % 10;      // 百位
    Seg_Buf[10] = (current_time.year / 10) % 10;      // 十位
    Seg_Buf[11] = current_time.year % 10;             // 个位

    // mm - 月(2位)
    Seg_Buf[12] = current_time.month / 10;  // 十位
    if(Seg_Buf[12] == 0) Seg_Buf[12] = 17;  // 显示空格
    Seg_Buf[13] = current_time.month % 10;  // 个位

    // dd - 天(2位)
    Seg_Buf[14] = current_time.day / 10;    // 十位
    if(Seg_Buf[14] == 0) Seg_Buf[14] = 17;  // 显示空格
    Seg_Buf[15] = current_time.day % 10;    // 个位
}

void UART_Send(unsigned int x)
{
        while(Uart_T_Len);
        TP=0;
        Uart_T_Len=x;
        TI=1;
}

void UART_Return(unsigned char temp)
{
        memcpy(T_Buf,R_Buf,temp);
        UART_Send(temp);
}

void Buzzer(void)
{
        // 蜂鸣器控制逻辑
        BUZ = 0; // 默认关闭蜂鸣器
}

void Seg_Display(void)
{
        // 数码管显示逻辑 - 显示时间信息
        Format_Time_To_Seg();
}

void LED_Display(void)
{
        // LED显示逻辑 - 秒的个位数LED闪烁
        unsigned char i;
       
        // 先关闭所有LED
        for(i = 0; i < 16; i++) {
                LED_Buf = 0x00;
        }
       
        // 根据blink_state控制秒个位数LED闪烁
        // 假设秒个位数对应Seg_Buf[5],可能需要根据实际硬件连接调整
        if(blink_state) {
                // 点亮秒个位数对应的LED
                // 注意:LED_Buf索引可能与Seg_Buf对应,也可能需要映射
                LED_Buf[5] = 0x01;  // 尝试点亮第5个LED
        }
}

void LED(void)
{
        unsigned char i;
        unsigned char xdata *p=XBYTE+0xFB10;
       
        // 更新数码管显示
        Seg_Display();
       
        // 更新LED显示
        LED_Display();
       
        // 写入显示缓存
        for(i=0;i<8;i++)
        {
                *(p+i)=Seg_Map[Seg_Buf];
                *(p+8+i)=(LED_Buf&0x07)<<4;
                *(p+16+i)=Seg_Map[Seg_Buf[8+i]];
                *(p+24+i)=(LED_Buf[8+i]&0x07)<<4;
        }
}

void Init(void)
{
        P_SW2|=EAXFR;
       
        P0=0x00;
        P1=0x00;
        P2=0x00;
        P3=0x0F;
        P4=0x00;
        P5=0x00;
       
        P0M0=0x80;
        P0M1=0x7F;
        P1M0=0x00;
        P1M1=0xFF;
        P2M0=0xFF;
        P2M1=0x00;
        P3M0=0x72;
        P3M1=0x80;
        P4M0=0xFF;
        P4M1=0x00;
        P5M0=0x00;
        P5M1=0xFF;
       
        AUXR=0x05;                //设置定时器0时钟为12T模式,设置定时器2为1T模式,设置定时器2为波特率发生器
        TMOD=0x01;                //设置定时器0为16位不自动重装载模式
        TH0=TMR>>8;                //设置定时器0初始值
        TL0=TMR;                //设置定时器0初始值
        TF0=0;                        //清除TF0中断标志位
        ET0=1;                        //启用定时器0中断
        TR0=1;                        //启动定时器0
       
        SCON=0x50;                //设置UART1模式为8位数据可变波特率
        T2H=BRT>>8;                //设置UART1波特率
        T2L=BRT;                //设置UART1波特率
        AUXR|=T2R;                //打开定时器2
        ES=1;                        //启用UART1中断
       
        COMEN=0xFF;                //使能COM
        SEGENL=0xFF;        //使能SEG
        SEGENH=0x70;        //使能SEG
        LEDCTRL=0xA0;        //使能LED驱动器,共阴共阳模式,亮度100%
        LEDCKS=0x00;        //
       
        EA=1;                        //启用总中断
       
        COM0_DA_L=0x00;
        COM0_DA_H=0x00;
        COM1_DA_L=0x00;
        COM1_DA_H=0x00;
        COM2_DA_L=0x00;
        COM2_DA_H=0x00;
        COM3_DA_L=0x00;
        COM3_DA_H=0x00;
        COM4_DA_L=0x00;
        COM4_DA_H=0x00;
        COM5_DA_L=0x00;
        COM5_DA_H=0x00;
        COM6_DA_L=0x00;
        COM6_DA_H=0x00;
        COM7_DA_L=0x00;
        COM7_DA_H=0x00;
        COM0_DC_L=0x00;
        COM0_DC_H=0x00;
        COM1_DC_L=0x00;
        COM1_DC_H=0x00;
        COM2_DC_L=0x00;
        COM2_DC_H=0x00;
        COM3_DC_L=0x00;
        COM3_DC_H=0x00;
        COM4_DC_L=0x00;
        COM4_DC_H=0x00;
        COM5_DC_L=0x00;
        COM5_DC_H=0x00;
        COM6_DC_L=0x00;
        COM6_DC_H=0x00;
        COM7_DC_L=0x00;
        COM7_DC_H=0x00;
       
        memset(R_Buf,0x00,sizeof R_Buf);
        memset(T_Buf,0x00,sizeof T_Buf);
       
        // 初始化时间
        Init_Time();
}

void main(void)
{
        Init();
        while(1)
        {
                LED();                        // 更新显示
                Buzzer();                // 蜂鸣器控制
               
                // 如果时间需要更新
                if(time_update_flag) {
                        time_update_flag = 0;
                        Update_Time();        // 更新时间
                }
        }
}

void Uart_Start(void)
{
        TH0=TMR>>8;
        TL0=TMR;
        TR0=1;
}

void Uart_Stop(void)
{
        TR0=0;
        TH0=TMR>>8;
        TL0=TMR;
        RP=0;
        memset(R_Buf,0x00,sizeof R_Buf);
}

// 定时器0中断服务程序 - 用于更新时间基准和LED闪烁
void Timer0_Isr(void) interrupt TMR0_VECTOR
{
        static unsigned int time_counter = 0;
        static unsigned char blink_counter = 0;
       
        // 重新装载定时器
        TH0 = TMR >> 8;
        TL0 = TMR;
       
        // UART处理
        if(RP > 0) {
                UART_Return(RP);
                Uart_Stop();
        }
       
        // 时间计数(200Hz中断)
        time_counter++;
        if(time_counter >= 200) {  // 1秒
                time_counter = 0;
                time_update_flag = 1;  // 设置时间更新标志
        }
       
        // LED闪烁控制(2Hz,每秒闪烁2次)
        blink_counter++;
        if(blink_counter >= 100) {  // 0.5秒
                blink_counter = 0;
                blink_state = !blink_state;  // 切换闪烁状态
        }
}

void Uart1_Isr(void) interrupt UART1_VECTOR
{
        if(RI)
        {
                RI=0;
                Uart_Start();
                R_Buf[RP]=SBUF;
                if(RP==R_Buf_Len-1)
                {
                        Uart_Stop();
                }
                else if(TR0)
                {
                        RP++;
                }
        }
        if(TI)
        {
                TI=0;
                if(TP==Uart_T_Len)
                {
                        TP=0;
                        Uart_T_Len=0;
                }
                if(Uart_T_Len!=0)
                {
                        SBUF=(T_Buf[TP]);
                        TP++;
                }
        }
}


AI8H4K64TL-LQFP48-万年历.rar

71.69 KB, 下载次数: 0

回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:691
  • 最近打卡:2026-03-18 11:41:10
已绑定手机

49

主题

2639

回帖

2864

积分

荣誉版主

积分
2864
发表于 2026-1-4 21:41:28 | 显示全部楼层
参考此帖代码中有关于刷冒号的部分,带冒号的数码管冒号和小数点同位。
https://www.stcaimcu.com/thread-18536-1-1.html

~~~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:724
  • 最近打卡:2026-03-18 07:56:47
已绑定手机

97

主题

7244

回帖

1万

积分

超级版主

积分
13791
发表于 2026-1-5 07:54:37 | 显示全部楼层
根据Seg_Map的值可以判断低位是a段高电平点亮
需要点亮小数点的位,Seg_Map[n]|0x80即可点亮小数点
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:294
  • 最近打卡:2026-03-19 00:08:12
已绑定手机

3

主题

65

回帖

794

积分

高级会员

积分
794
发表于 2026-1-5 15:35:34 | 显示全部楼层
感谢两位回复,段码0x80和0x7F都试过了,还是不行,0x7F显示8,0x80无显示。数字带点的也不显示点,共阳、共阴都不行。对于这块8段16位的测试板,官方的数码管段码生成工具怎么生成段码?
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:251
  • 最近打卡:2026-03-18 08:39:47
已绑定手机

22

主题

626

回帖

2318

积分

金牌会员

积分
2318
发表于 2026-1-5 16:15:59 | 显示全部楼层
对应缓冲区或个操作,假设SEG_H等于0x08,LedDispBuf[x] |=SEG_H,建议操作时都使用正逻辑,仅在显示时按高电平显示或低电平转换一下,这样程序可读性强
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:294
  • 最近打卡:2026-03-19 00:08:12
已绑定手机

3

主题

65

回帖

794

积分

高级会员

积分
794
发表于 2026-1-7 08:53:00 | 显示全部楼层
经过仔细检查,发现是R21焊接不良。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-19 06:15 , Processed in 0.124250 second(s), 72 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表