找回密码
 立即注册
查看: 87|回复: 8

基于“擎天柱Ai8051U转89C52-DIP40核心板”驱动16x16LED点阵显示汉字向左滚动进入

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-24 22:38:53 | 显示全部楼层 |阅读模式
        “擎天柱Ai8051U转89C52-DIP40核心板”附赠的实例很丰富,AI8051U-DEMO-CODE-V1.2文件里有8bit的实例,也有32bit的实例,各有80多个实例,定时器程序见“02-Timer0-Timer1-Timer2-Timer3-Timer4测试程序”,如果用其他Ai8051新片时,可以合理舍去不存在的Timer,上次用延时的方式驱动16x16LED点阵显示多个汉字,这次采用定时器0延时,驱动16x16LED点阵显示汉字,汉字向左循环滚动进入。
      开发板上的16x16LED点阵原理图:

    Proteus仿真图:
   源代码:
//版本2  在16x16LED点阵上多个汉字向左滚动进入
//向左滚动进入  容易
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/*---------------------------------------------------------------------*/

/*************  功能说明    **************
32bit
本例程基于AI8051U为主控芯片进行编写测试。
T0中断100us显示1列


******************************************/

#include "AI8051U.h"
#include "stdio.h"
#include "intrins.h"

typedef         unsigned char        u8;
typedef         unsigned int        u16;
typedef         unsigned long        u32;

#define MAIN_Fosc        24000000UL

//==========================================================================
//各定时器加载初值

//24MHZ,1T,一条指令耗时1/24us,定时100us,初值2400
//Timer 0 中断频率, 10000次/秒,定时100us,1/100us=10000HZ
#define Timer0_Reload   (MAIN_Fosc / 5000)  //定时100us,初值2400
//#define Timer0_Reload   (MAIN_Fosc / 2000)  //定时500us,初值1200

//#define Timer0_Reload   (MAIN_Fosc / 1000)      //Timer 0 中断频率, 1000次/秒,初值24000
#define Timer1_Reload   (MAIN_Fosc / 2000)      //Timer 1 中断频率, 2000次/秒
#define Timer2_Reload   (MAIN_Fosc / 3000)      //Timer 2 中断频率, 3000次/秒
#define Timer3_Reload   (MAIN_Fosc / 4000)      //Timer 3 中断频率, 4000次/秒
#define Timer4_Reload   (MAIN_Fosc / 5000)      //Timer 4 中断频率, 5000次/秒

void    Timer0_init(void);
//void    Timer1_init(void);
//void    Timer2_init(void);
//void    Timer3_init(void);
//void    Timer4_init(void);

bit T0_flag = 0;
#define DUAN1 P0           //段码直驱,NPN管同相驱动,硬件:下半列,bit7在前
#define DUAN2 P2     //段码直驱,NPN管同相驱动,硬件:上半列,bit7在前
#define SCAN P1             //扫描码经4-16译码器驱动

