51 入门 1 - 3

预备1 基础与 LED 灯控制

一、开发环境配置

1. 设置 Proteus 管理员权限

为避免仿真时出现权限问题,建议以管理员身份运行 Proteus 软件。

2. 创建编译环境

确保已安装 Keil C51 等单片机开发工具,并正确配置工程路径、芯片型号及编译选项。

二、认识原理图

下图为一个典型的单片机控制 LED 的原理示意图:

在原理图中,需要关注:

  • 单片机引脚与 LED 的连接方式

  • 电源与接地

  • 复位电路与晶振电路

三、工程思想:引脚编码的两种格式

在单片机编程中,操作引脚有两种常见方式:

  1. 整体操作整个端口
    例如:P1 = 0x55; 一次性设置 P1 口所有引脚的电平。

  2. 操作单个引脚
    例如:P1_0 = 0; 只设置 P1 口的第 0 引脚。

四、点亮 LED(基础示例)

 /*
 这里熟一下引脚
 开发板上LED接的是P0口接上拉电阻的形式,但是Protues仿真上接的是P1口,可能是板子不一样了,也可能是P0口比较特殊的原因。
 总之,注意顺序,LED1 -> P0_0 
 以此类推
 */

 /* 头文件区域 */
 #include <REGX52.H>
 ​
 /* Main 函数 */
 void main()
 {    
     // 单片机通过循环不断执行程序
     while(1)
     {
         // P1 = 0x55;      // 整体赋值,0101 0101
         P1 = 0xAA;          // 整体赋值,1010 1010
         P1_0 = 0;           // 将 P1.0 引脚设为低电平(点亮 LED)
         P2_2 = 1;           // 将 P2.2 引脚设为高电平(熄灭 LED)
     }
 }

五、延时函数

示例1:使用 ISP 工具生成的固定延时函数

 void Delay100ms(void)    //@12.000MHz
 {
     unsigned char data i, j;
 ​
     i = 195;
     j = 138;
     do
     {
         while (--j);
     } while (--i);
 }

示例2:可自定义时长的通用延时函数

 /* 延时函数 */
 void Delay(unsigned char xms)    //@12.000MHz
 {
     while(xms--)
     {
         unsigned char data i, j;
 ​
         i = 195;
         j = 138;
         do
         {
             while (--j);
         } while (--i);
     }
 }

示例3:LED 流水灯效果

 /* 头文件区域 */
 #include "REG52.H"
 #include "intrins.h"
 ​
 /* 延时函数 */
 void Delay(unsigned char xms)    //@12.000MHz
 {
     while(xms--)
     {
         unsigned char data i, j;
 ​
         i = 195;
         j = 138;
         do
         {
             while (--j);
         } while (--i);
     }
 }
 ​
 /* 变量声明 */
 unsigned char ucLed = 0xfe;      // 初始值 1111 1110,最低位为0,对应 LED 亮
 ​
 /* Main 函数 */
 void main()
 {    
     while(1)
     {
         // 循环左移一位,实现流水灯效果
         // _crol_:循环左移函数(需包含 intrins.h)
         // _cror_:循环右移函数
         ucLed = _crol_(ucLed, 1);
         Delay(5);                // 延时约 5ms
         P1 = ucLed;              // 输出到 P1 口
     }
 }

示例4:变速流水灯(延时时间逐渐缩短)

 /* 头文件区域 */
 #include "REG52.H"
 #include "intrins.h"
 ​
 /* 延时函数(调整了内部参数,延时更短) */
 void Delay(unsigned char xms)    //@12.000MHz
 {
     unsigned char data i, j;
 ​
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);
     }
 }
 ​
 /* 变量声明 */
 unsigned char ucLed = 0xfe;
 unsigned int time = 1000;        // 初始延时时间较大
 ​
 /* Main 函数 */
 void main()
 {    
     while(1)
     {
         ucLed = _crol_(ucLed, 1);
         Delay(time--);           // 每次循环延时递减,实现加速效果
         P1 = ucLed;
     }
 }

