找回密码
 立即注册
查看: 93|回复: 10

基于6引脚8.8.8.数码管的99.9秒显示器

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

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 6 天前 | 显示全部楼层 |阅读模式
    1.电路板电路原理
   “擎天柱Ai8051U转89C52-DIP40核心板”,用AI8051U-34k64单片机的timer0产生100us中断,作查理复用方式的LED的底层驱动,timer1中断产生1s计时,累加计时产生1s时间,制作0~99.9计时器,P33外接按键控制定时器启动、暂停、清零,单排6脚3位8.8.8.数码管显示。


   2. 6引脚8.8.8.数码管的电路结构
   3.源代码
   
  1. //主程序文件 main.c
  2. //AI8051U驱动三位8.8.8数码管显示的999s计时器  下载成功     32bit模式
  3. /**********************************************************
  4. 三位8.8.8数码管,共6个引脚,引脚组合
  5. ---    PIN1  PIN2  PIN3  PIN4  PIN5  PIN6 列/阳极
  6. PIN1    --    DP1   DP2    --   --    --
  7. PIN2    --    --    F1    G1    C1    --
  8. PIN3    --    A1    --    F2    G2    E2
  9. PIN4    --    B1    D2    --    A2    D3
  10. PIN5    G3    E1    B2    C2    --    F3
  11. PIN6    A3    D1    B3    E3    C3    --
  12. 行/阴极
  13. ********************************************************/
  14. #include "AI8051U.h"                       //调用头文件 手册 AI8051U.PDF
  15. #include "stc32_stc8_usb.h"                //调用头文件
  16. #include "intrins.h"                            //调用头文件
  17. #include "led.h"              //调用led扫描头文件
  18. #include "timer.h"            //调用timer初始化头文件
  19. #include "key.h"              //调用按键扫描头文件
  20. //#include "def.h"                   //调用定义数据类型头文件main.c里包含该头文件
  21. #define MAIN_Fosc        24000000UL   //时钟24MHZ
  22. //全局变量声明
  23. volatile u8 T1_1Sflag=0;          //timer1溢出标志
  24. volatile bit key_stime_ok;        //10ms按键时间标志
  25. volatile u8 T1_100ms,T1_1S = 0;   //100ms,1s计时单元
  26. volatile u8 buff[3];              //显存
  27. void main(void)
  28. {
  29.           u16 T1_1S=0,T1_cnt=0;         //T1秒计时,及10ms计时
  30.           u8 times = 0,Key_value = 0;   //按键次数,键值
  31.     WTST = 0;        //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  32.     P_SW2 |= EAXFR;  //扩展寄存器(XFR)访问使能
  33.     CKCON = 0;       //提高访问XRAM速度
  34.        
  35.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
  36.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
  37.     //P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  38.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  39.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  40.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  41.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  42.          Timer0_init( );             //timer0初始化函数
  43.          Timer1_init( );             //timer1初始化函数
  44.          EA  = 1;                   // 开总中断   
  45.    ET0 = 1;                  // 定时/计数器0允许中断  
  46.    ET1 = 1;                  // 定时/计数器1允许中断  
  47.    while (1)
  48.   {
  49.           
  50.                 if(key_stime_ok)          //10s按键扫描时间到
  51.                 {
  52.                    key_stime_ok = 0;      //10ms按键时间标志清0
  53.                          if(read_key())         //读取键值
  54.                          {
  55.                                  times++;             //按键次数加1
  56.                            if(3 == times)       //按键次数达3次
  57.            times = 0;         //按键次数清0
  58.                                  switch (times)       //根据按键次数执行不同的动作
  59.                                   {
  60.                                           case 1:
  61.                                                       TR1 = 1;    //T0开始运行
  62.                                               break;
  63.                                           case 2:
  64.                                                       TR1 = 0;    //T0暂停运行
  65.                                               break;
  66.                                                 case 0:
  67.                                                       TR1 = 0;       //T0停止运行
  68.                                                       T1_100ms = 0;  //100ms计时单元清0
  69.                                                       T1_1S = 0;     //1s计时器清0
  70.                                               break;
  71.                                  }
  72.                          }
  73.      }                         
  74.                 if(1==T1_1Sflag)          //如果timer1定时1s溢出标志为1
  75.            {
  76.                            T1_1Sflag = 0;        // 必须声明为volatile,防止编译器优化,后面可以省略延时
  77.          //DG_Display(buff[0],0,buff[1],0,buff[2]);   //显示xx.x
  78.                            if(++T1_cnt == 100)   //10ms*100=1s
  79.                                  {
  80.                                            T1_cnt = 0;                                 
  81.                                            //P2^=0xff;       //调试用
  82.                                            T1_1S++;
  83.                                          if(T1_1S > 99)
  84.                                                  T1_1S = 0;
  85.                                  }
  86.      }
  87.      //DG_Display(buff[0],0,buff[1],1,buff[2]);   //显示xx.x 放此处无法显示100ms
  88.      buff[0] =         T1_1S / 10; buff[1] =         T1_1S % 10; buff[2] = T1_100ms;
  89.   }
  90. }
  91. //========================================================================
  92. // 函数: void timer0_int (void) interrupt TIMER0_VECTOR
  93. // 描述:  timer0中断函数.
  94. // 参数: none.
  95. // 返回: none.
  96. // 版本: V1.0, 2015-1-12
  97. //========================================================================
  98. void timer0_int (void) interrupt 1   //100us中断一次
  99. {
  100.            static u8 T0_cnt = 0;
  101.                  Led_under_deal( );                    //数码管灯阵扫描函数
  102.                  if(++T0_cnt == 100)            //满100us*100=10ms
  103.                  {
  104.                          T0_cnt = 0;
  105.                          key_stime_ok = 1;                          //按键扫描标志置1
  106.                          DG_Display(buff[0],0,buff[1],1,buff[2]);   //显示xx.x
  107.                  }
  108.                          
  109. }
  110. //========================================================================
  111. // 函数: void timer1_int (void) interrupt TIMER1_VECTOR
  112. // 描述:  timer1中断函数.
  113. // 参数: none.
  114. // 返回: none.
  115. // 版本: V1.0, 2015-1-12
  116. //========================================================================
  117. void timer1_int (void) interrupt 3
  118. {
  119.     static u8 T1_cnt = 0;
  120.           if(++T1_cnt == 50)     //满2ms*50=100ms
  121.                 {
  122.                         T1_cnt = 0;
  123.                         T1_100ms++;         //T1定时100ms单元加1
  124.                         if(10 == T1_100ms)
  125.                         {
  126.                                 T1_100ms = 0;
  127.                                 T1_1Sflag = 1;          //timer1定时1s溢出标志置1
  128.                         }
  129.                 }
  130. }