u8 code  tab1 [ ]={            
                  //PCtoLCD2002完美版取码软件 阴码 逆向(低位在前。但字节在前?) 逐列   

// 威(0) 海(1) 市(2) 文(3) 登(4) 技(5) 师(6) 学(7) 院(8)
       
//"威"字为STC取码软件:无法生成

0x00,0x80,0x00,0x60,0xF8,0x1F,0x48,0x82,0x48,0x8A,0x48,0x56,0xC8,0x23,0x48,0x52,
0x48,0x8E,0x48,0x40,0xFF,0x27,0x08,0x18,0x09,0x26,0xCA,0x41,0x08,0xF0,0x00,0x00,/*"威",0*/

0x10,0x04,0x60,0x04,0x02,0x7C,0x0C,0x03,0xC0,0x00,0x10,0x01,0x08,0x1D,0xF7,0x13,
0x14,0x11,0x54,0x55,0x94,0x99,0x14,0x51,0xF4,0x3F,0x04,0x11,0x00,0x01,0x00,0x00,/*"海",1*/

0x00,0x00,0x08,0x00,0x88,0x3F,0x88,0x00,0x88,0x00,0x88,0x00,0x89,0x00,0xFA,0xFF,
0x88,0x00,0x88,0x00,0x88,0x10,0x88,0x20,0x88,0x1F,0x08,0x00,0x00,0x00,0x00,0x00,/*"市",2*/

0x08,0x80,0x08,0x80,0x08,0x40,0x38,0x40,0xC8,0x20,0x08,0x11,0x09,0x0A,0x0E,0x04,
0x08,0x0A,0x08,0x11,0xC8,0x20,0x38,0x40,0x08,0x40,0x08,0x80,0x08,0x80,0x00,0x00,/*"文",3*/

0x00,0x01,0x00,0x41,0x8A,0x40,0x52,0x4F,0x22,0x59,0x5A,0x69,0x46,0x49,0x40,0x49,
0x47,0x49,0x58,0x69,0x24,0x59,0x52,0x4F,0x88,0x40,0x04,0x41,0x00,0x01,0x00,0x00,/*"登",4*/

0x10,0x04,0x10,0x44,0x10,0x82,0xFF,0x7F,0x10,0x01,0x90,0x80,0x08,0x80,0x88,0x40,
0x88,0x43,0x88,0x2C,0xFF,0x10,0x88,0x28,0x88,0x46,0x88,0x81,0x08,0x80,0x00,0x00,/*"技",5*/

0x00,0x00,0xFC,0x87,0x00,0x40,0x00,0x30,0xFF,0x0F,0x00,0x00,0x02,0x00,0xE2,0x1F,
0x22,0x00,0x22,0x00,0xFE,0xFF,0x22,0x08,0x22,0x10,0xE2,0x0F,0x02,0x00,0x00,0x00,/*"师",6*/

0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00,/*"学",7*/

0x00,0x00,0xFE,0xFF,0x22,0x04,0x5A,0x08,0x86,0x07,0x10,0x80,0x0C,0x41,0x24,0x31,
0x24,0x0F,0x25,0x01,0x26,0x01,0x24,0x3F,0x24,0x41,0x14,0x41,0x0C,0x71,0x00,0x00,/*"院",8*/
};   //

u8 code   tab2[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
  0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};         //扫描码

/******************** 主函数 **************************/
void main(void)
{
    //u16 j = 0;           //1个字的字节数
          u16  zishu = 0;       //字数
    u8 lie = 0;          //每个字的列数,1列2个字节,兼作取码序号
          u8 times = 0;        //每个字重复显示的遍数

          WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置P0为推挽输出
    P1M1 = 0x00;   P1M0 = 0xff;   //设置P1为推挽输出
    P2M1 = 0x00;   P2M0 = 0xff;   //设置P2为推挽输出       

          //不用的端口要配置为准双向口,确保系统的稳定性和可靠性
          P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口



    Timer0_init();
//    Timer1_init();
//    Timer2_init();
//    Timer3_init();
//    Timer4_init();

                TF0 = 0;                //清除TF0标志
                ET0 = 1;    //打开T0中断
                EA = 1;     //打开总中断
    while (1)
                {
                        LOOP:
                        if(1 == T0_flag)
                        {
                                T0_flag = 0;
                    DUAN2 = 0x00;               //清屏
                    DUAN1 = 0x00;               //清屏
                                DUAN2 = tab1[lie + 2 * zishu];        //此处DUAN2先输出数据,上半列
                                                              
                    DUAN1 = tab1[lie + 1 + 2 * zishu];          //此处DUAN1后输出数据,下半列
                    SCAN = tab2[lie / 2];                      //0~15列

              lie += 2;           //下一列
              if(lie < 32)        //一个汉字16列,32个字节的数据
                goto LOOP;        //从最外层的if语句跳出来
                                lie = 0;            //下个字的首列
                                //P3 ^= 0xff;        //测试用
                                if(++times < 100)  //一个屏重复显示遍数,1屏维持时间
                             goto  LOOP;     //从最外层的if语句跳出来
        times = 0;
                                if(++zishu < (8 * 16))    //9个字,共(9-1)*160列,无乱码
                             goto  LOOP;           //从最外层的if语句跳出来
        zishu = 0;
                        }
                }
}