说明

  • 以上示例基于 51 单片机,使用 12MHz 晶振。

  • 延时函数的时间为近似值,实际延时受编译器优化等因素影响。

  • 流水灯示例中,LED 通常低电平点亮(共阳接法),具体需根据硬件电路确定。

预备2 : 按键

这里核心逻辑是: 按键按下之后,电路导通,单片机一侧的接收通道是接收低电平。

同样的,先熟悉一下比赛环境

独立按键

 没在原理图上找到,先听课吧
 行 : P3_0, P3_1, P3_2, P3_3
 列 : P3_4, P3_5, P3_6, P3_7

示例1:独立按键控制LED

 /*头文件区域*/
 #include <REGX52.H>
 #include "intrins.h"
 ​
 ​
 /*延时函数*/
 void Delay(unsigned char xms)  //@12.000MHz
 {
     unsigned char data i, j;
     
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while(--j);
         }while(--i);
     }
 }
 ​
 /*变量申明*/
 unsigned char ucLed = 0xfe;
 unsigned int time = 1000;  
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
 ​
 /*按键读取函数*/
 unsigned char Key_Read()
 {
     unsigned char temp = 0;// 这是一个标志位
     if(P3_4 == 0) temp = 1;
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
         
     return temp;
 }
 ​
 /*main 函数*/
 int main()
 {
     while(1)
     {
         Key_Val = Key_Read(); //读取键码值
         Key_Down = Key_Val & (Key_Val ^ Key_Old); //检测下降沿
         Key_Up =  ~Key_Val & (Key_Val ^ Key_Old); //检测上升沿
         Key_Old = Key_Val; // 扫描辅助变量
         
         if(Key_Down == 1) // 按键1下降
             P1_0 = 0;     // P1_0 亮
         if(Key_Up == 2)   // 按键2上升
             P1_0 = 1;     // P1_0 灭
         if(Key_Old == 3)  // key_Old如果一直按着
             P1_1 = 0;     // P1_1 亮
         else
             P1_1 = 1;     // P1_1 灭
     }
 }

示例2: 使用按键控制LED流水灯状态

 /*头文件区域*/
 #include <REGX52.H>
 #include "intrins.h"
 ​
 ​
 /*延时函数*/
 void Delay(unsigned char xms)   //@12.000MHz
 {
     unsigned char data i, j;
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);  
     }
 }
 ​
 ​
 /*变量申明*/
 unsigned char ucLed = 0xfe; 
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
 bit System_Flag; // 申明标志位
 ​
 /*按键读取函数*/
 unsigned char Key_Read()
 {
     unsigned char temp = 0;// 这是一个标志位
     if(P3_4 == 0) temp = 1;
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
         
     return temp;
 }
 ​
 /*main 函数*/
 int main()
 {
     while(1)
     {
         Key_Val = Key_Read(); //读取键码值
         Key_Down = Key_Val & (Key_Val ^ Key_Old); //检测下降沿
         Key_Up = ~Key_Val & (Key_Val ^ Key_Old);  //检测上升沿
         Key_Old = Key_Val; // 扫描辅助变量
         
         if(System_Flag == 1)
         {
             ucLed = _crol_(ucLed, 1);
             P1 = ucLed;
             Delay(1000);
         }
         
 //      if(Key_Down == 1)
 //          System_Flag = 1;
 //      if(Key_Down == 2)
 //          System_Flag = 0;
         
         switch(Key_Down)
         {
             case 1:
                 System_Flag = 1;
                 break;
             case 2:
                 System_Flag = 0;
                 break;
         }
     }
 }

矩阵按键

