第二十一节:多任务并行处理两路跑马灯。(上)

开场白:
上一节讲了依次逐个亮灯并且每次只能亮一个灯的跑马灯程序。这一节要结合前面两节的内容,实现多任务并行处理两路跑马灯。要教会大家一个知识点:利用鸿哥的switch状态机思想,实现多任务并行处理的程序。
具体内容,请看源代码讲解。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:
第一路独立运行的任务是:第1个至第8个LED灯,先依次逐个亮,再依次逐个灭。
第二路独立运行的任务是:第9个至第16个LED灯,依次逐个亮灯并且每次只能亮一个灯。

(3)源代码讲解如下: 

  1. #include "REG52.H"  
  2.   
  3. #define const_time_level_01_08  200  //第1个至第8个LED跑马灯的速度延时时间  
  4. #define const_time_level_09_16  300  //第9个至第16个LED跑马灯的速度延时时间  
  5.   
  6. void initial_myself();      
  7. void initial_peripheral();  
  8. void delay_short(unsigned int uiDelayShort);   
  9. void delay_long(unsigned int uiDelaylong);  
  10. void led_flicker_01_08(); //第一路独立运行的任务 第1个至第8个LED的跑马灯程序,逐个亮,逐个灭.  
  11. void led_flicker_09_16(); //第二路独立运行的任务 第9个至第16个LED的跑马灯程序,逐个亮并且每次只能亮一个.  
  12. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);  
  13. void led_update();  //LED更新函数  
  14. void T0_time();  //定时中断函数  
  15.   
  16.   
  17. sbit hc595_sh_dr=P2^3;      
  18. sbit hc595_st_dr=P2^4;    
  19. sbit hc595_ds_dr=P2^5;    
  20.   
  21. unsigned char ucLed_dr1=0;   //代表16个灯的亮灭状态,0代表灭,1代表亮  
  22. unsigned char ucLed_dr2=0;  
  23. unsigned char ucLed_dr3=0;  
  24. unsigned char ucLed_dr4=0;  
  25. unsigned char ucLed_dr5=0;  
  26. unsigned char ucLed_dr6=0;  
  27. unsigned char ucLed_dr7=0;  
  28. unsigned char ucLed_dr8=0;  
  29. unsigned char ucLed_dr9=0;  
  30. unsigned char ucLed_dr10=0;  
  31. unsigned char ucLed_dr11=0;  
  32. unsigned char ucLed_dr12=0;  
  33. unsigned char ucLed_dr13=0;  
  34. unsigned char ucLed_dr14=0;  
  35. unsigned char ucLed_dr15=0;  
  36. unsigned char ucLed_dr16=0;  
  37.   
  38. unsigned char ucLed_update=0;  //刷新变量。每次更改LED灯的状态都要更新一次。  
  39.   
  40.   
  41. unsigned char ucLedStep_01_08=0; //第1个至第8个LED跑马灯的步骤变量  
  42. unsigned int  uiTimeCnt_01_08=0; //第1个至第8个LED跑马灯的统计定时中断次数的延时计数器  
  43.   
  44. unsigned char ucLedStep_09_16=0; //第9个至第16个LED跑马灯的步骤变量  
  45. unsigned int  uiTimeCnt_09_16=0; //第9个至第16个LED跑马灯的统计定时中断次数的延时计数器  
  46.   
  47. unsigned char ucLedStatus16_09=0;   //代表底层74HC595输出状态的中间变量  
  48. unsigned char ucLedStatus08_01=0;   //代表底层74HC595输出状态的中间变量  
  49.   
  50. void main()   
  51.   {  
  52.    initial_myself();    
  53.    delay_long(100);     
  54.    initial_peripheral();   
  55.    while(1)     
  56.    {  
  57.       led_flicker_01_08(); //第一路独立运行的任务 第1个至第8个LED的跑马灯程序,逐个亮,逐个灭.  
  58.       led_flicker_09_16(); //第二路独立运行的任务 第9个至第16个LED的跑马灯程序,逐个亮并且每次只能亮一个.  
  59.           led_update();  //LED更新函数  
  60.    }  
  61.   
  62. }  
  63.   
  64.   
  65. void led_update()  //LED更新函数  
  66. {  
  67.   
  68.    if(ucLed_update==1)  
  69.    {  
  70.        ucLed_update=0;   //及时清零,让它产生只更新一次的效果,避免一直更新。  
  71.   
  72.        if(ucLed_dr1==1)  
  73.            {  
  74.               ucLedStatus08_01=ucLedStatus08_01|0x01;  
  75.            }  
  76.            else  
  77.            {  
  78.               ucLedStatus08_01=ucLedStatus08_01&0xfe;  
  79.            }  
  80.   
  81.        if(ucLed_dr2==1)  
  82.            {  
  83.               ucLedStatus08_01=ucLedStatus08_01|0x02;  
  84.            }  
  85.            else  
  86.            {  
  87.               ucLedStatus08_01=ucLedStatus08_01&0xfd;  
  88.            }  
  89.   
  90.        if(ucLed_dr3==1)  
  91.            {  
  92.               ucLedStatus08_01=ucLedStatus08_01|0x04;  
  93.            }  
  94.            else  
  95.            {  
  96.               ucLedStatus08_01=ucLedStatus08_01&0xfb;  
  97.            }  
  98.   
  99.        if(ucLed_dr4==1)  
  100.            {  
  101.               ucLedStatus08_01=ucLedStatus08_01|0x08;  
  102.            }  
  103.            else  
  104.            {  
  105.               ucLedStatus08_01=ucLedStatus08_01&0xf7;  
  106.            }  
  107.   
  108.   
  109.        if(ucLed_dr5==1)  
  110.            {  
  111.               ucLedStatus08_01=ucLedStatus08_01|0x10;  
  112.            }  
  113.            else  
  114.            {  
  115.               ucLedStatus08_01=ucLedStatus08_01&0xef;  
  116.            }  
  117.   
  118.   
  119.        if(ucLed_dr6==1)  
  120.            {  
  121.               ucLedStatus08_01=ucLedStatus08_01|0x20;  
  122.            }  
  123.            else  
  124.            {  
  125.               ucLedStatus08_01=ucLedStatus08_01&0xdf;  
  126.            }  
  127.   
  128.   
  129.        if(ucLed_dr7==1)  
  130.            {  
  131.               ucLedStatus08_01=ucLedStatus08_01|0x40;  
  132.            }  
  133.            else  
  134.            {  
  135.               ucLedStatus08_01=ucLedStatus08_01&0xbf;  
  136.            }  
  137.   
  138.   
  139.        if(ucLed_dr8==1)  
  140.            {  
  141.               ucLedStatus08_01=ucLedStatus08_01|0x80;  
  142.            }  
  143.            else  
  144.            {  
  145.               ucLedStatus08_01=ucLedStatus08_01&0x7f;  
  146.            }  
  147.   
  148.        if(ucLed_dr9==1)  
  149.            {  
  150.               ucLedStatus16_09=ucLedStatus16_09|0x01;  
  151.            }  
  152.            else  
  153.            {  
  154.               ucLedStatus16_09=ucLedStatus16_09&0xfe;  
  155.            }  
  156.   
  157.        if(ucLed_dr10==1)  
  158.            {  
  159.               ucLedStatus16_09=ucLedStatus16_09|0x02;  
  160.            }  
  161.            else  
  162.            {  
  163.               ucLedStatus16_09=ucLedStatus16_09&0xfd;  
  164.            }  
  165.   
  166.        if(ucLed_dr11==1)  
  167.            {  
  168.               ucLedStatus16_09=ucLedStatus16_09|0x04;  
  169.            }  
  170.            else  
  171.            {  
  172.               ucLedStatus16_09=ucLedStatus16_09&0xfb;  
  173.            }  
  174.   
  175.        if(ucLed_dr12==1)  
  176.            {  
  177.               ucLedStatus16_09=ucLedStatus16_09|0x08;  
  178.            }  
  179.            else  
  180.            {  
  181.               ucLedStatus16_09=ucLedStatus16_09&0xf7;  
  182.            }  
  183.   
  184.   
  185.        if(ucLed_dr13==1)  
  186.            {  
  187.               ucLedStatus16_09=ucLedStatus16_09|0x10;  
  188.            }  
  189.            else  
  190.            {  
  191.               ucLedStatus16_09=ucLedStatus16_09&0xef;  
  192.            }  
  193.   
  194.   
  195.        if(ucLed_dr14==1)  
  196.            {  
  197.               ucLedStatus16_09=ucLedStatus16_09|0x20;  
  198.            }  
  199.            else  
  200.            {  
  201.               ucLedStatus16_09=ucLedStatus16_09&0xdf;  
  202.            }  
  203.   
  204.   
  205.        if(ucLed_dr15==1)  
  206.            {  
  207.               ucLedStatus16_09=ucLedStatus16_09|0x40;  
  208.            }  
  209.            else  
  210.            {  
  211.               ucLedStatus16_09=ucLedStatus16_09&0xbf;  
  212.            }  
  213.   
  214.   
  215.        if(ucLed_dr16==1)  
  216.            {  
  217.               ucLedStatus16_09=ucLedStatus16_09|0x80;  
  218.            }  
  219.            else  
  220.            {  
  221.               ucLedStatus16_09=ucLedStatus16_09&0x7f;  
  222.            }  
  223.   
  224.        hc595_drive(ucLedStatus16_09,ucLedStatus08_01);  //74HC595底层驱动函数  
  225.   
  226.    }  
  227. }  
  228.   
  229. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)  
  230. {  
  231.    unsigned char i;  
  232.    unsigned char ucTempData;  
  233.    hc595_sh_dr=0;  
  234.    hc595_st_dr=0;  
  235.   
  236.    ucTempData=ucLedStatusTemp16_09;  //先送高8位  
  237.    for(i=0;i<8;i++)  
  238.    {   
  239.          if(ucTempData>=0x80)hc595_ds_dr=1;  
  240.          else hc595_ds_dr=0;  
  241.   
  242.          hc595_sh_dr=0;     //SH引脚的上升沿把数据送入寄存器  
  243.          delay_short(15);   
  244.          hc595_sh_dr=1;  
  245.          delay_short(15);   
  246.   
  247.          ucTempData=ucTempData<<1;  
  248.    }  
  249.   
  250.    ucTempData=ucLedStatusTemp08_01;  //再先送低8位  
  251.    for(i=0;i<8;i++)  
  252.    {   
  253.          if(ucTempData>=0x80)hc595_ds_dr=1;  
  254.          else hc595_ds_dr=0;  
  255.   
  256.          hc595_sh_dr=0;     //SH引脚的上升沿把数据送入寄存器  
  257.          delay_short(15);   
  258.          hc595_sh_dr=1;  
  259.          delay_short(15);   
  260.   
  261.          ucTempData=ucTempData<<1;  
  262.    }  
  263.   
  264.    hc595_st_dr=0;  //ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来  
  265.    delay_short(15);   
  266.    hc595_st_dr=1;  
  267.    delay_short(15);   
  268.   
  269.    hc595_sh_dr=0;    //拉低,抗干扰就增强  
  270.    hc595_st_dr=0;  
  271.    hc595_ds_dr=0;  
  272.   
  273. }  
  274.   
  275. /* 注释一: 
  276. * 以下程序,看似简单而且重复,其实蕴含着鸿哥的大智慧。 
  277. * 它是基于鸿哥的switch状态机思想,领略到了它的简单和精髓, 
  278. * 以后任何所谓复杂的工程项目,都不再复杂。 
  279. */  
  280.   
  281. void led_flicker_01_08() //第一路独立运行的任务 第1个至第8个LED的跑马灯程序,逐个亮,逐个灭.  
  282. {  
  283.   switch(ucLedStep_01_08)  
  284.   {  
  285.      case 0:  
  286.            if(uiTimeCnt_01_08>=const_time_level_01_08) //时间到  
  287.            {  
  288.                uiTimeCnt_01_08=0; //时间计数器清零  
  289.   
  290.                ucLed_dr1=1;  //第1个亮  
  291.   
  292.                ucLed_update=1;  //更新显示  
  293.                ucLedStep_01_08=1; //切换到下一个步骤  
  294.            }  
  295.            break;  
  296.      case 1:  
  297.            if(uiTimeCnt_01_08>=const_time_level_01_08) //时间到  
  298.            {  
  299.                uiTimeCnt_01_08=0; //时间计数器清零  
  300.   
  301.                ucLed_dr2=1;  //第2个亮  
  302.   
  303.                ucLed_update=1;  //更新显示  
  304.                ucLedStep_01_08=2; //切换到下一个步骤  
  305.            }  
  306.            break;  

(下本部分http://www.eeskill.com/group/topic_scan/id/505

永不止步步 发表于11-20 15:24 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:308317个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号