复制代码
  1. //按键扫描C文件   key.c
  2. #include "key.h"        //调用按键扫描头文件  
  3. #include "AI8051U.h"                //调用头文件 手册 AI8051U.PDF
  4. //======基于状态机的按键处理程序=============================
  5. sbit KWIN = P3^3;         //单按键位置INT1
  6. #define key_state_0  0     //状态0,初态,无按键按下
  7. #define key_state_1  1    //状态1,按键确认态
  8. #define key_state_2  2    //状态2,计时1
  9. unsigned char read_key(void)
  10. {
  11.         static unsigned char key_state = 0;
  12.         unsigned char key_press, key_return = 0;
  13.         P3M1 &= ~(1 << 3);   P3M0 &= ~(1 << 3);   //P33设置为准双向口
  14.         P3 |= 1 << 3;        //P33写1
  15.         key_press = KWIN;       // 读按键I/O电平
  16.         switch (key_state)
  17.         {
  18.                 case key_state_0:// 按键初始态
  19.                                 if (!key_press) key_state = key_state_1;// 键被按下,状态转换到键确认态
  20.                                 break;
  21.                 case key_state_1:// 按键确认态
  22.                                         if (!key_press)
  23.             {
  24.                 key_return = 1;// 输出"1"
  25.                                                         key_state = key_state_2;// 按键仍按下,状态转换到计时1
  26.             }
  27.                                 else
  28.                                                 key_state = key_state_0;// 按键已抬起,转换到按键初始态
  29.                                 break;
  30.                 case key_state_2:
  31.                                 if (key_press)
  32.            key_state = key_state_0;// 按键已释放,转换到按键初始态
  33.                                 break;
  34.   }
  35.     return key_return;
  36. }
  37.   
