单片机——实现交通信号灯管理

[复制链接]
发表于 2025-5-24 08:43:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
随便写写,汇总一下,就一个单片机,没有模仿软件,什么都没有~
点阵、数码管、led同时点亮

  1. #include <reg52.h>
  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. // 交通灯控制引脚定义
  8. sbit A_Red    = P0^0;
  9. sbit A_Yellow = P0^1;
  10. sbit A_Green  = P0^2;
  11. sbit B_Red    = P0^3;
  12. sbit B_Yellow = P0^4;
  13. sbit B_Green  = P0^5;
  14. unsigned char code LedChar[] = {  // 数码管显示字符转换表
  15.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  16.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  17. };
  18. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  19. unsigned char flag1s = 0;          // 1秒定时标志
  20. // 交通灯状态变量
  21. unsigned char current_state = 0;   // 0:A绿灯 1:A黄灯 2:B绿灯 3:B黄灯
  22. unsigned char count_down = 27;     // 当前倒计时
  23. bit yellow_blink = 0;              // 黄灯闪烁标志
  24. unsigned int timer_count = 0;      // 定时器计数
  25. // LED流水灯变量
  26. static unsigned char j = 0;
  27. static unsigned int shift1 = 0x01;
  28. static unsigned int shift2 = 0x80;
  29. static unsigned char dir1 = 0;
  30. void main()
  31. {
  32.     EA = 1;                     // 开启总中断
  33.     TMOD = 0x11;                // 使用定时器0和定时器1
  34.     // 定时器0初始化(2ms,用于1秒定时)
  35.     TH0 = 0xFC;
  36.     TL0 = 0x67;
  37.     ET0 = 1;
  38.     TR0 = 1;
  39.     // 定时器1初始化(1ms,用于数码管扫描)
  40.     TH1 = 0xFC;
  41.     TL1 = 0x67;
  42.     ET1 = 1;
  43.     TR1 = 1;
  44.     // 初始状态:A绿灯,B红灯
  45.     A_Green = 0;
  46.     B_Red = 0;
  47.     A_Red = B_Green = B_Yellow = A_Yellow = 1;
  48.     while (1)
  49.     {
  50.         if (flag1s == 1)        // 每秒触发一次
  51.         {
  52.             flag1s = 0;
  53.             
  54.             // 交通灯状态机处理
  55.             if(count_down > 0) count_down--;
  56.             
  57.             if(count_down == 0) {
  58.                 switch(current_state) {
  59.                     case 0: // A绿灯结束
  60.                         current_state = 1;
  61.                         count_down = 3;
  62.                         A_Green = 1;
  63.                         A_Yellow = 0;
  64.                         break;
  65.                         
  66.                     case 1: // A黄灯结束
  67.                         current_state = 2;
  68.                         count_down = 17;
  69.                         A_Yellow = 1;
  70.                         B_Red = 1;
  71.                         B_Green = 0;
  72.                         break;
  73.                         
  74.                     case 2: // B绿灯结束
  75.                         current_state = 3;
  76.                         count_down = 3;
  77.                         B_Green = 1;
  78.                         B_Yellow = 0;
  79.                         break;
  80.                         
  81.                     case 3: // B黄灯结束
  82.                         current_state = 0;
  83.                         count_down = 27;
  84.                         B_Yellow = 1;
  85.                         A_Red = 1;
  86.                         A_Green = 0;
  87.                         break;
  88.                 }
  89.             }
  90.             // 更新数码管显示(显示倒计时)
  91.             LedBuff[0] = LedChar[count_down % 10];  // 个位
  92.             LedBuff[1] = LedChar[count_down / 10];   // 十位
  93.             // 其余位保持熄灭
  94.             LedBuff[2] = LedBuff[3] = LedBuff[4] = LedBuff[5] = 0xFF;
  95.         }
  96.     }
  97. }
  98. // 定时器1中断服务函数(1ms,用于数码管扫描和LED流水灯)
  99. void Timer1_ISR() interrupt 3
  100. {
  101.     static unsigned char index = 0;
  102.    
  103.     TH1 = 0xFC;
  104.     TL1 = 0x67;
  105.    
  106.     // 黄灯闪烁处理(500ms间隔)
  107.     if(++timer_count % 250 == 0 &&
  108.       (current_state == 1 || current_state == 3)) {
  109.         yellow_blink = ~yellow_blink;
  110.         if(current_state == 1) A_Yellow = yellow_blink;
  111.         else B_Yellow = yellow_blink;
  112.     }
  113.     // 数码管动态扫描
  114.     P0 = 0xFF;                  // 消隐
  115.     ENLED = 0;
  116.     ADDR3 = 1;                  // 选择数码管
  117.    
  118.     switch(index) {
  119.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; P0=LedBuff[0]; break;
  120.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; P0=LedBuff[1]; break;
  121.         default: P0 = 0xFF;     // 其余位不显示
  122.     }
  123.    
  124.     index = (index >= 1) ? 0 : index+1;
  125.     // LED流水灯控制(复用case 6)
  126.     if(index == 0) {  // 每轮扫描结束后处理LED
  127.         ADDR3 = 1;    // 选择LED控制地址
  128.         ADDR2 = 1;
  129.         ADDR1 = 1;
  130.         ADDR0 = 0;
  131.         
  132.         j++;
  133.         if (j >= 200) {  // 每200ms改变一次LED位置
  134.             j = 0;
  135.             if (dir1 == 0) {  // 从左向右移动
  136.                 shift1 <<= 1;
  137.                 shift2 >>= 1;
  138.                 if (shift1 == 0x80 && shift2 == 0x01)
  139.                     dir1 = 1;  // 改变方向
  140.             } else {  // 从右向左移动
  141.                 shift1 >>= 1;
  142.                 shift2 <<= 1;
  143.                 if (shift1 == 0x01 && shift2 == 0x80)
  144.                     dir1 = 0;  // 改变方向
  145.             }
  146.         }
  147.         P0 = ~(shift1 | shift2);  // 输出LED状态
  148.     }
  149. }
  150. // 定时器0中断服务函数(2ms,用于1秒定时)
  151. void Timer0_ISR() interrupt 1
  152. {
  153.     static unsigned int sec_count = 0;
  154.    
  155.     TH0 = 0xFC;
  156.     TL0 = 0x67;
  157.    
  158.     if(++sec_count >= 500) {  // 500 * 2ms = 1秒
  159.         sec_count = 0;
  160.         flag1s = 1;
  161.     }
  162. }