//========================================================================
// 函数: void Timer0_init(void)
// 描述: timer0初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer0_init(void)
{
        TR0 = 0;    //停止计数

    #if (Timer0_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer0设置的中断过快!"

    #elif ((Timer0_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET0 = 1;    //允许中断
    //  PT0 = 1;    //高优先级中断
        TMOD &= ~0x03;
        TMOD |= 0;  //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
    //  T0_CT = 1;  //计数
        T0_CT = 0;  //定时
    //  T0CLKO = 1; //输出时钟
        T0CLKO = 0; //不输出时钟

        #if (Timer0_Reload < 65536UL)
            T0x12 = 1;  //1T mode
            TH0 = (u8)((65536UL - Timer0_Reload) / 256);
            TL0 = (u8)((65536UL - Timer0_Reload) % 256);
        #else
            T0x12 = 0;  //12T mode
            TH0 = (u8)((65536UL - Timer0_Reload/12) / 256);
            TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);
        #endif

        TR0 = 1;    //开始运行

    #else
        #error "Timer0设置的中断过慢!"
    #endif

}

/*****************************************************************
//========================================================================
// 函数: void Timer1_init(void)
// 描述: timer1初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer1_init(void)
{
        TR1 = 0;    //停止计数

    #if (Timer1_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer1设置的中断过快!"

    #elif ((Timer1_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET1 = 1;    //允许中断
    //  PT1 = 1;    //高优先级中断
        TMOD &= ~0x30;
        TMOD |= (0 << 4);   //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
    //  T1_CT = 1;  //计数
        T1_CT = 0;  //定时
    //  T1CLKO = 1; //输出时钟
        T1CLKO = 0; //不输出时钟

        #if (Timer1_Reload < 65536UL)
            T1x12 = 1;  //1T mode
            TH1 = (u8)((65536UL - Timer1_Reload) / 256);
            TL1 = (u8)((65536UL - Timer1_Reload) % 256);
        #else
            T1x12 = 0;  //12T mode
            TH1 = (u8)((65536UL - Timer1_Reload/12) / 256);
            TL1 = (u8)((65536UL - Timer1_Reload/12) % 256);
        #endif

        TR1 = 1;    //开始运行

    #else
        #error "Timer1设置的中断过慢!"
    #endif
}

//========================================================================
// 函数: void Timer2_init(void)
// 描述: timer2初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer2_init(void)
{
        T2R = 0;    //停止计数

    #if (Timer2_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer2设置的中断过快!"

    #elif ((Timer2_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET2 = 1;    //允许中断
    //  T2_CT = 1;  //计数
        T2_CT = 0;  //定时
    //  T2CLKO = 1; //输出时钟
        T2CLKO = 0; //不输出时钟

        #if (Timer2_Reload < 65536UL)
            T2x12 = 1;    //1T mode
            T2H = (u8)((65536UL - Timer2_Reload) / 256);
            T2L = (u8)((65536UL - Timer2_Reload) % 256);
        #else
            T2x12 = 0;    //12T mode
            T2H = (u8)((65536UL - Timer2_Reload/12) / 256);
            T2L = (u8)((65536UL - Timer2_Reload/12) % 256);
        #endif

        T2R = 1;    //开始运行

    #else
        #error "Timer2设置的中断过慢!"
    #endif
}

//========================================================================
// 函数: void Timer3_init(void)
// 描述: timer3初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer3_init(void)
{
        T3R = 0;    //停止计数

    #if (Timer3_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer3设置的中断过快!"

    #elif ((Timer3_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET3 = 1;    //允许中断
    //  T3_CT = 1;  //计数
        T3_CT = 0;  //定时
    //  T3CLKO = 1; //输出时钟
        T3CLKO = 0; //不输出时钟

        #if (Timer3_Reload < 65536UL)
            T3x12 = 1;    //1T mode
            T3H = (u8)((65536UL - Timer3_Reload) / 256);
            T3L = (u8)((65536UL - Timer3_Reload) % 256);
        #else
            T3x12 = 0;    //12T mode
            T3H = (u8)((65536UL - Timer3_Reload/12) / 256);
            T3L = (u8)((65536UL - Timer3_Reload/12) % 256);
        #endif

        T3R = 1;    //开始运行

    #else
        #error "Timer3设置的中断过慢!"
    #endif
}

//========================================================================
// 函数: void Timer4_init(void)
// 描述: timer4初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer4_init(void)
{
        T4R = 0;    //停止计数

    #if (Timer4_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer4设置的中断过快!"

    #elif ((Timer4_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET4 = 1;    //允许中断
    //  T4_CT = 1;  //计数
        T4_CT = 0;  //定时
    //  T4CLKO = 1; //输出时钟
        T4CLKO = 0; //不输出时钟

        #if (Timer4_Reload < 65536UL)
            T4x12 = 1;    //1T mode
            T4H = (u8)((65536UL - Timer4_Reload) / 256);
            T4L = (u8)((65536UL - Timer4_Reload) % 256);
        #else
            T4x12 = 0;    //12T mode
            T4H = (u8)((65536UL - Timer4_Reload/12) / 256);
            T4L = (u8)((65536UL - Timer4_Reload/12) % 256);
        #endif

        T4R = 1;    //开始运行

    #else
        #error "Timer4设置的中断过慢!"
    #endif
}
******************************************/
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述:  timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer0_int (void) interrupt 1
{
   //P07 = ~P07;
                        T0_flag = 1;         //T0中断标志置1
}

