51单片机彩灯控制器的设计 | 珊瑚贝

前言

又到了一学期一度的期末设计环节,作为全班第一大神的我居然抽到了单片机课程设计里最简单的一道题,真的是不给我一点挑战的机会 [微笑]

51单片机彩灯控制器的设计

原题要求如下:

1. 用16盏以上的LED小灯,实现至少4种彩灯灯光效果(不含全部点亮,全部熄灭);

2. 可以用输入按钮在几种灯光效果间切换;

3. 可以通过按钮暂停彩灯效果,使小灯全亮,再次按下相同按钮后继续之前的效果;

4. 增加自动在几种效果间切换的功能,并设置一个按钮可以在自动模式和手动模式间切换;

5. 使用定时中断延时。

我的最终作品如下:

(为方便演示,速度已调快一倍处理)

51单片机彩灯控制器的设计

一共有十钟灯光效果,分别是:
顺时针流水灯、逆时针流水灯、交替闪烁、顺时针对角灯、逆时针对角灯、顺时针逐个点亮、顺时针逐个熄灭、逆时针逐个点亮、逆时针逐个熄灭、二进制加法。

程序代码如下:

代码太长,已被折叠。点击展开查看
  1. /**************************************************************************************************
  2. 模块名称:51单片机彩灯控制器
  3. 模块功能:实现十种循环彩灯控制
  4. 编写人员:mengkun  (http://mkblog.cn)
  5. 编写日期:2016/12/18
  6. **************************************************************************************************/
  7. #include <reg51.h>
  8. #define false 0
  9. #define true 1
  10. #define uchar unsigned char
  11. #define uint unsigned int
  12. sbit pause_key = P3^0;  //暂停按钮
  13. sbit auto_key = P3^1;   //手动模式的效果切换
  14. sbit change_key = P3^2; //手动模式效果切换
  15. sbit pauseLed = P3^6;   //暂停、启动指示灯
  16. sbit autoLed = P3^7;    //自动、手动模式指示灯
  17. int ledCode[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //led段码(单个显示)
  18. int ledCode2[8]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00}; //led段码(半显示半灭)
  19. int disCode[10]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //数码管段码 0~9
  20. void displayLed(void);  //显示led的主函数
  21. void keyScan(void); //键盘扫描处理函数
  22. void Delay10ms(unsigned int n); //延时10ms
  23. bit isPause = false;    //是否暂停
  24. bit isAuto = true;  //是否自动运行
  25. bit isChange = false;   //是否要切换下一个效果
  26. uchar time;   //计时满0.5s
  27. uchar types;    //第几种灯光显示方案
  28. uint counts;    //灯光的第几个
  29. /******************************************************************************* 
  30. * 函 数 名          : T0_INT
  31. * 函数功能         : T0定时器中断函数
  32. * 输      入         : 无
  33. * 输      出         : 无 
  34. *******************************************************************************/
  35. void T0_INT(void)  interrupt 1
  36. {
  37.     TL0= (65536-50000)/256;
  38.     TH0= (65536-50000)%256;
  39.     time ++;
  40.     if(time >= 10) //定时时间:0.5s
  41.     {
  42.         time=0;
  43.         if(isChange == true)    //可以变换下一种显示效果了
  44.         {
  45.             counts = 0;
  46.             types++;    //显示下一种效果
  47.             if(types > 9) types = 0;
  48.             P0 = disCode[types];        //更新数码管显示
  49.             isChange = false;
  50.         }
  51.         displayLed();
  52.         counts++;
  53.     }
  54. }
  55. /******************************************************************************* 
  56. * 函 数 名          : main
  57. * 函数功能         : 主函数
  58. * 输      入         : 无
  59. * 输      出         : 无 
  60. *******************************************************************************/
  61. void main(void)
  62. {
  63.     TMOD=0x61; //0110 0001  //方式一
  64.     TL0= (65536-50000)/256;     //50ms
  65.     TH0= (65536-50000)%256;
  66.     TR0=1;      //开启T0
  67.     ET0=1;      //T0中断允许
  68.     EA=1;   //总中断开启
  69.     time = 0;   //定时器时间扩种(0.5s)
  70.     counts = 0; //灯光的第几次    
  71.     types = 0;  //灯光显示模式
  72.     pauseLed = 0; //暂停指示灯灭
  73.     P0 = disCode[types];        //更新数码管显示
  74.     while(1)
  75.     {
  76.         keyScan();  //键盘扫描及处理
  77.     }
  78. }
  79. /******************************************************************************* 
  80. * 函 数 名          : keyScan
  81. * 函数功能         : 键盘扫描处理
  82. * 输      入         : 无
  83. * 输      出         : 无 
  84. *******************************************************************************/
  85. void keyScan(void)
  86. {
  87.     if(pause_key == 0)  //按下了暂停按钮
  88.     {
  89.         Delay10ms(1);
  90.         if(pause_key == 0)
  91.         {
  92.             isPause = ~isPause;
  93.             pauseLed = isPause;
  94.             if(isPause == true)
  95.             {
  96.                 ET0=0;      //关闭T0中断
  97.                 P0 = 0xfd;  //数码管显示 “-”
  98.                 P1 = 0x00;  //所有的灯都亮起来
  99.                 P2 = 0x00;
  100.             }else{
  101.                 ET0=1;      //T0中断允许
  102.                 P0 = disCode[types];        //更新数码管显示
  103.                 displayLed();
  104.             }
  105.             while(pause_key == 0);  //防止按键重复检测
  106.         }
  107.     }
  108.     if(auto_key == 0)   //自动、手动切换按键按下
  109.     {
  110.         Delay10ms(1);
  111.         if(auto_key == 0)
  112.         {
  113.             isAuto = ~isAuto;
  114.             autoLed = isAuto;
  115.         }
  116.         while(auto_key == 0);   //防止按键重复检测
  117.     }
  118.     if(change_key == 0 && isAuto == false)  //手动模式,并且效果切换按下
  119.     {
  120.         Delay10ms(1);
  121.         if(change_key == 0)
  122.         {
  123.             isChange = true;
  124.         }
  125.         while(change_key == 0); //防止按键重复检测
  126.     }
  127. }
  128. /******************************************************************************* 
  129. * 函 数 名          : displayLed
  130. * 函数功能         : 显示led灯
  131. * 输      入         : (全局变量 )types:显示效果;counts:当前效果下的第几次
  132. * 输      出         : 无 
  133. *******************************************************************************/
  134. void displayLed(void)
  135. {
  136.     switch(types)
  137.     {
  138.         case 0: //顺时针旋转led灯
  139.         {
  140.             if(counts >= 16) counts = 0;
  141.             if(counts >=15)
  142.             {
  143.                 if(isAuto == true) isChange = true;
  144.             }
  145.             if(counts <8)
  146.             {
  147.                 P1 = 0xff;
  148.                 P2 = ledCode[7-counts];
  149.             }
  150.             else
  151.             {
  152.                 P1 = ledCode[15-counts];
  153.                 P2 = 0xff;
  154.             }
  155.             break;
  156.         }
  157.         case 1: //逆时针旋转LED灯
  158.         {
  159.             if(counts >= 16) counts = 0;
  160.             if(counts >=15)
  161.             {
  162.                 if(isAuto == true) isChange = true;
  163.             }
  164.             if(counts <8)
  165.             {
  166.                 P1 = ledCode[counts];
  167.                 P2 = 0xff;
  168.             }
  169.             else
  170.             {
  171.                 P1 = 0xff;
  172.                 P2 = ledCode[counts-8];
  173.             }
  174.             break;
  175.         }
  176.         case 2: //交叉替换
  177.         {
  178.             if(counts >= 16) counts = 0;
  179.             if(counts >=15)
  180.             {
  181.                 if(isAuto == true) isChange = true;
  182.             }
  183.             if(counts % 2 == 0) //偶数
  184.             {
  185.                 P1=0xaa;
  186.                 P2=0xaa;
  187.             }
  188.             else
  189.             {
  190.                 P1=0x55;
  191.                 P2=0x55;
  192.             }
  193.             break;
  194.         }
  195.         case 3: //对角顺时针
  196.         {
  197.             if(counts >= 8) counts = 0;
  198.             if(counts >=7)
  199.             {
  200.                 if(isAuto == true) isChange = true;
  201.             }
  202.             P1 = ledCode[7 – counts];
  203.             P2 = ledCode[7 – counts];
  204.             break;
  205.         }
  206.         case 4: //对角逆时针
  207.         {
  208.             if(counts >= 8) counts = 0;
  209.             if(counts >=7)
  210.             {
  211.                 if(isAuto == true) isChange = true;
  212.             }
  213.             P1 = ledCode[counts];
  214.             P2 = ledCode[counts];
  215.             break;
  216.         }
  217.         case 5: //顺时针逐个点亮
  218.         {
  219.             if(counts >= 17) counts = 0;
  220.             if(counts <8)
  221.             {
  222.                 P1 = ~ledCode2[7 – counts];
  223.                 P2 = 0xff;
  224.             }
  225.             else if(counts <16)
  226.             {
  227.                 P1 = 0x00;
  228.                 P2 = ~ledCode2[15 – counts];
  229.             }
  230.             else    //全亮
  231.             {
  232.                 P1 = 0x00;
  233.                 P2 = 0x00;
  234.                 if(isAuto == true) isChange = true;
  235.             }
  236.             break;
  237.         }
  238.         case 6: //顺时针逐个又灭掉
  239.         {
  240.             if(counts >= 17) counts = 0;
  241.             if(counts <8)
  242.             {
  243.                 P1 = ledCode2[7 – counts];
  244.                 P2 = 0x00;
  245.             }
  246.             else if(counts <16)
  247.             {
  248.                 P1 = 0xff;
  249.                 P2 = ledCode2[15 – counts];
  250.             }
  251.             else    //全灭
  252.             {
  253.                 P1 = 0xff;
  254.                 P2 = 0xff;
  255.                 if(isAuto == true) isChange = true;
  256.             }
  257.             break;
  258.         }
  259.         case 7: //逆时针逐个点亮
  260.         {
  261.             if(counts >= 17) counts = 0;
  262.             if(counts <8)
  263.             {
  264.                 P1 = 0xff;
  265.                 P2 = ledCode2[counts];
  266.             }
  267.             else if(counts <16)
  268.             {
  269.                 P1 = ledCode2[counts – 7];
  270.                 P2 = 0x00;
  271.             }
  272.             else    //全亮
  273.             {
  274.                 P1 = 0x00;
  275.                 P2 = 0x00;
  276.                 if(isAuto == true) isChange = true;
  277.             }
  278.             break;
  279.         }
  280.         case 8: //逆时针逐个灭掉
  281.         {
  282.             if(counts >= 17) counts = 0;
  283.             if(counts <8)
  284.             {
  285.                 P1 = 0x00;
  286.                 P2 = ~ledCode2[counts];
  287.             }
  288.             else if(counts <16)
  289.             {
  290.                 P1 = ~ledCode2[counts – 7];
  291.                 P2 = 0xff;
  292.             }
  293.             else    //全亮
  294.             {
  295.                 P1 = 0xff;
  296.                 P2 = 0xff;
  297.                 if(isAuto == true) isChange = true;
  298.             }
  299.             break;
  300.         }
  301.         case 9: //二进制加法
  302.         {
  303.             if(counts >= 255) counts = 0;
  304.             if(counts == 254 && isAuto == true) isChange = true;
  305.             P1 = ~counts;
  306.             P2 = ~counts;
  307.             break;
  308.         }
  309.         default:
  310.             types = 0;
  311.             P0 = disCode[types];        //更新数码管显示
  312.     }
  313. }
  314. /******************************************************************************* 
  315. * 函 数 名          : Delay10ms (多个) 
  316. * 函数功能         : 延时函数,延时n*10ms 
  317. * 输      入         : n-延时次数 
  318. * 输      出         : 无 
  319. *******************************************************************************/
  320. void Delay10ms(unsigned int n)
  321. {
  322.     unsigned char a, b;
  323.     for (; n>0; n–)
  324.     {
  325.         for (b=38; b>0; b–)
  326.         {
  327.             for (a=130; a>0; a–);
  328.         }
  329.     }
  330. }

完整proteus仿真图如下:

(可点击查看大图)

51单片机彩灯控制器的设计

程序和仿真图打包下载:

下载地址

来源:https://mkblog.cn/459/

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?