复制代码
红绿灯熄灭 

实现30秒绿灯倒计时熄灭,20秒倒计时红灯熄灭 

  1. #include <reg52.h>
  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. // 交通灯控制引脚定义
  8. sbit A_Red    = P0^0;
  9. sbit A_Yellow = P0^1;
  10. sbit A_Green  = P0^2;
  11. sbit B_Red    = P0^3;
  12. sbit B_Yellow = P0^4;
  13. sbit B_Green  = P0^5;
  14. unsigned char code LedChar[] = {
  15.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  16.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  17. };
  18. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  19. volatile unsigned char flag1s = 0;
  20. volatile unsigned int timer_count = 0;
  21. unsigned char current_state = 0;  // 0:A绿灯 1:A黄灯 2:B绿灯 3:B黄灯
  22. unsigned char count_down = 27;    // 当前倒计时
  23. bit yellow_blink = 0;              // 黄灯闪烁标志
  24. void main() {
  25.     EA = 1;
  26.     TMOD = 0x11;
  27.    
  28.     // 定时器0初始化(2ms)
  29.     TH0 = 0xFC;
  30.     TL0 = 0x67;
  31.     ET0 = 1;
  32.     TR0 = 1;
  33.     // 定时器1初始化(1ms)
  34.     TH1 = 0xFC;
  35.     TL1 = 0x67;
  36.     ET1 = 1;
  37.     TR1 = 1;
  38.     // 初始状态:A绿灯,B红灯
  39.     A_Green = 0;
  40.     B_Red = 0;
  41.     A_Red = B_Green = B_Yellow = A_Yellow = 1;
  42.     while(1) {
  43.         if(flag1s) {
  44.             flag1s = 0;
  45.             
  46.             // 状态机处理
  47.             if(count_down > 0) count_down--;
  48.             
  49.             if(count_down == 0) {
  50.                 switch(current_state) {
  51.                     case 0: // A绿灯结束
  52.                         current_state = 1;
  53.                         count_down = 3;
  54.                         A_Green = 1;
  55.                         A_Yellow = 0;
  56.                         break;
  57.                         
  58.                     case 1: // A黄灯结束
  59.                         current_state = 2;
  60.                         count_down = 17;
  61.                         A_Yellow = 1;
  62.                         B_Red = 1;
  63.                         B_Green = 0;
  64.                         break;
  65.                         
  66.                     case 2: // B绿灯结束
  67.                         current_state = 3;
  68.                         count_down = 3;
  69.                         B_Green = 1;
  70.                         B_Yellow = 0;
  71.                         break;
  72.                         
  73.                     case 3: // B黄灯结束
  74.                         current_state = 0;
  75.                         count_down = 27;
  76.                         B_Yellow = 1;
  77.                         A_Red = 1;
  78.                         A_Green = 0;
  79.                         break;
  80.                 }
  81.             }
  82.             // 更新数码管显示
  83.             LedBuff[0] = LedChar[count_down % 10];  // 个位
  84.             LedBuff[1] = LedChar[count_down / 10];   // 十位
  85.         }
  86.     }
  87. }
  88. // 定时器1中断(数码管扫描)
  89. void Timer1_ISR() interrupt 3 {
  90.     static unsigned char index = 0;
  91.    
  92.     TH1 = 0xFC;
  93.     TL1 = 0x67;
  94.    
  95.     // 黄灯闪烁处理(500ms间隔)
  96.     if(++timer_count % 250 == 0 &&
  97.       (current_state == 1 || current_state == 3)) {
  98.         yellow_blink = ~yellow_blink;
  99.         if(current_state == 1) A_Yellow = yellow_blink;
  100.         else B_Yellow = yellow_blink;
  101.     }
  102.     // 数码管动态扫描
  103.     P0 = 0xFF;
  104.     ENLED = 0;
  105.     ADDR3 = 1;
  106.    
  107.     switch(index) {
  108.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; P0=LedBuff[0]; break;
  109.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; P0=LedBuff[1]; break;
  110.         default: P0 = 0xFF;
  111.     }
  112.    
  113.     index = (index >= 1) ? 0 : index+1;
  114. }
  115. // 定时器0中断(1秒定时)
  116. void Timer0_ISR() interrupt 1 {
  117.     static unsigned int sec_count = 0;
  118.    
  119.     TH0 = 0xFC;
  120.     TL0 = 0x67;
  121.    
  122.     if(++sec_count >= 500) { // 500 * 2ms=1秒
  123.         sec_count = 0;
  124.         flag1s = 1;
  125.     }
  126. }
复制代码
红绿灯跳转