复制代码

  1. //LED驱动函数C文件   led.c
  2. #include "led.h"
  3. /**********************************************************
  4. 三位8.8.8数码管,共6个引脚,引脚组合
  5. ---    PIN1  PIN2  PIN3  PIN4  PIN5  PIN6 列/阳极
  6. PIN1    --    DP1   DP2    --   --    --
  7. PIN2    --    --    F1    G1    C1    --
  8. PIN3    --    A1    --    F2    G2    E2
  9. PIN4    --    B1    D2    --    A2    D3
  10. PIN5    G3    E1    B2    C2    --    F3
  11. PIN6    A3    D1    B3    E3    C3    --
  12. 行/阴极
  13. ********************************************************/
  14. ByteBit_Union DG1_Flag = {0};    //变量不可以放led.h文件里定义
  15. ByteBit_Union DG2_Flag = {0};    //此处定义可以加初值
  16. ByteBit_Union DG3_Flag = {0};
  17. /*********************************************************
  18. 函  数:Led_under_deal
  19. 描  述:    LED底层处理(正反扫)(100us 中断)
  20. 输入值: 无
  21. 输出值: 无
  22. 返回值: 无
  23. **********************************************************/
  24. void Led_under_deal(void)
  25. {
  26.         static    unsigned char led_disp_step = 0; //static
  27.         //全部端口为输入口
  28.         led_io_1_in;
  29.         led_io_2_in;
  30.         led_io_3_in;
  31.         led_io_4_in;
  32.         led_io_5_in;
  33.         led_io_6_in;
  34.         clr_led_io_1;  //
  35.         clr_led_io_2;
  36.         clr_led_io_3;
  37.         clr_led_io_4;
  38.         clr_led_io_5;
  39.         clr_led_io_6;
  40.         //根据引脚组合按行扫描
  41.         if(led_disp_step==0)   //第一行
  42.         {
  43.                 if(DG1_DP)
  44.                 {
  45.                         led_io_2_out;
  46.                         set_led_io_2;
  47.                 }
  48.                 if(DG2_DP)
  49.                 {
  50.                         led_io_3_out;
  51.                         set_led_io_3;
  52.                 }
  53.                 led_io_1_out;
  54.                 clr_led_io_1;
  55.         }
  56.         else if(led_disp_step==1)  //第二行
  57.         {
  58.                 if(DG1_F)
  59.                 {
  60.                         led_io_3_out;
  61.                         set_led_io_3;
  62.                 }
  63.                 if(DG1_G)
  64.                 {
  65.                         led_io_4_out;
  66.                         set_led_io_4;
  67.                 }
  68.                 if(DG1_C)
  69.                 {
  70.                         led_io_5_out;
  71.                         set_led_io_5;
  72.                 }
  73.                 led_io_2_out;
  74.                 clr_led_io_2;
  75.         }
  76.         else if(led_disp_step==2) //第三行
  77.         {
  78.                 if(DG1_A)
  79.                 {
  80.                         led_io_2_out;
  81.                         set_led_io_2;
  82.                 }
  83.                 if(DG2_F)
  84.                 {
  85.                         led_io_4_out;
  86.                         set_led_io_4;
  87.                 }
  88.                 if(DG2_G)
  89.                 {
  90.                         led_io_5_out;
  91.                         set_led_io_5;
  92.                 }
  93.                 if(DG2_E)
  94.                 {
  95.                         led_io_6_out;
  96.                         set_led_io_6;
  97.                 }
  98.                 led_io_3_out;
  99.                 clr_led_io_3;
  100.         }
  101.         else if(led_disp_step==3)  //第四行
  102.         {
  103.                 if(DG1_B)
  104.                 {
  105.                         led_io_2_out;
  106.                         set_led_io_2;
  107.                 }
  108.                 if(DG2_D)
  109.                 {
  110.                         led_io_3_out;
  111.                         set_led_io_3;
  112.                 }
  113.                 if(DG2_A)
  114.                 {
  115.                         led_io_5_out;
  116.                         set_led_io_5;
  117.                 }
  118.                 if(DG3_D)
  119.                 {
  120.                         led_io_6_out;
  121.                         set_led_io_6;
  122.                 }
  123.                 led_io_4_out;
  124.                 clr_led_io_4;
  125.         }
  126.         else if(led_disp_step==4)  //第5行
  127.         {
  128.                 if(DG3_G)
  129.                 {
  130.                         led_io_1_out;
  131.                         set_led_io_1;
  132.                 }
  133.                 if(DG1_E)
  134.                 {
  135.                         led_io_2_out;
  136.                         set_led_io_2;
  137.                 }
  138.                 if(DG2_B)
  139.                 {
  140.                         led_io_3_out;
  141.                         set_led_io_3;
  142.                 }
  143.                 if(DG2_C)
  144.                 {
  145.                         led_io_4_out;
  146.                         set_led_io_4;
  147.                 }
  148.                 if(DG3_F)
  149.                 {
  150.                         led_io_6_out;
  151.                         set_led_io_6;
  152.                 }
  153.                 led_io_5_out;
  154.                 clr_led_io_5;
  155.         }
  156.         else if(led_disp_step==5)  //第6行
  157.         {
  158.                 if(DG3_A)
  159.                 {
  160.                         led_io_1_out;
  161.                         set_led_io_1;
  162.                 }
  163.                 if(DG1_D)
  164.                 {
  165.                         led_io_2_out;
  166.                         set_led_io_2;
  167.                 }
  168.                 if(DG3_B)
  169.                 {
  170.                         led_io_3_out;
  171.                         set_led_io_3;
  172.                 }
  173.                 if(DG3_E)
  174.                 {
  175.                         led_io_4_out;
  176.                         set_led_io_4;
  177.                 }
  178.                 if(DG3_C)
  179.                 {
  180.                         led_io_5_out;
  181.                         set_led_io_5;
  182.                 }
  183.                 led_io_6_out;
  184.                 clr_led_io_6;
  185.         }
  186.         led_disp_step++;
  187.         if(led_disp_step>=6)led_disp_step=0;
  188. }
  189. /*数码全显或全关*/
  190. void DG_ALL(unsigned char EN_DIS)
  191. {
  192.         if(EN_DIS)        //全开
  193.         {
  194.                 DG1_Flag.byte = 0xff;
  195.                 DG2_Flag.byte = 0xff;
  196.         DG3_Flag.byte = 0xff;       
  197.         }
  198.         else        //全关
  199.         {
  200.                 DG1_Flag.byte = 0;
  201.                 DG2_Flag.byte = 0;                               
  202.                 DG3_Flag.byte = 0;
  203.         }
  204. }
  205. //3位数码管,显示00.9,dp1为百位小数点,dp2为十位小数点
  206. void DG_Display(u8 num1,u8 dp1,u8 num2,u8 dp2,u8 num3)
  207. {       
  208.         DG_ALL(0);  //全写0,灭
  209.     if(1 == dp1) DG1_DP = 1;   //显示第一位.
  210.     if(1 == dp2) DG2_DP = 1;   //显示第二位.
  211.         switch(num1)
  212.         {
  213.                 case 0:        //A.B.C.D.E.F
  214.             //if(1 == dp1) DG1_DP = 1;   //.
  215.                         DG1_A = 1;DG1_B = 1;DG1_C = 1;
  216.             DG1_D = 1;DG1_E = 1;DG1_F = 1;         
  217.                         break;
  218.                 case 1:        //B.C
  219.                     DG1_B = 1;DG1_C = 1;       
  220.                         break;
  221.                 case 2:        //A.B.D.E.G
  222.                     DG1_A = 1;DG1_B = 1;DG1_D = 1;
  223.             DG1_E = 1;DG1_G = 1;
  224.                         break;               
  225.                 case 3:        //A.B.C.D.G
  226.                     DG1_A = 1;DG1_B = 1;DG1_C = 1;
  227.             DG1_D = 1;DG1_G = 1;       
  228.                         break;
  229.                 case 4:        //B.C.F.G
  230.                     DG1_B = 1;DG1_C = 1;DG1_F = 1;
  231.                         DG1_G = 1;       
  232.                         break;
  233.                 case 5:        //A.C.D.F.G
  234.                     DG1_A = 1;
  235.                         DG1_C = 1;DG1_D = 1;
  236.                         DG1_F = 1;DG1_G = 1;       
  237.                         break;       
  238.                 case 6:        //A.C.D.E.F.G
  239.                     DG1_A = 1;DG1_C = 1;DG1_D = 1;
  240.                         DG1_E = 1;DG1_F = 1;DG1_G = 1;       
  241.                         break;               
  242.                 case 7:        //A.B.C
  243.                     DG1_A = 1;DG1_B = 1;DG1_C = 1;       
  244.                         break;
  245.                 case 8:        //A.B.C.D.E.F.G
  246.                     DG1_A = 1;DG1_B = 1;DG1_C = 1;DG1_D = 1;
  247.                         DG1_E = 1;DG1_F = 1;DG1_G = 1;       
  248.                         break;
  249.                 case 9:        //A.B.C.D.F.G
  250.                     DG1_A = 1;DG1_B = 1;DG1_C = 1;
  251.             DG1_D = 1;DG1_F = 1;DG1_G = 1;               
  252.                         break;
  253.         default:break;                       
  254.         }
  255.         switch(num2)
  256.         {
  257.                 case 0:        //A.B.C.D.E.F
  258.            //if(1 == dp2) DG2_DP = 1;   //.
  259.                         DG2_A = 1;DG2_B = 1;DG2_C = 1;
  260.             DG2_D = 1;DG2_E = 1;DG2_F = 1;      
  261.                         break;
  262.                 case 1:        //B.C
  263.                         DG2_B = 1;DG2_C = 1;
  264.                         break;
  265.                 case 2:        //A.B.D.E.G
  266.                         DG2_A = 1;DG2_B = 1;DG2_D = 1;
  267.                         DG2_E = 1;DG2_G = 1;
  268.                         break;               
  269.                 case 3:        //A.B.C.D.G
  270.                         DG2_A = 1;DG2_B = 1;DG2_C = 1;
  271.             DG2_D = 1;DG2_G = 1;
  272.                         break;
  273.                 case 4:        //B.C.F.G
  274.                         DG2_B = 1;DG2_C = 1;DG2_F = 1;DG2_G = 1;
  275.                         break;
  276.                 case 5:        //A.C.D.F.G
  277.                         DG2_A = 1;DG2_C = 1;DG2_D = 1;
  278.                         DG2_F = 1;DG2_G = 1;
  279.                         break;       
  280.                 case 6:        //A.C.D.E.F.G
  281.                         DG2_A = 1;DG2_C = 1;DG2_D = 1;
  282.                         DG2_E = 1;DG2_F = 1;DG2_G = 1;
  283.                         break;               
  284.                 case 7:        //A.B.C
  285.                         DG2_A = 1;DG2_B = 1;DG2_C = 1;
  286.                         break;
  287.                 case 8:        //A.B.C.D.E.F.G
  288.                         DG2_A = 1;DG2_B = 1;DG2_C = 1;DG2_D = 1;
  289.                         DG2_E = 1;DG2_F = 1;DG2_G = 1;
  290.                         break;
  291.                 case 9:        //A.B.C.D.F.G
  292.                         DG2_A = 1;DG2_B = 1;DG2_C = 1;
  293.             DG2_D = 1;DG2_F = 1;DG2_G = 1;
  294.                         break;
  295.         default:break;                       
  296.         }
  297.         switch(num3)
  298.         {
  299.                 case 0:        //A.B.C.D.E.F
  300.                         DG3_A = 1;DG3_B = 1;DG3_C = 1;
  301.             DG3_D = 1;DG3_E = 1;DG3_F = 1;      
  302.                         break;
  303.                 case 1:        //B.C
  304.                         DG3_B = 1;DG3_C = 1;
  305.                         break;
  306.                 case 2:        //A.B.D.E.G
  307.                         DG3_A = 1;DG3_B = 1;DG3_D = 1;
  308.             DG3_E = 1;DG3_G = 1;
  309.                         break;               
  310.                 case 3:        //A.B.C.D.G
  311.                         DG3_A = 1;DG3_B = 1;DG3_C = 1;
  312.             DG3_D = 1;DG3_G = 1;
  313.                         break;
  314.                 case 4:        //B.C.F.G
  315.                         DG3_B = 1;DG3_C = 1;
  316.                         DG3_F = 1;DG3_G = 1;
  317.                         break;
  318.                 case 5:        //A.C.D.F.G
  319.                         DG3_A = 1;DG3_C = 1;DG3_D = 1;
  320.             DG3_F = 1;DG3_G = 1;
  321.                         break;       
  322.                 case 6:        //A.C.D.E.F.G
  323.                         DG3_A = 1;DG3_C = 1;DG3_D = 1;
  324.                         DG3_E = 1;DG3_F = 1;DG3_G = 1;
  325.                         break;               
  326.                 case 7:        //A.B.C
  327.                         DG3_A = 1;DG3_B = 1;DG3_C = 1;
  328.                         break;
  329.                 case 8:        //A.B.C.D.E.F.G
  330.                         DG3_A = 1;DG3_B = 1;DG3_C = 1;DG3_D = 1;
  331.                         DG3_E = 1;DG3_F = 1;DG3_G = 1;
  332.                         break;
  333.                 case 9:        //A.B.C.D.F.G
  334.                         DG3_A = 1;DG3_B = 1;DG3_C = 1;
  335.             DG3_D = 1;DG3_F = 1;DG3_G = 1;
  336.                         break;
  337.         default:break;                       
  338.         }
  339.        
  340. }