![image-20260131123009189](https://gitee.com/alps-chenyu/typora/raw/master/image/image-20260131123009189.png)

矩阵按键的本质,就是选中行,再选择列

示例1:矩阵按键控制流水灯状态

 /*头文件区域*/
 #include <REGX52.H>
 #include "intrins.h"
 ​
 ​
 /*延时函数*/
 void Delay(unsigned char xms)   //@12.000MHz
 {
     unsigned char data i, j;
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);  
     }
 }
 ​
 ​
 /*变量申明*/
 unsigned char ucLed = 0xfe; 
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
 bit System_Flag; // 申明标志位
 ​
 /*按键读取函数*/
 unsigned char Key_Read()
 {
     unsigned char temp = 0;// 这是一个标志位
     P3_0 = 0; P3_1 = 1; P3_2 = 1; P3_3 = 1; // 先选中第一行
     if(P3_4 == 0) temp = 1; 
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     P3_0 = 1; P3_1 = 0; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 5;
     if(P3_5 == 0) temp = 6;
     if(P3_6 == 0) temp = 7;
     if(P3_7 == 0) temp = 8;
     P3_0 = 1; P3_1 = 1; P3_2 = 0; P3_3 = 1;
     if(P3_4 == 0) temp = 9;
     if(P3_5 == 0) temp = 10;
     if(P3_6 == 0) temp = 11;
     if(P3_7 == 0) temp = 12;
     P3_0 = 1; P3_1 = 1; P3_2 = 1; P3_3 = 0;
     if(P3_4 == 0) temp = 13;
     if(P3_5 == 0) temp = 14;
     if(P3_6 == 0) temp = 15;
     if(P3_7 == 0) temp = 16;    
     return temp;
 }
 ​
 /*main 函数*/
 int main()
 {
     while(1)
     {
         Key_Val = Key_Read(); //读取键码值
         Key_Down = Key_Val & (Key_Val ^ Key_Old); //检测下降沿
         Key_Up = ~Key_Val & (Key_Val ^ Key_Old);  //检测上升沿
         Key_Old = Key_Val; // 扫描辅助变量
         
         if(System_Flag == 1)
         {
             ucLed = _crol_(ucLed, 1);
             P1 = ucLed;
             Delay(1000);
         }
         
 //      if(Key_Down == 1)
 //          System_Flag = 1;
 //      if(Key_Down == 2)
 //          System_Flag = 0;
         switch(Key_Down)
         {
             case 1:
                 System_Flag = 1;
                 break;
             case 2:
                 System_Flag = 0;
                 break;
         }
     }
 }

示例2 : 矩阵键盘控制流水灯速度

 /*头文件区域*/
 #include <REGX52.H>
 #include "intrins.h"
 ​
 ​
 /*延时函数*/
 void Delay(unsigned char xms)   //@12.000MHz
 {
     unsigned char data i, j;
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);  
     }
 }
 ​
 ​
 /*变量申明*/
 unsigned char ucLed = 0xfe; 
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
 unsigned int Time = 500;
 bit System_Flag; // 申明标志位
 ​
 ​
 /*按键读取函数*/
 unsigned char Key_Read()
 {
     unsigned char temp = 0;// 这是一个标志位
     P3_0 = 0; P3_1 = 1; P3_2 = 1; P3_3 = 1; // 先选中第一行
     if(P3_4 == 0) temp = 1; 
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     P3_0 = 1; P3_1 = 0; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 5;
     if(P3_5 == 0) temp = 6;
     if(P3_6 == 0) temp = 7;
     if(P3_7 == 0) temp = 8;
     P3_0 = 1; P3_1 = 1; P3_2 = 0; P3_3 = 1;
     if(P3_4 == 0) temp = 9;
     if(P3_5 == 0) temp = 10;
     if(P3_6 == 0) temp = 11;
     if(P3_7 == 0) temp = 12;
     P3_0 = 1; P3_1 = 1; P3_2 = 1; P3_3 = 0;
     if(P3_4 == 0) temp = 13;
     if(P3_5 == 0) temp = 14;
     if(P3_6 == 0) temp = 15;
     if(P3_7 == 0) temp = 16;    
     return temp;
 }
 ​
 /*main 函数*/
 int main()
 {
     while(1)
     {
         Key_Val = Key_Read(); //读取键码值
         Key_Down = Key_Val & (Key_Val ^ Key_Old); //检测下降沿
         Key_Up = ~Key_Val & (Key_Val ^ Key_Old);  //检测上升沿
         Key_Old = Key_Val; // 扫描辅助变量
         
         if(System_Flag == 1)
         {
             ucLed = _crol_(ucLed, 1);
             P1 = ucLed;
             Delay(Time);
         }
         
 //      if(Key_Down == 1)
 //          System_Flag = 1;
 //      if(Key_Down == 2)
 //          System_Flag = 0;
         switch(Key_Down)
         {
             case 1:
                 System_Flag = 1;
                 break;
             case 2:
                 System_Flag = 0;
                 break;
             case 3:
                 Time += 100;
                 break;
             case 4: 
                 Time -= 100;
                 break;
         }
     }
 }