当绿灯30秒剩余三秒时跳转至黄灯,当黄灯3秒后 跳转红灯,红灯20秒后继承跳转

  1. #include <reg52.h>
  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. unsigned char code LedChar[] = {  // 数码管显示字符转换表
  8.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  9.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  10. };
  11. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  12. unsigned char flag1s = 0;
  13. unsigned char countDownPhase = 0;  // 倒计时阶段:0=30->0, 1=20->0
  14. unsigned long sec = 30;  // 初始值设为30
  15. bit countDownFinished = 0;  // 倒计时结束标志
  16. void main()
  17. {
  18.     char j;
  19.     unsigned char buf[6];
  20.     EA = 1;                     // 开启总中断
  21.     TMOD = 0x01;                // 只使用定时器0
  22.     // 定时器0初始化(T0)
  23.     TH0 = 0xFC;                 // 定时1ms
  24.     TL0 = 0x67;
  25.     ET0 = 1;                    // 使能定时器0中断
  26.     TR0 = 1;                    // 启动定时器0
  27.     // 初始化显示30
  28.     buf[0] = sec%10;            // 个位
  29.     buf[1] = sec/10%10;         // 十位
  30.     buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0; // 高位补0
  31.    
  32.     // 高位消零处理
  33.     for (j=5; j>=1; j--)
  34.     {
  35.         if (buf[j] == 0)
  36.             LedBuff[j] = 0xFF;  // 不显示前导零
  37.         else
  38.             break;
  39.     }
  40.     // 显示有效数字
  41.     for (; j>=0; j--)
  42.     {
  43.         LedBuff[j] = LedChar[buf[j]];
  44.     }
  45.     while (1)
  46.     {
  47.         if (flag1s == 1)        // 每秒触发一次
  48.         {
  49.             flag1s = 0;
  50.             
  51.             if (!countDownFinished)  // 如果倒计时未结束
  52.             {
  53.                 if (sec > 0)
  54.                 {
  55.                     sec--;          // 秒计数器减1
  56.                     
  57.                     // 分解秒数为单个数字
  58.                     buf[0] = sec%10;    // 个位
  59.                     buf[1] = sec/10%10; // 十位
  60.                     buf[2] = sec/100%10;
  61.                     buf[3] = sec/1000%10;
  62.                     buf[4] = sec/10000%10;
  63.                     buf[5] = sec/100000%10;
  64.                     // 高位消零处理
  65.                     for (j=5; j>=1; j--)
  66.                     {
  67.                         if (buf[j] == 0)
  68.                             LedBuff[j] = 0xFF;  // 不显示前导零
  69.                         else
  70.                             break;
  71.                     }
  72.                     // 显示有效数字
  73.                     for (; j>=0; j--)
  74.                     {
  75.                         LedBuff[j] = LedChar[buf[j]];
  76.                     }
  77.                 }
  78.                 else
  79.                 {
  80.                     countDownFinished = 1;  // 倒计时结束
  81.                     
  82.                     // 切换到下一阶段
  83.                     countDownPhase++;
  84.                     if (countDownPhase == 1) {
  85.                         // 进入20->0阶段
  86.                         sec = 20;
  87.                         countDownFinished = 0;  // 重置结束标志
  88.                         
  89.                         // 更新显示
  90.                         buf[0] = sec%10;
  91.                         buf[1] = sec/10%10;
  92.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  93.                         
  94.                         for (j=5; j>=1; j--)
  95.                         {
  96.                             if (buf[j] == 0)
  97.                                 LedBuff[j] = 0xFF;
  98.                             else
  99.                                 break;
  100.                         }
  101.                         for (; j>=0; j--)
  102.                         {
  103.                             LedBuff[j] = LedChar[buf[j]];
  104.                         }
  105.                     }
  106.                     else if (countDownPhase >= 2) {
  107.                         // 所有阶段完成,重置到第一阶段
  108.                         countDownPhase = 0;
  109.                         sec = 30;
  110.                         countDownFinished = 0;
  111.                         
  112.                         // 更新显示
  113.                         buf[0] = sec%10;
  114.                         buf[1] = sec/10%10;
  115.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  116.                         
  117.                         for (j=5; j>=1; j--)
  118.                         {
  119.                             if (buf[j] == 0)
  120.                                 LedBuff[j] = 0xFF;
  121.                             else
  122.                                 break;
  123.                         }
  124.                         for (; j>=0; j--)
  125.                         {
  126.                             LedBuff[j] = LedChar[buf[j]];
  127.                         }
  128.                     }
  129.                 }
  130.             }
  131.         }
  132.     }
  133. }
  134. // 定时器0中断服务函数(修改LED控制部分)
  135. void Timer0_ISR() interrupt 1
  136. {
  137.     static unsigned char j = 0;
  138.     static unsigned char i = 0;
  139.     static unsigned int cnt = 0;
  140.     static unsigned int shift1 = 0x01;
  141.     static unsigned int shift2 = 0x80;
  142.     static unsigned char dir1 = 0;
  143.     TH0 = 0xFC;                 // 重新加载初值
  144.     TL0 = 0x67;
  145.    
  146.     P0 = 0xFF;                  // 显示消隐
  147.     ENLED = 0;                  // 使能显示
  148.     ADDR3 = 1;                  // 选择数码管和LED
  149.     // 数码管动态扫描(保持不变)
  150.     switch (i)
  151.     {
  152.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
  153.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
  154.         case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
  155.         case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
  156.         case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
  157.         case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
  158.         case 6: // LED控制(修改部分)
  159.             ADDR2=1; ADDR1=1; ADDR0=0;
  160.             
  161.             // 根据倒计时阶段控制LED
  162.             if (countDownPhase == 0) {
  163.                 // 30秒倒计时阶段,点亮第一个LED(P0.0)
  164.                 P0 = 0xFE;  // 二进制 1111 1110,仅P0.0为低电平
  165.             } else {
  166.                 // 20秒倒计时阶段,熄灭所有LED
  167.                 P0 = 0xFF;  // 二进制 1111 1111,所有LED熄灭
  168.             }
  169.             
  170.             i = 0;
  171.             break;
  172.         default: break;
  173.     }
  174.     // 1秒定时处理(保持不变)
  175.     cnt++;
  176.     if (cnt >= 1000)            // 1000ms = 1s
  177.     {
  178.         cnt = 0;
  179.         flag1s = 1;             // 设置1秒标志
  180.     }
  181. }
复制代码
增加B车道 

30秒阶段LED 逻辑:

30 秒→4 秒:点亮 LED2和 LED7
3 秒→0 秒:点亮 LED3和 LED