复制代码
  1. //led扫描头文件  led.h
  2. #ifndef __LED_H__            
  3. #define __LED_H__
  4. #include "AI8051U.h"                //调用头文件 手册 AI8051U.PDF
  5. #include "def.h"                   //调用定义数据类型头文件
  6. //typedef         unsigned char        u8;
  7. //typedef         unsigned int        u16;
  8. //typedef         unsigned long        u32;
  9. //#define u8  unsigned char
  10. //#define u16  unsigned int
  11.        
  12. typedef union
  13. {
  14.         unsigned char byte;
  15.         struct{
  16.                 unsigned char bit0:1;
  17.                 unsigned char bit1:1;
  18.                 unsigned char bit2:1;
  19.                 unsigned char bit3:1;
  20.                 unsigned char bit4:1;
  21.                 unsigned char bit5:1;
  22.                 unsigned char bit6:1;
  23.                 unsigned char bit7:1;
  24.         }Bits;
  25. }ByteBit_Union;
  26. //#define  led_io_6  P05   //led io口
  27. //#define  led_io_5  P04   //led io口
  28. //#define  led_io_4  P03   //led io口
  29. //#define  led_io_3  P02   //led io口
  30. //#define  led_io_2  P01   //led io口
  31. //#define  led_io_1  P00   //led io口
  32. //某位清0
  33. //#define  clr_led_io_6   P0 &=  ~(1<<5)        //led_io_6=0
  34. #define  clr_led_io_6   P05 = 0
  35. #define  clr_led_io_5   P04 = 0         //led io口清0
  36. #define  clr_led_io_4   P03 = 0         //led io口清0
  37. #define  clr_led_io_3   P02 = 0         //led io口清0
  38. #define  clr_led_io_2   P01 = 0          //led io口清0
  39. #define  clr_led_io_1   P00 = 0          //led io口清0
  40. //某位置1
  41. //#define  set_led_io_6   P0 |=  (1<<5)   //led io口写1
  42. #define  set_led_io_6   P05 = 1
  43. #define  set_led_io_5   P04 = 1        //led io口写1
  44. #define  set_led_io_4   P03 = 1      //led io口写1
  45. #define  set_led_io_3   P02 = 1      //led io口写1
  46. #define  set_led_io_2   P01 = 1       //led io口写1
  47. #define  set_led_io_1   P00 = 1       //led io口写1
  48. #define  led_io_6_in  {P0M1 |=1<<5;P0M0 &= ~(1<<5);}   //io6置为高阻输入
  49. #define  led_io_5_in  {P0M1 |=1<<4;P0M0 &= ~(1<<4);}        //io5置为输入
  50. #define  led_io_4_in  {P0M1 |=1<<3;P0M0 &= ~(1<<3);}        //io4置为输入
  51. #define  led_io_3_in  {P0M1 |=1<<2;P0M0 &= ~(1<<2);}        //io3置为输入
  52. #define  led_io_2_in  {P0M1 |=1<<1;P0M0 &= ~(1<<1);}        //io2置为输入
  53. #define  led_io_1_in  {P0M1 |=1<<0;P0M0 &= ~(1<<0);}        //io1置为输入
  54. #define  led_io_6_out  {P0M1 &= ~(1<<5);P0M0|=1<<5;}
  55. #define  led_io_5_out  {P0M1 &= ~(1<<4);P0M0|=1<<4;}   //io5置为推挽输出
  56. #define  led_io_4_out  {P0M1 &= ~(1<<3);P0M0|=1<<3;}   //io4置为输出
  57. #define  led_io_3_out  {P0M1 &= ~(1<<2);P0M0|=1<<2;}   //io3置为输出
  58. #define  led_io_2_out  {P0M1 &= ~(1<<1);P0M0|=1<<1;}   //io2置为输出
  59. #define  led_io_1_out  {P0M1 &= ~(1<<0);P0M0|=1<<0;}   //io1置为输出
  60. /*数码管段显*/
  61. extern ByteBit_Union DG1_Flag;
  62. #define DG1_A DG1_Flag.Bits.bit0
  63. #define DG1_B DG1_Flag.Bits.bit1
  64. #define DG1_C DG1_Flag.Bits.bit2
  65. #define DG1_D DG1_Flag.Bits.bit3
  66. #define DG1_E DG1_Flag.Bits.bit4
  67. #define DG1_F DG1_Flag.Bits.bit5
  68. #define DG1_G DG1_Flag.Bits.bit6
  69. #define DG1_DP DG1_Flag.Bits.bit7
  70. extern ByteBit_Union DG2_Flag;
  71. #define DG2_A DG2_Flag.Bits.bit0
  72. #define DG2_B DG2_Flag.Bits.bit1
  73. #define DG2_C DG2_Flag.Bits.bit2
  74. #define DG2_D DG2_Flag.Bits.bit3
  75. #define DG2_E DG2_Flag.Bits.bit4
  76. #define DG2_F DG2_Flag.Bits.bit5
  77. #define DG2_G DG2_Flag.Bits.bit6
  78. #define DG2_DP DG2_Flag.Bits.bit7
  79. extern ByteBit_Union DG3_Flag;
  80. #define DG3_A DG3_Flag.Bits.bit0
  81. #define DG3_B DG3_Flag.Bits.bit1
  82. #define DG3_C DG3_Flag.Bits.bit2
  83. #define DG3_D DG3_Flag.Bits.bit3
  84. #define DG3_E DG3_Flag.Bits.bit4
  85. #define DG3_F DG3_Flag.Bits.bit5
  86. #define DG3_G DG3_Flag.Bits.bit6
  87. //#define DG3_DP DG3_Flag.Bits.bit7
  88. void Led_under_deal(void);                //数码管灯阵扫描函数,100us调用一次
  89. void DG_ALL(unsigned char EN_DIS);        //数码全显或全关
  90. //3位数码管,显示00.9,dp1为百位小数点,dp2为十位小数点
  91. void DG_Display(u8 num1,u8 dp1,u8 num2,u8 dp2,u8 num3);
  92. //extern ByteBit_Union DG1_Flag;    //变量放led.h文件里声明需加extern修饰
  93. //extern ByteBit_Union DG2_Flag;    //但不可定义,加上初值
  94. //extern ByteBit_Union DG3_Flag;
  95. #endif