/*********************************************
//========================================================================
// 函数: void timer1_int (void) interrupt TIMER1_VECTOR
// 描述:  timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer1_int (void) interrupt 3
{
   P06 = ~P06;
}

//========================================================================
// 函数: void timer2_int (void) interrupt TIMER2_VECTOR
// 描述:  timer2中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer2_int (void) interrupt 12
{
    P05 = ~P05;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
}

//========================================================================
// 函数: void timer3_int (void) interrupt TIMER3_VECTOR
// 描述:  timer3中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer3_int(void) interrupt 19
{
    P04 = ~P04;
}

//========================================================================
// 函数: void timer4_int (void) interrupt TIMER4_VECTOR
// 描述:  timer4中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer4_int(void) interrupt 20
{
    P03 = ~P03;
}
***********************************************************************/

为了充分发挥Ai8051U单片机的特性,这里采用timer0产生100us中断,采用32bit方式编程,定时器初始化和中断函数采用官方文件,多余部分屏蔽了,通过手机录的视频也不闪烁。













12.png

16x16点阵图

16x16点阵图
13.png

x.mp4

8.04 MB, 下载次数: 1

汉字向左滚动视频

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:299
  • 最近打卡:2026-07-04 00:01:55
已绑定手机

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 2026-6-24 23:52:24 | 显示全部楼层
AI8051U支持8bit模式
多方面与89C5x相似
学生用户学习
永怀这学徒心
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-25 14:59:22 | 显示全部楼层
采用上述代码,为何STC带的取码软件却无法取到相同的数据码,试遍8种逐列取码方式都不行,最后还是用PCtoLCD2002完美版取码软件 阴码 逆向(低位在前。低字节在前) 逐列 ,软件中规定:   从第一列开始向下每取8个点作为一个字节,如果最后不足8个点就补满8位。取模顺序是从低到高,即第一个点作为最低位。如*-------取为00000001,这一点STC还有待改进。
  程序中的代码:                             
    DUAN2 = tab1[lie + 2 * zishu];        //此处DUAN2先输出数据,上半列
    DUAN1 = tab1[lie + 1 + 2 * zishu];          //此处DUAN1后输出数据,下半列
1、如果始终令 zishu=0,则只显示首字“威”,并屏蔽以下代码:
//if(++zishu < (8 * 16))    //9个字,共(9-1)*160列,无乱码
//   goto  LOOP;           //从最外层的if语句跳出来
//zishu = 0;
2、无限循环部分,按如下改动可以循环显示所有的汉字。
    while (1)
                {
                        LOOP:
                        if(1 == T0_flag)
                        {
                                T0_flag = 0;
                    DUAN2 = 0x00;               //清屏
                    DUAN1 = 0x00;               //清屏
                                DUAN2 = tab1[lie + 32 * zishu];        //此处DUAN2先输出数据,上半列,32* zishu可以找到下个汉字
                                                              
                    DUAN1 = tab1[lie + 1 + 32 * zishu];          //此处DUAN1后输出数据,下半列,32* zishu可以找到下个汉字
                    SCAN = tab2[lie / 2];                      //0~15列

              lie += 2;           //下一列
              if(lie < 32)        //一个汉字16列,32个字节的数据
                goto LOOP;        //从最外层的if语句跳出来
                                lie = 0;            //下个字的首列
                                //P3 ^= 0xff;        //测试用
                                if(++times < 100)  //一个屏重复显示遍数,1屏维持时间
                             goto  LOOP;     //从最外层的if语句跳出来
        times = 0;
                                if(++zishu < 9)    //9个字,无乱码
                             goto  LOOP;           //从最外层的if语句跳出来
        zishu = 0;
                        }
                }
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-26 10:07:58 | 显示全部楼层