20 秒阶段 LED 逻辑:
20 秒→4 秒:点亮 LED4和 LED5
3 秒→0 秒:点亮 LED4和 LED6


  1. #include <reg52.h>
  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. unsigned char code LedChar[] = {  // 数码管显示字符转换表
  8.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  9.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  10. };
  11. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  12. unsigned char flag1s = 0;
  13. unsigned char countDownPhase = 0;  // 倒计时阶段:0=30秒阶段, 1=20秒阶段
  14. unsigned long sec = 30;  // 初始值设为30
  15. bit countDownFinished = 0;  // 倒计时结束标志
  16. void main()
  17. {
  18.     char j;
  19.     unsigned char buf[6];
  20.     EA = 1;                     // 开启总中断
  21.     TMOD = 0x01;                // 只使用定时器0
  22.     // 定时器0初始化(T0)
  23.     TH0 = 0xFC;                 // 定时1ms
  24.     TL0 = 0x67;
  25.     ET0 = 1;                    // 使能定时器0中断
  26.     TR0 = 1;                    // 启动定时器0
  27.     // 初始化显示30
  28.     buf[0] = sec%10;            // 个位
  29.     buf[1] = sec/10%10;         // 十位
  30.     buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0; // 高位补0
  31.    
  32.     // 高位消零处理
  33.     for (j=5; j>=1; j--)
  34.     {
  35.         if (buf[j] == 0)
  36.             LedBuff[j] = 0xFF;  // 不显示前导零
  37.         else
  38.             break;
  39.     }
  40.     // 显示有效数字
  41.     for (; j>=0; j--)
  42.     {
  43.         LedBuff[j] = LedChar[buf[j]];
  44.     }
  45.     while (1)
  46.     {
  47.         if (flag1s == 1)        // 每秒触发一次
  48.         {
  49.             flag1s = 0;
  50.             
  51.             if (!countDownFinished)  // 如果倒计时未结束
  52.             {
  53.                 if (sec > 0)
  54.                 {
  55.                     sec--;          // 秒计数器减1
  56.                     
  57.                     // 分解秒数为单个数字
  58.                     buf[0] = sec%10;    // 个位
  59.                     buf[1] = sec/10%10; // 十位
  60.                     buf[2] = sec/100%10;
  61.                     buf[3] = sec/1000%10;
  62.                     buf[4] = sec/10000%10;
  63.                     buf[5] = sec/100000%10;
  64.                     // 高位消零处理
  65.                     for (j=5; j>=1; j--)
  66.                     {
  67.                         if (buf[j] == 0)
  68.                             LedBuff[j] = 0xFF;  // 不显示前导零
  69.                         else
  70.                             break;
  71.                     }
  72.                     // 显示有效数字
  73.                     for (; j>=0; j--)
  74.                     {
  75.                         LedBuff[j] = LedChar[buf[j]];
  76.                     }
  77.                 }
  78.                 else
  79.                 {
  80.                     countDownFinished = 1;  // 倒计时结束
  81.                     
  82.                     // 切换到下一阶段
  83.                     countDownPhase++;
  84.                     if (countDownPhase == 1) {
  85.                         // 进入20->0阶段
  86.                         sec = 20;
  87.                         countDownFinished = 0;  // 重置结束标志
  88.                         
  89.                         // 更新显示
  90.                         buf[0] = sec%10;
  91.                         buf[1] = sec/10%10;
  92.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  93.                         
  94.                         for (j=5; j>=1; j--)
  95.                         {
  96.                             if (buf[j] == 0)
  97.                                 LedBuff[j] = 0xFF;
  98.                             else
  99.                                 break;
  100.                         }
  101.                         for (; j>=0; j--)
  102.                         {
  103.                             LedBuff[j] = LedChar[buf[j]];
  104.                         }
  105.                     }
  106.                     else if (countDownPhase >= 2) {
  107.                         // 所有阶段完成,重置到第一阶段
  108.                         countDownPhase = 0;
  109.                         sec = 30;
  110.                         countDownFinished = 0;
  111.                         
  112.                         // 更新显示
  113.                         buf[0] = sec%10;
  114.                         buf[1] = sec/10%10;
  115.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  116.                         
  117.                         for (j=5; j>=1; j--)
  118.                         {
  119.                             if (buf[j] == 0)
  120.                                 LedBuff[j] = 0xFF;
  121.                             else
  122.                                 break;
  123.                         }
  124.                         for (; j>=0; j--)
  125.                         {
  126.                             LedBuff[j] = LedChar[buf[j]];
  127.                         }
  128.                     }
  129.                 }
  130.             }
  131.         }
  132.     }
  133. }
  134. // 定时器0中断服务函数(修改LED控制部分)
  135. void Timer0_ISR() interrupt 1
  136. {
  137.     static unsigned char j = 0;
  138.     static unsigned char i = 0;
  139.     static unsigned int cnt = 0;
  140.     TH0 = 0xFC;                 // 重新加载初值
  141.     TL0 = 0x67;
  142.    
  143.     P0 = 0xFF;                  // 显示消隐
  144.     ENLED = 0;                  // 使能显示
  145.     ADDR3 = 1;                  // 选择数码管和LED
  146.     // 数码管动态扫描
  147.     switch (i)
  148.     {
  149.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
  150.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
  151.         case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
  152.         case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
  153.         case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
  154.         case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
  155.         case 6: // LED控制部分
  156.             ADDR2=1; ADDR1=1; ADDR0=0;
  157.             
  158.             // 根据倒计时阶段和剩余秒数控制LED
  159.             if (countDownPhase == 0) {
  160.                 // 30秒倒计时阶段
  161.                 if (sec > 3) {
  162.                     // 前27秒:LED1(P0.0)和LED6(P0.5)亮
  163.                     P0 = 0xDE;  // 二进制 1101 1110 (P0.0和P0.5低电平)
  164.                 } else if (sec > 0) {
  165.                     // 后3秒:LED2(P0.1)和LED6(P0.5)亮
  166.                     P0 = 0xDD;  // 二进制 1101 1101 (P0.1和P0.5低电平)
  167.                 } else {
  168.                     // 倒计时结束:熄灭所有LED
  169.                     P0 = 0xFF;
  170.                 }
  171.             } else if (countDownPhase == 1) {
  172.                 // 20秒倒计时阶段
  173.                 if (sec > 3) {
  174.                     // 前17秒:LED3(P0.2)和LED4(P0.3)亮
  175.                     P0 = 0xF3;  // 二进制 1111 0011 (P0.2和P0.3低电平)
  176.                 } else if (sec > 0) {
  177.                     // 后3秒:LED3(P0.2)和LED5(P0.4)亮
  178.                     P0 = 0xEB;  // 二进制 1110 1011 (P0.2和P0.4低电平)
  179.                 } else {
  180.                     // 倒计时结束:熄灭所有LED
  181.                     P0 = 0xFF;
  182.                 }
  183.             } else {
  184.                 // 其他阶段:熄灭所有LED
  185.                 P0 = 0xFF;
  186.             }
  187.             
  188.             i = 0;
  189.             break;
  190.         default: break;
  191.     }
  192.     // 1秒定时处理
  193.     cnt++;
  194.     if (cnt >= 1000)            // 1000ms = 1s
  195.     {
  196.         cnt = 0;
  197.         flag1s = 1;             // 设置1秒标志
  198.     }
  199. }