复制代码
  1. //timer初始化C文件
  2. #include "timer.h"      //调用timer初始化头文件
  3. #include "AI8051U.h"                //调用头文件 手册 AI8051U.PDF
  4.        
  5. #define MAIN_Fosc        24000000UL   //时钟24MHZ
  6. //24MHZ,1T,一条指令耗时1/24us,定时100us,初值2400
  7. //Timer 0 中断频率, 10000次/秒,定时100us,1/100us=10000HZ
  8. #define Timer0_Reload   (MAIN_Fosc / 10000)   //定时100us
  9. #define Timer1_Reload   (MAIN_Fosc / 48000)   //定时2ms
  10. //官方文件
  11. void Timer0_init(void)
  12. {
  13.         TR0 = 0;    //停止计数
  14.     #if (Timer0_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
  15.         #error "Timer0设置的中断过快!"
  16.     #elif ((Timer0_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
  17.         ET0 = 1;    //允许中断
  18.     //  PT0 = 1;    //高优先级中断
  19.         TMOD &= ~0x03;
  20.         TMOD |= 0;  //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
  21.     //  T0_CT = 1;  //计数
  22.         T0_CT = 0;  //定时
  23.     //  T0CLKO = 1; //输出时钟
  24.         T0CLKO = 0; //不输出时钟
  25.         #if (Timer0_Reload < 65536UL)
  26.             T0x12 = 1;  //1T mode
  27.             TH0 = (u8)((65536UL - Timer0_Reload) / 256);
  28.             TL0 = (u8)((65536UL - Timer0_Reload) % 256);
  29.         #else
  30.             T0x12 = 0;  //12T mode
  31.             TH0 = (u8)((65536UL - Timer0_Reload/12) / 256);
  32.             TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);
  33.         #endif
  34.         TR0 = 1;    //开始运行
  35.     #else
  36.         #error "Timer0设置的中断过慢!"
  37.     #endif
  38. }
  39. //========================================================================
  40. // 函数: void Timer1_init(void)
  41. // 描述: timer1初始化函数.
  42. // 参数: none.
  43. // 返回: none.
  44. // 版本: V1.0, 2015-1-12
  45. //========================================================================
  46. void Timer1_init(void)
  47. {
  48.         TR1 = 0;    //停止计数
  49.     #if (Timer1_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
  50.         #error "Timer1设置的中断过快!"
  51.     #elif ((Timer1_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
  52.         ET1 = 1;    //允许中断
  53.     //  PT1 = 1;    //高优先级中断
  54.         TMOD &= ~0x30;
  55.         TMOD |= (0 << 4);   //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
  56.     //  T1_CT = 1;  //计数
  57.         T1_CT = 0;  //定时
  58.     //  T1CLKO = 1; //输出时钟
  59.         T1CLKO = 0; //不输出时钟
  60.         #if (Timer1_Reload < 65536UL)
  61.             T1x12 = 1;  //1T mode
  62.             TH1 = (u8)((65536UL - Timer1_Reload) / 256);
  63.             TL1 = (u8)((65536UL - Timer1_Reload) % 256);
  64.         #else
  65.             T1x12 = 0;  //12T mode
  66.             TH1 = (u8)((65536UL - Timer1_Reload/12) / 256);
  67.             TL1 = (u8)((65536UL - Timer1_Reload/12) % 256);
  68.         #endif
  69.         //TR1 = 1;    //开始运行
  70.     #else
  71.         #error "Timer1设置的中断过慢!"
  72.     #endif
  73. }