示例3 : 彩灯控制器

彩灯运行模式:

模式1:Led1 – Led2 – Led3 – Led4 – Led5 – Led6 – Led7 – Led8

模式2:Led8 – Led7 – Led6 – Led5 – Led4 – Led3 – Led2 – Led1

模式3:Led1+Led8 – Led2+Led7 - Led3+Led5 – Led4+Led6

模式4:Led4+Led6 – Led3+Led5 – Led2+Led7 – Led1+Led8

按键功能定义:

S1:彩灯系统启动按键

S2:彩灯系统暂停按键

S3:显示模式调整按键(运行模式+1)(若模式4+1后返回到模式1)

S4:显示模式调整按键(运行模式-1)(若模式1-1后返回到模式4)

初始化状态:

上电时,默认为模式1-启动状态,固定流转时间500ms/次

 /*彩灯控制系统*/
 // 注意,这份代码没有优化,也没用定时器,回头再来看看
 /*头文件*/
 #include <REGX52.H>
 #include "intrins.h"
 ​
 /*延时函数*/
 void Delay(unsigned char xms)   //@12.000MHz
 {
     unsigned char data i, j;
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);
     }
 }
 ​
 ​
 /*变量声明*/
 unsigned char ucLed = 0xfe;
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
 //unsigned char Led_State_1[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; 
 unsigned char Led_State_3[4] = {0x7e, 0xbd, 0xdb, 0xe7};
 unsigned char Led_Mode = 1;
 unsigned char i = 0, j = 0;
 bit Led_Flag;
     
 /*独立按键读取函数*/
 unsigned char Key_Read(void)
 {
     unsigned char temp = 0;
     if(P3_4 == 0) temp = 1;
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     
     return temp;
 }
                 
 /*main*/
 int main()
 {
     while(1)
     {
         // 按键消抖处理
         Key_Val = Key_Read();
         Key_Down = Key_Val & (Key_Val ^ Key_Old);
         Key_Up  = ~Key_Val & (Key_Val ^ Key_Old);
         Key_Old = Key_Val;
         
         if(Key_Down == 1) Led_Flag = 1;
         if(Key_Down == 2) Led_Flag = 0;
         
         
         if(Key_Down == 3)
         {
             P1 = 0x00;
             Led_Mode++;
             if(Led_Mode == 5)
             {
                 Led_Mode = 1;
             }
         
         }   
         if(Key_Down == 4)
         {
             P1 = 0x00;
             Led_Mode--;
             if(Led_Mode == 0)
             {
                 Led_Mode = 4;
             }
         } 
             
         if(Led_Flag == 1)
         {
             if(Led_Mode == 1)
             {
                 P1 = ucLed;
                 Delay(500);
                 ucLed = _crol_(ucLed, 1);
                 
             }
             
             if(Led_Mode == 2)
             {
                 P1 = ucLed;
                 Delay(500);
                 ucLed = _cror_(ucLed, 1);
             }
             
             if(Led_Mode == 3)
             {
                 if(++i == 4) i = 0;
                 P1 = Led_State_3[i];
                 Delay(500);
             }
             
             if(Led_Mode == 4)
             {   
                 if(++j == 4) j = 0;
                 P1 = Led_State_3[j];
                 Delay(500);
             }
         }
     }
 }
 ​
 // 功能实现了,但是功能的分数不是很高