基于“擎天柱Ai8051U转89C52-DIP40核心板”驱动16x16LED点阵显示汉字向右滚动进入

1.硬件电路
见x.png
2.擎天柱Ai8051U转89C52-DIP40核心板
见11.jpg
3.汉字取码软件与取码
采用PCtolc2002,见图12.png
由于端口改了,用STC下载器自带的点阵生成工具按逐列取码,8种方式竟没有一种适合,没办法,只得采用PCtolc2002软件生成点阵数据,但又不甘心,STC的生态做得这么好,不会出这么明显的错误吧,由于初次使用STC取码工具,由于自己的疏忽,STC取码工具中还有一个存储顺序栏未改动,本例取码模式:扫描模式选:垂直扫描,从上到下,从左到右,存储顺序:低位优先,生成的代码与PCtoLCD2002一样。
   启动STC下载软件,执行菜单命令:工具\字库生成工具,即可打开取码工具,很方便,见图14.png。
  想要向右滚动显示“技师学院好”+2黑屏,取码要按“好院学师技”+2黑屏,加上2屏黑屏码可以确保显示时无乱码。
  硬件电路的一列从上到下,依次是P27~20、P07~00,输入数据P2=0x17,P0=0x55,扫描码输入0x00,可见最右边的1列点亮,P2=B1110 1000,P0=B10101010,所以取码要逆序(低位在前,低字节在前),扫描是自右向左逐列扫描。