复制代码
  1. //timer.h
复制代码
4.视频效果

111.png

q.mp4

4.53 MB, 下载次数: 3

回复

使用道具 举报 送花

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

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 6 天前 | 显示全部楼层
这种方式用少量io引脚
而io需支持高阻
永怀这学徒心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:788
  • 最近打卡:2026-07-05 13:03:19
已绑定手机

50

主题

2745

回帖

3039

积分

荣誉版主

积分
3039
发表于 6 天前 | 显示全部楼层
显示驱动部分要是有详细注释就更好了
~~~
回复

使用道具 举报 送花

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

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 6 天前 | 显示全部楼层
经典的89系列没有高阻模式
永怀这学徒心
回复

使用道具 举报 送花

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

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 6 天前 | 显示全部楼层
1. LED底层处理(正反扫)(100us 中断)

void Led_under_deal(void)
要结合表格三位8.8.8数码管,共6个引脚,引脚组合
---    PIN1  PIN2  PIN3  PIN4  PIN5  PIN6   列/阳极
PIN1    --    DP1   DP2    --   --    --            第一行
PIN2    --    --    F1    G1    C1    --            第2行
PIN3    --    A1    --    F2    G2    E2
PIN4    --    B1    D2    --    A2    D3
PIN5    G3    E1    B2    C2    --    F3
PIN6    A3    D1    B3    E3    C3    --
行/阴极
例如      if(led_disp_step==0)   //第一行
45.         {
46.                 if(DG1_DP)      //点亮DG1_DP
47.                 {
48.                         led_io_2_out;    //正极输出口
49.                         set_led_io_2;     //正极输出1
50.                 }
51.                 if(DG2_DP)         //点亮DG2_DP
52.                 {
53.                         led_io_3_out;    //正极输出口
54.                         set_led_io_3;     //输出1
55.                 }
56.                 led_io_1_out;       //负极输出口
57.                 clr_led_io_1;        //负极输出0
58.         }
为了可以使用每一段,定义了联合位域结构体。
2. //3位数码管,显示00.9,dp1为百位小数点,dp2为十位小数点
void DG_Display(u8 num1,u8 dp1,u8 num2,u8 dp2,u8 num3)
{        
        case 0:        //A.B.C.D.E.F  这里实际采用了共阴数码管的字段码,显示0,码是0x3f,其他类似
回复

使用道具 举报 送花

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

10

主题

13

回帖

216

积分

中级会员

积分
216
发表于 6 天前 | 显示全部楼层
为了限流,每一个LED引脚串联了47欧+47欧电阻

点评

从我的实践经验来看,相比高阻模式+推挽模式的组合,使用开漏模式+内部上拉实现的效果更好一些,而且更省物料 查理复用结构的数码管每个IO都串限流电阻的话,容易出现部分笔划亮度不均匀的情况 理由如下: 如果IO直  详情 回复 发表于 5 天前
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:120
  • 最近打卡:2026-07-05 08:00:11
已绑定手机

3

主题

180

回帖

857

积分

高级会员

积分
857
发表于 5 天前 | 显示全部楼层
yyq_*** 发表于 2026-6-29 17:21
为了限流,每一个LED引脚串联了47欧+47欧电阻

https://www.stcaimcu.com/forum.p ... 4176&pid=219748
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:394
  • 最近打卡:2026-07-05 12:28:34

83

主题

7889

回帖

1万

积分

超级版主

积分
16831
发表于 5 天前 | 显示全部楼层
楼主程序整得比较复杂,其实这种数码管有规律的,按照其规律驱动,程序会比较简单。

这种数码管常见于移动电源(充电宝)、无线话筒、小家电上。
大量使用的充电宝的驱动方式,N个IO最多可以驱动N(N-1)个LED,称之为“查理复用”,驱动原则是:
分N个时隙驱动,每次驱动时一个IO做COM驱动,另外(N-1)个IO做SEG驱动。
先把所有IO设置为高阻。
对于共阴,不显示的SEG为高阻,显示的SEG推挽输出1, COM推挽输出0。
对于共阳,不显示的SEG为高阻,显示的SEG推挽输出0, COM推挽输出1。
回复

使用道具 举报 送花

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

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 5 天前 | 显示全部楼层
梁*** 发表于 2026-6-30 10:59
楼主程序整得比较复杂,其实这种数码管有规律的,按照其规律驱动,程序会比较简单。

这种数码管常见于移动 ...

学习初期自个思考的常见写法
后期可尝试整理使用循环和数组
逻辑整合简化可能程序到百行左右
永怀这学徒心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:788
  • 最近打卡:2026-07-05 13:03:19
已绑定手机

50

主题

2745

回帖

3039

积分

荣誉版主

积分
3039
发表于 5 天前 | 显示全部楼层
yyq_*** 发表于 2026-6-29 17:21
为了限流,每一个LED引脚串联了47欧+47欧电阻

从我的实践经验来看,相比高阻模式+推挽模式+外部限流电阻的组合,使用开漏模式+内部上拉实现的效果更好一些,而且更省物料
查理复用结构的数码管每个IO都串限流电阻的话,容易出现部分笔划亮度不均匀的情况
~~~
回复

使用道具 举报 送花

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

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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