预备3:数码管

基本原理

数码管分为两个控制部分:

  • 段选:控制数码管上具体哪一段LED亮灭,用于显示数字0-9

  • 位选:控制6个数码管中具体哪一个被选中点亮

信号电平定义

  • 段码:本单片机采用高电平有效,给1亮,给0灭

  • 位码:本单片机采用低电平有效,给0选中,给1不选

控制引脚分配

  • P2_6:控制段选信号

  • P2_7:控制位选信号

静态数码管显示

变量声明

 unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
 unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};

数码管显示函数

 void Seg_Disp(unsigned char wela, unsigned char dula)
 {
     // #1. 消隐操作(防止重影)
     P0 = 0x00;
     P2_6 = 1; // 开门(锁存器使能)
     P2_6 = 0; // 关门(锁存器锁存)
     
     // #2. 位选(选择要显示的数码管)
     P0 = Seg_Wela[wela];
     P2_7 = 1; // 开门
     P2_7 = 0; // 关门
     
     // #3. 段选(设置显示的数字)
     P0 = Seg_Dula[dula];
     P2_6 = 1;
     P2_6 = 0;
 }

静态数码管调用方法

 Seg_Disp(0, 0);  // 在第一个数码管上显示数字0

动态数码管显示

动态数码管显示需要使用定时器中断来实现扫描,避免使用延时函数阻塞程序运行。

定时器初始化

使用ISP工具初始化定时器设置

定时器初始化函数

 void Timer0_Init(void)        // 1毫秒@12.000MHz
 {
 //    AUXR &= 0x7F;            // 定时器时钟12T模式
     TMOD &= 0xF0;            // 设置定时器模式
     TL0 = 0x18;              // 设置定时初始值
     TH0 = 0xFC;              // 设置定时初始值
     TF0 = 0;                 // 清除TF0标志
     TR0 = 1;                 // 定时器0开始计时
     ET0 = 1;                 // 允许定时器0中断
     EA = 1;                  // 开启总中断
 }

定时器中断服务函数

 void Timer0Server() interrupt 1  // 中断序号为1
 {
     TMOD &= 0xF0;            // 设置定时器模式
     TL0 = 0x18;              // 重新设置定时初始值
 }