4、编程
原则:先找到最后一个字的最后一列(15列)的2个字节并扫描,即字库表中最后的2个0x00,前一个送P2口,后一个送P0口,扫描码(0~15)也要先找到最后1列的扫描码,即15。
为了充分发挥Ai8051U单片机的性能,采用100us定时中断,从而提高刷新率,这样在录像的时候也无闪烁感。
  1. //版本3  在16x16LED点阵上多个汉字向右滚动进入  难
  2. //基于“擎天柱Ai8051U转89C52-DIP40核心板”驱动16x16LED点阵显示汉字向右滚动进入
  3. //
  4. /*************  功能说明    **************
  5. 32bit   Keil uVision C251_32bit开发
  6. T0中断100us显示1列
  7. ******************************************/
  8. #include "AI8051U.h"
  9. #include "stdio.h"
  10. #include "intrins.h"
  11. typedef         unsigned char        u8;
  12. typedef         unsigned int        u16;
  13. typedef         unsigned long        u32;
  14. #define MAIN_Fosc        24000000UL
  15. //==========================================================================
  16. //各定时器加载初值
  17. //24MHZ,1T,一条指令耗时1/24us,定时100us,初值2400
  18. //Timer 0 中断频率, 10000次/秒,定时100us,1/100us=10000HZ
  19. #define Timer0_Reload   (MAIN_Fosc / 5000)  //定时100us,初值2400
  20. //#define Timer0_Reload   (MAIN_Fosc / 2000)  //定时500us,初值1200
  21. //#define Timer0_Reload   (MAIN_Fosc / 1000)      //Timer 0 中断频率, 1000次/秒,初值24000
  22. //#define Timer1_Reload   (MAIN_Fosc / 2000)      //Timer 1 中断频率, 2000次/秒
  23. //#define Timer2_Reload   (MAIN_Fosc / 3000)      //Timer 2 中断频率, 3000次/秒
  24. //#define Timer3_Reload   (MAIN_Fosc / 4000)      //Timer 3 中断频率, 4000次/秒
  25. //#define Timer4_Reload   (MAIN_Fosc / 5000)      //Timer 4 中断频率, 5000次/秒
  26. void    Timer0_init(void);
  27. //void    Timer1_init(void);
  28. //void    Timer2_init(void);
  29. //void    Timer3_init(void);
  30. //void    Timer4_init(void);
  31. bit T0_flag = 0;      //T0中断标志
  32. #define DUAN1 P0           //段码直驱,NPN管同相驱动,硬件:下半列,bit7在前
  33. #define DUAN2 P2     //段码直驱,NPN管同相驱动,硬件:上半列,bit7在前
  34. #define SCAN P1             //扫描码经4-16译码器驱动
  35. u8 code  tab1 [ ]={            
  36. //为何STC带的取码软件却无法取到相同的数据码,试遍8种逐列取码方式都不行,原来还有存储顺序
  37. //那项未选择,选择垂直扫描,从上到下,从左到右,低位优先,生成的代码与PCtoLCD2002一样
  38.        
  39. //用PCtoLCD2002完美版取码软件 阴码 逆向(低位在前,低字节在前) 逐列 ,
  40. //软件中规定:   从第一列开始向下每取8个点作为一个字节,如果最后不足8个点就补满8位。
  41. //取模顺序是从低到高,即第一个点作为最低位。如*-------取为00000001。
  42.   
  43. //想向右滚动显示“技师学院好”+2黑屏,取码要按“好院学师技”+2黑屏
  44.        
  45. //向右滚动显示5个汉字,要先显示最后一个字的最末一列的2个码
  46. //好(0) 院(1) 学(2) 师(3) 技(4)
  47.         //逆向
  48. 0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,0x10,0x16,0xF0,0x61,0x00,0x00,0x80,0x00,
  49. 0x82,0x40,0x82,0x80,0xE2,0x7F,0x92,0x00,0x8A,0x00,0x86,0x00,0x80,0x00,0x00,0x00,/*"好",0*/
  50. 0x00,0x00,0xFE,0xFF,0x22,0x04,0x5A,0x08,0x86,0x07,0x10,0x80,0x0C,0x41,0x24,0x31,
  51. 0x24,0x0F,0x25,0x01,0x26,0x01,0x24,0x3F,0x24,0x41,0x14,0x41,0x0C,0x71,0x00,0x00,/*"院",1*/
  52. 0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
  53. 0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00,/*"学",2*/
  54. 0x00,0x00,0xFC,0x87,0x00,0x40,0x00,0x30,0xFF,0x0F,0x00,0x00,0x02,0x00,0xE2,0x1F,
  55. 0x22,0x00,0x22,0x00,0xFE,0xFF,0x22,0x08,0x22,0x10,0xE2,0x0F,0x02,0x00,0x00,0x00,/*"师",3*/
  56. 0x10,0x04,0x10,0x44,0x10,0x82,0xFF,0x7F,0x10,0x01,0x90,0x80,0x08,0x80,0x88,0x40,
  57. 0x88,0x43,0x88,0x2C,0xFF,0x10,0x88,0x28,0x88,0x46,0x88,0x81,0x08,0x80,0x00,0x00,/*"技",4*/
  58.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   //黑屏
  59.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   //黑屏
  60. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   //黑屏
  61. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   //黑屏
  62. };   //
  63. u8 code   tab2[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
  64.   0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};         //扫描码
  65. /******************** 主函数 **************************/
  66. void main(void)
  67. {
  68.     //u16 j = 0;           //1个字的字节数
  69.           u16  zishu = 6 * 16;  //总列数,7个字,总列数取(7-1) * 16无乱码
  70.     u8 lie = 0;          //每个字的列数,1列2个字节,兼作取码序号
  71.           u8 times = 0;        //每个字重复显示的遍数
  72.   
  73.           WTST = 0;    //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  74.     EAXFR = 1;   //扩展寄存器(XFR)访问使能
  75.     CKCON = 0;   //提高访问XRAM速度
  76.     P0M1 = 0x00;   P0M0 = 0xff;   //设置P0为推挽输出
  77.     P1M1 = 0x00;   P1M0 = 0xff;   //设置P1为推挽输出
  78.     P2M1 = 0x00;   P2M0 = 0xff;   //设置P2为推挽输出       
  79.           //不用的端口要配置为准双向口,确保系统的稳定性和可靠性
  80.           P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  81.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  82.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  83.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  84.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  85.   
  86.     Timer0_init();  //T0初始化
  87.       
  88.                 TF0 = 0;                //清除TF0标志
  89.                 ET0 = 1;    //打开T0中断
  90.                 EA = 1;     //打开总中断
  91.     while (1)
  92.                 {       //原则:先找到最后一个字的最后一列(15列)的2个字节并扫描
  93.                         LOOP:
  94.                         if(1 == T0_flag)
  95.                         {
  96.                                 T0_flag = 0;
  97.                     DUAN2 = 0x00;               //清屏
  98.                     DUAN1 = 0x00;               //清屏
  99.                                 DUAN2 = tab1[32 - lie + 2 * zishu];         //此处DUAN2先输出数据
  100.                                                               
  101.                     DUAN1 = tab1[32 - lie + 1 + 2 * zishu];             //此处DUAN1后输出数据
  102.                     SCAN = tab2[ 15-lie / 2];         //0~15列
  103.               lie += 2;           //下一列
  104.               if(lie < 32)        //一个汉字16列,32个字节的数据
  105.                 goto LOOP;        //从最外层的if语句跳出来
  106.                                 lie = 0;            //下个字的首列
  107.                                 //P3 ^= 0xff;        //测试用
  108.                                 if(++times < 100)  //一个屏重复显示遍数,1屏维持时间
  109.                              goto  LOOP;    //从最外层的if语句跳出来
  110.         times = 0;
  111.                                 if(--zishu > 0)    //7个字,共(7-1)*16列,无乱码
  112.                              goto  LOOP;       //从最外层的if语句跳出来
  113.         zishu = 6 * 16;
  114.                  }
  115.         }
  116. }
  117. //========================================================================
  118. // 函数: void Timer0_init(void)
  119. // 描述: timer0初始化函数.
  120. // 参数: none.
  121. // 返回: none.
  122. // 版本: V1.0, 2015-1-12
  123. //========================================================================
  124. void Timer0_init(void)
  125. {
  126.         TR0 = 0;    //停止计数
  127.     #if (Timer0_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
  128.         #error "Timer0设置的中断过快!"
  129.     #elif ((Timer0_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
  130.         ET0 = 1;    //允许中断
  131.     //  PT0 = 1;    //高优先级中断
  132.         TMOD &= ~0x03;
  133.         TMOD |= 0;  //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
  134.     //  T0_CT = 1;  //计数
  135.         T0_CT = 0;  //定时
  136.     //  T0CLKO = 1; //输出时钟
  137.         T0CLKO = 0; //不输出时钟
  138.         #if (Timer0_Reload < 65536UL)
  139.             T0x12 = 1;  //1T mode
  140.             TH0 = (u8)((65536UL - Timer0_Reload) / 256);
  141.             TL0 = (u8)((65536UL - Timer0_Reload) % 256);
  142.         #else
  143.             T0x12 = 0;  //12T mode
  144.             TH0 = (u8)((65536UL - Timer0_Reload/12) / 256);
  145.             TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);
  146.         #endif
  147.         TR0 = 1;    //开始运行
  148.     #else
  149.         #error "Timer0设置的中断过慢!"
  150.     #endif
  151. }
  152. //========================================================================
  153. // 函数: void timer0_int (void) interrupt TIMER0_VECTOR
  154. // 描述:  timer0中断函数.
  155. // 参数: none.
  156. // 返回: none.[apoyl_aliyunvideo]1074[/apoyl_aliyunvideo]
  157. // 版本: V1.0, 2015-1-12
  158. //========================================================================
  159. void timer0_int (void) interrupt 1
  160. {
  161.    //P07 = ~P07;
  162.                         T0_flag = 1;         //T0中断标志置1
  163. }
复制代码
5、动画效果

  








x.png
11.jpg
14.png
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-26 10:11:39 | 显示全部楼层

基于“擎天柱Ai8051U转89C52-DIP40核心板”驱动16x16LED点阵显示汉字向右滚动进入的视


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-26 10:14:02 | 显示全部楼层
网络有问题,不出现则以,一出现竟这么多。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:299
  • 最近打卡:2026-07-04 00:01:55
已绑定手机

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 2026-6-26 10:33:52 | 显示全部楼层
点阵LED应用
功耗大概有多少
永怀这学徒心
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-07-04 22:38:22
已绑定手机

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 2026-6-26 10:48:59 | 显示全部楼层
狂热主宰 发表于 2026-6-26 10:33
点阵LED应用
功耗大概有多少

这一个,用usb供电的,未测量
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:299
  • 最近打卡:2026-07-04 00:01:55
已绑定手机

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 2026-6-26 10:52:52 | 显示全部楼层
yyq_007 发表于 2026-6-26 10:48
这一个,用usb供电的,未测量

通常应用在广告牌方面
物料选型需要考虑
选择合适器件
永怀这学徒心
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-7-5 14:04 , Processed in 0.868967 second(s), 79 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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