复制代码
按键控制led灯的10秒定时亮灭

  1. #include <reg52.h>
  2. // 引脚定义(补充完整矩阵按键输出和输入引脚)
  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;
  7. sbit ENLED = P1^4;
  8. sbit KEY_OUT_1 = P2^3;  // 矩阵按键输出引脚(完整定义)
  9. sbit KEY_OUT_2 = P2^2;
  10. sbit KEY_OUT_3 = P1^2;  // 假设KEY_OUT_3连接到P1^2(避免与ADDR2冲突)
  11. sbit KEY_OUT_4 = P1^3;  // 假设KEY_OUT_4连接到P1^3(避免与ADDR3冲突)
  12. sbit KEY_IN_1  = P2^4;  // 矩阵按键输入引脚(完整定义)
  13. sbit KEY_IN_2  = P2^5;
  14. sbit KEY_IN_3  = P2^6;
  15. sbit KEY_IN_4  = P2^7;
  16. sbit LED1 = P0^0;      // K2控制的LED(原LED)
  17. sbit LED4 = P0^3;      // K1控制的LED4(假设连接到P0^3)
  18. // 状态变量
  19. unsigned char KeySta[4][4] = {  // 按键状态数组(使用[0][0]对应K1,[0][1]对应K2)
  20.     {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
  21. };
  22. unsigned int Timer10s_LED1 = 0;  // LED1的10秒计时计数器
  23. unsigned int Timer10s_LED4 = 0;  // LED4的10秒计时计数器
  24. bit Led1Active = 0;             // LED1激活标志
  25. bit Led4Active = 0;             // LED4激活标志
  26. // 定时器0参数(1ms定时)
  27. #define TIMER0_RELOAD_H 0xFC  // 1ms初值高位
  28. #define TIMER0_RELOAD_L 0x67  // 1ms初值低位
  29. void main()
  30. {
  31.     // 硬件初始化
  32.     ENLED = 0;                // 使能LED控制
  33.     ADDR3 = 1;                // 选择LED所在电路(共阳连接)
  34.     ADDR2 = 1;
  35.     ADDR1 = 1;
  36.     ADDR0 = 0;
  37.     LED1 = 1;                 // 初始熄灭LED1
  38.     LED4 = 1;                 // 初始熄灭LED4
  39.     // 定时器0初始化
  40.     TMOD = 0x01;              // 模式1(16位定时器)
  41.     TH0 = TIMER0_RELOAD_H;
  42.     TL0 = TIMER0_RELOAD_L;
  43.     ET0 = 1;                  // 使能定时器中断
  44.     EA = 1;                   // 使能总中断
  45.     TR0 = 1;                  // 启动定时器
  46.     // 矩阵按键初始化
  47.     KEY_OUT_1 = 1;            // 初始拉高所有行
  48.     KEY_OUT_2 = 1;
  49.     KEY_OUT_3 = 1;
  50.     KEY_OUT_4 = 1;
  51.     while (1)
  52.     {
  53.         // 检测K1按键状态(矩阵坐标[0][0],第1行第1列)
  54.         if (KeySta[0][0] == 0 && !Led4Active)  // K1按下且LED4未激活
  55.         {
  56.             LED4 = 0;                 // 点亮LED4
  57.             Led4Active = 1;           // 标记LED4激活
  58.             Timer10s_LED4 = 0;        // 重置LED4计时器
  59.             while (KeySta[0][0] == 0);  // 等待K1释放
  60.         }
  61.         // 检测K2按键状态(矩阵坐标[0][1],第1行第2列)
  62.         if (KeySta[0][1] == 0 && !Led1Active)  // K2按下且LED1未激活
  63.         {
  64.             LED1 = 0;                 // 点亮LED1
  65.             Led1Active = 1;           // 标记LED1激活
  66.             Timer10s_LED1 = 0;        // 重置LED1计时器
  67.             while (KeySta[0][1] == 0);  // 等待K2释放
  68.         }
  69.     }
  70. }
  71. /* 定时器0中断服务函数(1ms执行一次) */
  72. void InterruptTimer0() interrupt 1
  73. {
  74.     static unsigned char keyout = 0;       // 矩阵行扫描索引
  75.     static unsigned char keybuf[4][4] = {  // 按键消抖缓冲区
  76.         {0xFF, 0xFF, 0xFF, 0xFF},
  77.         {0xFF, 0xFF, 0xFF, 0xFF},
  78.         {0xFF, 0xFF, 0xFF, 0xFF},
  79.         {0xFF, 0xFF, 0xFF, 0xFF}
  80.     };
  81.     // 重新加载定时器初值
  82.     TH0 = TIMER0_RELOAD_H;
  83.     TL0 = TIMER0_RELOAD_L;
  84.     // 扫描第1行(KEY_OUT_1)
  85.     KEY_OUT_1 = 0;          // 拉低第1行
  86.     KEY_OUT_2 = 1;          // 拉高其他行
  87.     KEY_OUT_3 = 1;
  88.     KEY_OUT_4 = 1;
  89.     // 读取K1和K2的按键值(第1行第1、2列)
  90.     keybuf[0][0] = (keybuf[0][0] << 1) | KEY_IN_1;  // K1(第1列)
  91.     keybuf[0][1] = (keybuf[0][1] << 1) | KEY_IN_2;  // K2(第2列)
  92.     // K1消抖逻辑
  93.     if ((keybuf[0][0] & 0x0F) == 0x00)  
  94.     {
  95.         KeySta[0][0] = 0;  // 标记K1按下
  96.     }
  97.     else if ((keybuf[0][0] & 0x0F) == 0x0F)
  98.     {
  99.         KeySta[0][0] = 1;  // 标记K1释放
  100.     }
  101.     // K2消抖逻辑
  102.     if ((keybuf[0][1] & 0x0F) == 0x00)  
  103.     {
  104.         KeySta[0][1] = 0;  // 标记K2按下
  105.     }
  106.     else if ((keybuf[0][1] & 0x0F) == 0x0F)
  107.     {
  108.         KeySta[0][1] = 1;  // 标记K2释放
  109.     }
  110.     // LED1计时逻辑
  111.     if (Led1Active)
  112.     {
  113.         Timer10s_LED1++;
  114.         if (Timer10s_LED1 >= 10000)  
  115.         {
  116.             LED1 = 1;
  117.             Led1Active = 0;
  118.         }
  119.     }
  120.     // LED4计时逻辑
  121.     if (Led4Active)
  122.     {
  123.         Timer10s_LED4++;
  124.         if (Timer10s_LED4 >= 10000)  
  125.         {
  126.             LED4 = 1;
  127.             Led4Active = 0;
  128.         }
  129.     }
  130. }
复制代码
按下按键暂停红绿灯时间

  1. #include <reg52.h>
  2. // 引脚定义
  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;
  7. sbit ENLED = P1^4;
  8. sbit KEY_OUT_1 = P2^3;
  9. sbit KEY_OUT_2 = P2^2;
  10. sbit KEY_OUT_3 = P1^2;
  11. sbit KEY_OUT_4 = P1^3;
  12. sbit KEY_IN_1  = P2^4;  // K1按键输入
  13. sbit KEY_IN_2  = P2^5;  // K2按键输入
  14. // 数码管显示
  15. unsigned char code LedChar[] = {
  16.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  17.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  18. };
  19. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  20. // 状态变量
  21. unsigned char flag1s = 0;
  22. unsigned char flag10ms = 0;
  23. unsigned char countDownPhase = 0;  // 0=30秒阶段, 1=20秒阶段
  24. unsigned long sec = 30;
  25. bit countDownFinished = 0;
  26. // 按键状态和LED控制
  27. unsigned char KeySta[4][4] = {
  28.     {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
  29. };
  30. bit K1_Pressed = 0;  // K1按键按下标志
  31. bit K2_Pressed = 0;  // K2按键按下标志
  32. bit LED_SpecialMode = 0; // 特殊LED模式标志
  33. unsigned int SpecialModeTimer = 0; // 特殊模式计时器(10秒)
  34. unsigned int secCnt = 0; // 秒计数器
  35. bit SpecialModeType = 0; // 0=K1模式, 1=K2模式
  36. void main()
  37. {
  38.     char j;
  39.     unsigned char buf[6];
  40.     // 初始化
  41.     EA = 1;
  42.     TMOD = 0x01;
  43.     TH0 = 0xFC;
  44.     TL0 = 0x67;
  45.     ET0 = 1;
  46.     TR0 = 1;
  47.    
  48.     // 初始化显示30
  49.     buf[0] = sec%10;
  50.     buf[1] = sec/10%10;
  51.     buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  52.    
  53.     for (j=5; j>=1; j--)
  54.     {
  55.         if (buf[j] == 0)
  56.             LedBuff[j] = 0xFF;
  57.         else
  58.             break;
  59.     }
  60.     for (; j>=0; j--)
  61.     {
  62.         LedBuff[j] = LedChar[buf[j]];
  63.     }
  64.     while (1)
  65.     {
  66.         // 检测K1按键状态(30秒阶段)
  67.         if (countDownPhase == 0 && KeySta[0][0] == 0 && !K1_Pressed && sec > 3)
  68.         {
  69.             K1_Pressed = 1;
  70.             LED_SpecialMode = 1;
  71.             SpecialModeTimer = 0;
  72.             SpecialModeType = 0; // K1模式
  73.             while (KeySta[0][0] == 0);  // 等待释放
  74.         }
  75.         else if (KeySta[0][0] == 1)
  76.         {
  77.             K1_Pressed = 0;
  78.         }
  79.         // 检测K2按键状态(20秒阶段)
  80.         if (countDownPhase == 1 && KeySta[0][1] == 0 && !K2_Pressed && sec > 3)
  81.         {
  82.             K2_Pressed = 1;
  83.             LED_SpecialMode = 1;
  84.             SpecialModeTimer = 0;
  85.             SpecialModeType = 1; // K2模式
  86.             while (KeySta[0][1] == 0);  // 等待释放
  87.         }
  88.         else if (KeySta[0][1] == 1)
  89.         {
  90.             K2_Pressed = 0;
  91.         }
  92.         // 特殊模式计时
  93.         if (flag10ms && LED_SpecialMode) {
  94.             SpecialModeTimer++;
  95.             if (SpecialModeTimer >= 1000) { // 1000*10ms = 10秒
  96.                 LED_SpecialMode = 0;
  97.             }
  98.         }
  99.         // 倒计时处理
  100.         if (flag1s == 1)
  101.         {
  102.             flag1s = 0;
  103.             
  104.             if (!countDownFinished)
  105.             {
  106.                 if (sec > 0)
  107.                 {
  108.                     sec--;
  109.                     
  110.                     buf[0] = sec%10;
  111.                     buf[1] = sec/10%10;
  112.                     buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  113.                     for (j=5; j>=1; j--)
  114.                     {
  115.                         if (buf[j] == 0)
  116.                             LedBuff[j] = 0xFF;
  117.                         else
  118.                             break;
  119.                     }
  120.                     for (; j>=0; j--)
  121.                     {
  122.                         LedBuff[j] = LedChar[buf[j]];
  123.                     }
  124.                 }
  125.                 else
  126.                 {
  127.                     countDownFinished = 1;
  128.                     countDownPhase++;
  129.                     LED_SpecialMode = 0; // 阶段切换时重置特殊模式
  130.                     
  131.                     if (countDownPhase == 1) {
  132.                         sec = 20;
  133.                         countDownFinished = 0;
  134.                         
  135.                         buf[0] = sec%10;
  136.                         buf[1] = sec/10%10;
  137.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  138.                         
  139.                         for (j=5; j>=1; j--)
  140.                         {
  141.                             if (buf[j] == 0)
  142.                                 LedBuff[j] = 0xFF;
  143.                             else
  144.                                 break;
  145.                         }
  146.                         for (; j>=0; j--)
  147.                         {
  148.                             LedBuff[j] = LedChar[buf[j]];
  149.                         }
  150.                     }
  151.                     else if (countDownPhase >= 2) {
  152.                         countDownPhase = 0;
  153.                         sec = 30;
  154.                         countDownFinished = 0;
  155.                         
  156.                         buf[0] = sec%10;
  157.                         buf[1] = sec/10%10;
  158.                         buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  159.                         
  160.                         for (j=5; j>=1; j--)
  161.                         {
  162.                             if (buf[j] == 0)
  163.                                 LedBuff[j] = 0xFF;
  164.                             else
  165.                                 break;
  166.                         }
  167.                         for (; j>=0; j--)
  168.                         {
  169.                             LedBuff[j] = LedChar[buf[j]];
  170.                         }
  171.                     }
  172.                 }
  173.             }
  174.         }
  175.     }
  176. }
  177. // 定时器0中断服务函数
  178. void Timer0_ISR() interrupt 1
  179. {
  180.     static unsigned char i = 0;
  181.     static unsigned int cnt = 0;
  182.     static unsigned char keyout = 0;
  183.     static unsigned char keybuf[4][4] = {
  184.         {0xFF, 0xFF, 0xFF, 0xFF},
  185.         {0xFF, 0xFF, 0xFF, 0xFF},
  186.         {0xFF, 0xFF, 0xFF, 0xFF},
  187.         {0xFF, 0xFF, 0xFF, 0xFF}
  188.     };
  189.     TH0 = 0xFC;
  190.     TL0 = 0x67;
  191.    
  192.     // 按键扫描(仅扫描第1行)
  193.     KEY_OUT_1 = 0;
  194.     KEY_OUT_2 = 1;
  195.     KEY_OUT_3 = 1;
  196.     KEY_OUT_4 = 1;
  197.     keybuf[0][0] = (keybuf[0][0] << 1) | KEY_IN_1;  // K1
  198.     keybuf[0][1] = (keybuf[0][1] << 1) | KEY_IN_2;  // K2
  199.     // K1消抖
  200.     if ((keybuf[0][0] & 0x0F) == 0x00)
  201.         KeySta[0][0] = 0;
  202.     else if ((keybuf[0][0] & 0x0F) == 0x0F)
  203.         KeySta[0][0] = 1;
  204.     // K2消抖
  205.     if ((keybuf[0][1] & 0x0F) == 0x00)
  206.         KeySta[0][1] = 0;
  207.     else if ((keybuf[0][1] & 0x0F) == 0x0F)
  208.         KeySta[0][1] = 1;
  209.     // 数码管显示和LED控制
  210.     P0 = 0xFF;
  211.     ENLED = 0;
  212.     ADDR3 = 1;
  213.     switch (i)
  214.     {
  215.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
  216.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
  217.         case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
  218.         case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
  219.         case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
  220.         case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
  221.         case 6:
  222.             ADDR2=1; ADDR1=1; ADDR0=0;
  223.             
  224.             if (countDownPhase == 0) {
  225.                 // 30秒阶段
  226.                 if (sec > 3) {
  227.                     // 前27秒
  228.                     if (LED_SpecialMode && !SpecialModeType) {
  229.                         P0 = 0xD7;  // LED1(P0.0)和LED4(P0.3)亮 (11010111)
  230.                     } else {
  231.                         P0 = 0xDE;  // 默认:LED1(P0.0)和LED6(P0.5)亮 (11011110)
  232.                     }
  233.                 } else if (sec > 0) {
  234.                     // 后3秒
  235.                     P0 = 0xDD;  // LED2(P0.1)和LED6(P0.5)亮 (11011101)
  236.                 } else {
  237.                     P0 = 0xFF;  // 熄灭所有
  238.                 }
  239.             } else if (countDownPhase == 1) {
  240.                 // 20秒阶段
  241.                 if (sec > 3) {
  242.                     // 前17秒
  243.                     if (LED_SpecialMode && SpecialModeType) {
  244.                         P0 = 0xF6;  // LED1(P0.0)和LED4(P0.3)亮 (11110110)
  245.                     } else {
  246.                         P0 = 0xF3;  // 默认:LED3(P0.2)和LED4(P0.3)亮 (11110011)
  247.                     }
  248.                 } else if (sec > 0) {
  249.                     // 后3秒
  250.                     P0 = 0xEB;  // LED3(P0.2)和LED5(P0.4)亮 (11101011)
  251.                 } else {
  252.                     P0 = 0xFF;  // 熄灭所有
  253.                 }
  254.             } else {
  255.                 P0 = 0xFF;
  256.             }
  257.             
  258.             i = 0;
  259.             break;
  260.         default: break;
  261.     }
  262.     // 定时处理
  263.     cnt++;
  264.     if (cnt >= 10) {  // 10ms
  265.         cnt = 0;
  266.         flag10ms = 1;
  267.         
  268.         secCnt++;
  269.         if (secCnt >= 100) {  // 100*10ms = 1s
  270.             secCnt = 0;
  271.             flag1s = 1;
  272.         }
  273.     } else {
  274.         flag10ms = 0;
  275.     }
  276. }
复制代码
基于STC89C52单片机的交通灯控制系统设计
用单片机控制一个交通信号灯系统,设 A 车道与 B 车道交织构成十字路口, A 是主车道, B 是支车道。具体要求如下:(1)用发光二极管模仿交通信号灯, A 、 B 车道各三盏灯,分别代表红、黄、绿;用
按键开关模仿车辆检测信号。(2)
正常情况下, A 、 B 辆车道轮替放行, A 车道放行30s,此中3s用于警告; B 车道放行20s,此中3s用于警告。
(3)
在交通繁忙时,交通信号灯控制系统应有手控开关,可人为地改变信号灯的状态,以缓解交通拥挤状况。在 B 车道放行期间,若 A 车道有车而 B 车道无车,按下开关K1使 A 车道放行10s;在 A 车道放行期间,若 B 车道有车而 A 车道无车,按下开关K2使 B 车道放行10s。(4)有紧急车辆通过时,按下K3开关使 A 、 B 车道均为红灯,禁行15s。


 

  1. #include <reg52.h>
  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. // 矩阵按键引脚定义
  8. sbit KEY_IN_1 = P2^4;  // 第1列
  9. sbit KEY_IN_2 = P2^5;  // 第2列
  10. sbit KEY_IN_3 = P2^6;  // 第3列
  11. sbit KEY_IN_4 = P2^7;  // 第4列
  12. sbit KEY_OUT_1 = P2^3; // 第1行
  13. sbit KEY_OUT_2 = P2^2; // 第2行
  14. sbit KEY_OUT_3 = P2^1; // 第3行
  15. sbit KEY_OUT_4 = P2^0; // 第4行
  16. unsigned char code LedChar[] = {
  17.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  18.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  19. };
  20. unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  21. unsigned char flag1s = 0;
  22. unsigned char countDownPhase = 0;  // 0=30秒阶段, 1=20秒阶段
  23. unsigned long sec = 30;
  24. bit countDownFinished = 0;
  25. // 按键和LED控制变量
  26. bit K1_pressed = 0;          // K1按下标志(第1行第1列)
  27. bit K2_pressed = 0;          // K2按下标志(第1行第2列)
  28. unsigned char K1_holdTime = 0; // K1按下保持时间
  29. unsigned char K2_holdTime = 0; // K2按下保持时间
  30. bit LED_override = 0;        // LED覆盖标志
  31. unsigned char overrideLEDState = 0xFF; // 覆盖的LED状态
  32. unsigned char normalLEDState = 0xFF; // 正常LED状态
  33. void KeyScan();
  34. void UpdateLEDs();
  35. void main()
  36. {
  37.     char j;
  38.     unsigned char buf[6];
  39.     EA = 1;
  40.     TMOD = 0x01;
  41.     TH0 = 0xFC;
  42.     TL0 = 0x67;
  43.     ET0 = 1;
  44.     TR0 = 1;
  45.     // 初始化显示30
  46.     buf[0] = sec%10;
  47.     buf[1] = sec/10%10;
  48.     buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
  49.    
  50.     for (j=5; j>=1; j--) {
  51.         if (buf[j] == 0) LedBuff[j] = 0xFF;
  52.         else break;
  53.     }
  54.     for (; j>=0; j--) {
  55.         LedBuff[j] = LedChar[buf[j]];
  56.     }
  57.     while(1) {
  58.         KeyScan();
  59.         
  60.         if (flag1s == 1) {
  61.             flag1s = 0;
  62.             
  63.             // 处理K1按下后的10秒计时
  64.             if (K1_pressed) {
  65.                 K1_holdTime++;
  66.                 if (K1_holdTime >= 10) {
  67.                     K1_pressed = 0;
  68.                     K1_holdTime = 0;
  69.                     LED_override = 0; // 恢复正常LED状态
  70.                 }
  71.             }
  72.             
  73.             // 处理K2按下后的10秒计时
  74.             if (K2_pressed) {
  75.                 K2_holdTime++;
  76.                 if (K2_holdTime >= 10) {
  77.                     K2_pressed = 0;
  78.                     K2_holdTime = 0;
  79.                     LED_override = 0; // 恢复正常LED状态
  80.                 }
  81.             }
  82.             
  83.             // 正常倒计时处理
  84.             if (!countDownFinished) {
  85.                 if (sec > 0) {
  86.                     sec--;
  87.                     
  88.                     // 更新数码管显示
  89.                     buf[0] = sec%10;
  90.                     buf[1] = sec/10%10;
  91.                     for (j=5; j>=1; j--) {
  92.                         if (buf[j] == 0) LedBuff[j] = 0xFF;
  93.                         else break;
  94.                     }
  95.                     for (; j>=0; j--) {
  96.                         LedBuff[j] = LedChar[buf[j]];
  97.                     }
  98.                     
  99.                     // 更新正常LED状态
  100.                     if (countDownPhase == 0) { // 30秒阶段
  101.                         if (sec > 3) normalLEDState = 0xDE; // LED1&6
  102.                         else if (sec > 0) normalLEDState = 0xDD; // LED2&6
  103.                         else normalLEDState = 0xFF;
  104.                     }
  105.                     else if (countDownPhase == 1) { // 20秒阶段
  106.                         if (sec > 3) normalLEDState = 0xF3; // LED3&4
  107.                         else if (sec > 0) normalLEDState = 0xEB; // LED3&5
  108.                         else normalLEDState = 0xFF;
  109.                     }
  110.                 } else {
  111.                     // 倒计时结束,切换到下一阶段
  112.                     countDownFinished = 1;
  113.                 }
  114.             } else {
  115.                 // 阶段切换处理
  116.                 countDownPhase++;
  117.                 if (countDownPhase == 1) { // 切换到20秒阶段
  118.                     sec = 20;
  119.                     countDownFinished = 0;
  120.                     normalLEDState = 0xF3; // LED3&4
  121.                 }
  122.                 else if (countDownPhase >= 2) { // 循环回到30秒阶段
  123.                     countDownPhase = 0;
  124.                     sec = 30;
  125.                     countDownFinished = 0;
  126.                     normalLEDState = 0xDE; // LED1&6
  127.                 }
  128.                
  129.                 // 更新数码管显示
  130.                 buf[0] = sec%10;
  131.                 buf[1] = sec/10%10;
  132.                 for (j=5; j>=1; j--) {
  133.                     if (buf[j] == 0) LedBuff[j] = 0xFF;
  134.                     else break;
  135.                 }
  136.                 for (; j>=0; j--) {
  137.                     LedBuff[j] = LedChar[buf[j]];
  138.                 }
  139.             }
  140.         }
  141.     }
  142. }
  143. void KeyScan()
  144. {
  145.     static unsigned char keyDebounceK1 = 0;
  146.     static unsigned char keyDebounceK2 = 0;
  147.    
  148.     // 扫描第1行
  149.     KEY_OUT_1 = 0;  // 选通第1行
  150.     KEY_OUT_2 = 1;
  151.     KEY_OUT_3 = 1;
  152.     KEY_OUT_4 = 1;
  153.    
  154.     // 检测K1 (第1行第1列)
  155.     if (KEY_IN_1 == 0) {
  156.         keyDebounceK1++;
  157.         if (keyDebounceK1 >= 5 && !K1_pressed && countDownPhase == 0 && sec >= 10) {
  158.             K1_pressed = 1;
  159.             K1_holdTime = 0;
  160.             LED_override = 1;
  161.             overrideLEDState = 0xF3; // LED3和LED4亮
  162.         }
  163.     } else {
  164.         keyDebounceK1 = 0;
  165.     }
  166.    
  167.     // 检测K2 (第1行第2列)
  168.     if (KEY_IN_2 == 0) {
  169.         keyDebounceK2++;
  170.         if (keyDebounceK2 >= 5 && !K2_pressed && countDownPhase == 1 && sec >= 10) {
  171.             K2_pressed = 1;
  172.             K2_holdTime = 0;
  173.             LED_override = 1;
  174.             overrideLEDState = 0xDE; // LED1和LED6亮
  175.         }
  176.     } else {
  177.         keyDebounceK2 = 0;
  178.     }
  179. }
  180. void Timer0_ISR() interrupt 1
  181. {
  182.     static unsigned char i = 0;
  183.     static unsigned int cnt = 0;
  184.     TH0 = 0xFC;
  185.     TL0 = 0x67;
  186.    
  187.     P0 = 0xFF;
  188.     ENLED = 0;
  189.     ADDR3 = 1;
  190.     // 数码管动态扫描
  191.     switch(i) {
  192.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
  193.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
  194.         case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
  195.         case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
  196.         case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
  197.         case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
  198.         case 6:
  199.             ADDR2=1; ADDR1=1; ADDR0=0;
  200.             
  201.             // LED控制
  202.             if (LED_override) {
  203.                 P0 = overrideLEDState; // 使用覆盖的LED状态
  204.             } else {
  205.                 P0 = normalLEDState; // 正常LED状态
  206.             }
  207.             i = 0;
  208.             break;
  209.         default: break;
  210.     }
  211.     // 1秒定时
  212.     cnt++;
  213.     if (cnt >= 1000) {
  214.         cnt = 0;
  215.         flag1s = 1;
  216.     }
  217. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表