动态数码管显示模板

 /* 头文件区域 */
 #include <REGX52.H>
 #include "intrins.h"
 ​
 /* 延时函数 */
 void Delay(unsigned char xms)    // @12.000MHz
 {
     unsigned char data i, j;
     while(xms--)
     {
         i = 2;
         j = 239;
         do
         {
             while (--j);
         } while (--i);    
     }
 }
 ​
 /* 变量声明 */
 unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
 unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
 unsigned char Seg_Pos;                           // 扫描位置变量
 unsigned char Seg_Buf[] = {1,2,3,10,10,10};      // 显示缓冲区,默认显示{1,2,3}
 unsigned char ucLed = 0xfe;                      // LED初始状态
 unsigned char Key_Val, Key_Down, Key_Up, Key_Old; // 按键相关变量
 unsigned int Time = 500;                         // 时间变量
 bit System_Flag;                                 // 系统标志位
 ​
 /* 矩阵按键读取函数 */
 unsigned char Key_Read()
 {
     unsigned char temp = 0;                      // 临时变量存储按键值
     
     // 扫描第一行
     P3_0 = 0; P3_1 = 1; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 1;    
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     
     // 扫描第二行
     P3_0 = 1; P3_1 = 0; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 5;
     if(P3_5 == 0) temp = 6;
     if(P3_6 == 0) temp = 7;
     if(P3_7 == 0) temp = 8;
     
     // 扫描第三行
     P3_0 = 1; P3_1 = 1; P3_2 = 0; P3_3 = 1;
     if(P3_4 == 0) temp = 9;
     if(P3_5 == 0) temp = 10;
     if(P3_6 == 0) temp = 11;
     if(P3_7 == 0) temp = 12;
     
     // 扫描第四行
     P3_0 = 1; P3_1 = 1; P3_2 = 1; P3_3 = 0;
     if(P3_4 == 0) temp = 13;
     if(P3_5 == 0) temp = 14;
     if(P3_6 == 0) temp = 15;
     if(P3_7 == 0) temp = 16;    
     
     return temp;
 }
 ​
 /* 数码管显示函数 */
 void Seg_Disp(unsigned char wela, unsigned char dula)
 {
     // #1. 消隐操作(防止重影)
     P0 = 0x00;
     P2_6 = 1; // 开门
     P2_6 = 0; // 关门
     
     // #2. 位选(选择数码管)
     P0 = Seg_Wela[wela];
     P2_7 = 1; // 开门
     P2_7 = 0; // 关门
     
     // #3. 段选(显示数字)
     P0 = Seg_Dula[dula];
     P2_6 = 1;
     P2_7 = 0;
 }
 ​
 /* 定时器初始化函数 */
 void Timer0_Init(void)        // 1毫秒@12.000MHz
 {
 //    AUXR &= 0x7F;            // 定时器时钟12T模式
     TMOD &= 0xF0;            // 设置定时器模式
     TL0 = 0x18;              // 设置定时初始值
     TH0 = 0xFC;              // 设置定时初始值
     TF0 = 0;                 // 清除TF0标志
     TR0 = 1;                 // 定时器0开始计时
     ET0 = 1;                 // 允许定时器0中断
     EA = 1;                  // 开启总中断
 }
 ​
 /* 定时器0中断服务函数 - 每1毫秒执行一次 */
 void Timer0Server() interrupt 1
 {
     TMOD &= 0xF0;            // 设置定时器模式
     TL0 = 0x18;              // 重新设置定时初始值
     
     // 扫描6个数码管
     if(++Seg_Pos == 6) Seg_Pos = 0;
     Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos]);
 }
 ​
 /* 主函数 */
 int main()
 {
     Timer0_Init();           // 初始化定时器
     
     while(1)
     {
         // 按键检测与处理
         Key_Val = Key_Read();                    // 读取键码值
         Key_Down = Key_Val & (Key_Val ^ Key_Old); // 检测下降沿(按键按下)
         Key_Up = ~Key_Val & (Key_Val ^ Key_Old);  // 检测上升沿(按键释放)
         Key_Old = Key_Val;                       // 保存当前按键状态
         
         // 按键功能分配
         switch(Key_Down)
         {
             case 1: 
                 System_Flag = 1;  // 启动系统
                 break;
             case 2:
                 System_Flag = 0;  // 暂停系统
                 break;
             case 3:
                 Time += 100;      // 时间增加100
                 break;
             case 4:
                 Time -= 100;      // 时间减少100
                 break;
         }
         
         // 更新数码管显示内容
         Seg_Buf[0] = Time / 100 % 10;  // 显示百位
         Seg_Buf[1] = Time / 10 % 10;   // 显示十位
         Seg_Buf[2] = Time / 1 % 10;    // 显示个位
     }
 }

说明:此模板实现了基于定时器中断的动态数码管扫描显示,配合矩阵按键实现系统控制功能。数码管显示缓冲区Seg_Buf存储要显示的数字,定时器中断服务函数Timer0Server负责循环扫描更新显示。