第十七节:两片联级74HC595驱动16个LED灯的基本驱动程序。

开场白:
上一节讲了如何把矩阵键盘翻译成独立按键的处理方式。这节讲74HC595的驱动程序。要教会大家两个知识点:
第一点:朱兆祺的学习板是用74HC595控制LED,因此可以直接把595的OE引脚接地。如果在工控中,用来控制继电器,那么此芯片的片选脚OE不要为了省一个IO口而直接接地,否则会引起上电瞬间继电器莫名其妙地动作。为了解决这个问题,OE脚应该用一个IO口单独驱动,并且千万要记住,此IO必须接一个15K左右的上拉电阻,然后在程序刚上电运行时,先把OE置高,并且尽快把所有的74HC595输出口置低,然后再把OE置低.当然还有另外一种解决办法,就是用一个10uF的电解电容跟一个100K的下拉电阻,组成跟51单片机外围复位电路原理一样的电路,连接到OE口,这样确保上电瞬间OE口有一小段时间是处于高电平状态,在此期间,尽快通过软件把74hc595的所有输出口置低。
第二点:两个联级74HC595的工作过程:每个74HC595内部都有一个8位的寄存器,两个联级起来就有两个寄存器。ST引脚就相当于一个刷新信号引脚,当ST引脚产生一个上升沿信号时,就会把寄存器的数值输出到74HC595的输出引脚并且锁存起来,DS是数据引脚,SH是把新数据送入寄存器的时钟信号。也就是说,SH引脚负责把数据送入到寄存器里,ST引脚负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。

具体内容,请看源代码讲解。

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

(2)实现功能:两片联级的74HC595驱动的16个LED灯交叉闪烁。比如,先是第1,3,5,7,9,11,13,15八个灯亮,其它的灯都灭。然后再反过来,原来亮的就灭,原来灭的就亮。交替闪烁。

(3)源代码讲解如下: 

  1. #include "REG52.H"  
  2.   
  3. #define const_time_level 200    
  4.   
  5. void initial_myself();      
  6. void initial_peripheral();  
  7. void delay_short(unsigned int uiDelayShort);   
  8. void delay_long(unsigned int uiDelaylong);  
  9. void led_flicker();  
  10. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);  
  11. void T0_time();  //定时中断函数  
  12.   
  13. /* 注释一: 
  14. * 朱兆祺的学习板是用74HC595控制LED,因此可以直接把595的OE引脚接地。如果在工控中,用来控制继电器, 
  15. * 那么此芯片的片选脚OE不要为了省一个IO口而直接接地,否则会引起上电瞬间继电器莫名其妙地动作。 
  16. * 为了解决这个问题,OE脚应该用一个IO口单独驱动,并且千万要记住,此IO必须接一个15K左右的 
  17. * 上拉电阻,然后在程序刚上电运行时,先把OE置高,并且尽快把所有的74HC595输出口置低,然后再把OE置低. 
  18. * 当然还有另外一种解决办法,就是用一个10uF的电解电容跟一个100K的下拉电阻,组成跟51单片机外围复位电路原理 
  19. * 一样的电路,连接到OE口,这样确保上电瞬间OE口有一小段时间是处于高电平状态,在此 期间, 
  20. * 尽快通过软件把74hc595的所有输出口置低。 
  21. */  
  22. sbit hc595_sh_dr=P2^3;      
  23. sbit hc595_st_dr=P2^4;    
  24. sbit hc595_ds_dr=P2^5;    
  25.   
  26.   
  27. unsigned char ucLedStep=0; //步骤变量  
  28. unsigned int  uiTimeCnt=0; //统计定时中断次数的延时计数器  
  29.   
  30.   
  31. void main()   
  32.   {  
  33.    initial_myself();    
  34.    delay_long(100);     
  35.    initial_peripheral();   
  36.    while(1)     
  37.    {  
  38.       led_flicker();     
  39.    }  
  40.   
  41. }  
  42.   
  43. /* 注释二: 
  44. * 两个联级74HC595的工作过程: 
  45. * 每个74HC595内部都有一个8位的寄存器,两个联级起来就有两个寄存器。ST引脚就相当于一个刷新 
  46. * 信号引脚,当ST引脚产生一个上升沿信号时,就会把寄存器的数值输出到74HC595的输出引脚并且锁存起来, 
  47. * DS是数据引脚,SH是把新数据送入寄存器的时钟信号。也就是说,SH引脚负责把数据送入到寄存器里,ST引脚 
  48. * 负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。 
  49. */  
  50. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)  
  51. {  
  52.    unsigned char i;  
  53.    unsigned char ucTempData;  
  54.    hc595_sh_dr=0;  
  55.    hc595_st_dr=0;  
  56.   
  57.    ucTempData=ucLedStatusTemp16_09;  //先送高8位  
  58.    for(i=0;i<8;i++)  
  59.    {   
  60.          if(ucTempData>=0x80)hc595_ds_dr=1;  
  61.          else hc595_ds_dr=0;  
  62.   
  63.          hc595_sh_dr=0;     //SH引脚的上升沿把数据送入寄存器  
  64.          delay_short(15);   
  65.          hc595_sh_dr=1;  
  66.          delay_short(15);   
  67.   
  68.          ucTempData=ucTempData<<1;  
  69.    }  
  70.   
  71.    ucTempData=ucLedStatusTemp08_01;  //再先送低8位  
  72.    for(i=0;i<8;i++)  
  73.    {   
  74.          if(ucTempData>=0x80)hc595_ds_dr=1;  
  75.          else hc595_ds_dr=0;  
  76.   
  77.          hc595_sh_dr=0;     //SH引脚的上升沿把数据送入寄存器  
  78.          delay_short(15);   
  79.          hc595_sh_dr=1;  
  80.          delay_short(15);   
  81.   
  82.          ucTempData=ucTempData<<1;  
  83.    }  
  84.   
  85.    hc595_st_dr=0;  //ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来  
  86.    delay_short(15);   
  87.    hc595_st_dr=1;  
  88.    delay_short(15);   
  89.   
  90.    hc595_sh_dr=0;    //拉低,抗干扰就增强  
  91.    hc595_st_dr=0;  
  92.    hc595_ds_dr=0;  
  93.   
  94. }  
  95.   
  96.   
  97. void led_flicker() ////第三区 LED闪烁应用程序  
  98. {  
  99.   switch(ucLedStep)  
  100.   {  
  101.      case 0:  
  102.            if(uiTimeCnt>=const_time_level) //时间到  
  103.            {  
  104.                uiTimeCnt=0; //时间计数器清零  
  105.                hc595_drive(0x55,0x55);  
  106.                ucLedStep=1; //切换到下一个步骤  
  107.            }  
  108.            break;  
  109.      case 1:  
  110.            if(uiTimeCnt>=const_time_level) //时间到  
  111.            {  
  112.                uiTimeCnt=0; //时间计数器清零  
  113.                hc595_drive(0xaa,0xaa);  
  114.                ucLedStep=0; //返回到上一个步骤  
  115.            }  
  116.            break;  
  117.     
  118.    }  
  119.   
  120. }  
  121.   
  122.   
  123. void T0_time() interrupt 1  
  124. {  
  125.   TF0=0;  //清除中断标志  
  126.   TR0=0; //关中断  
  127.   
  128.   if(uiTimeCnt<0xffff)  //设定这个条件,防止uiTimeCnt超范围。  
  129.   {  
  130.       uiTimeCnt++;  //累加定时中断的次数,  
  131.   }  
  132.   
  133.   TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f  
  134.   TL0=0x2f;  
  135.   TR0=1;  //开中断  
  136. }  
  137.   
  138. void delay_short(unsigned int uiDelayShort)   
  139. {  
  140.    unsigned int i;    
  141.    for(i=0;i<uiDelayShort;i++)  
  142.    {  
  143.      ;   //一个分号相当于执行一条空语句  
  144.    }  
  145. }  
  146.   
  147. void delay_long(unsigned int uiDelayLong)  
  148. {  
  149.    unsigned int i;  
  150.    unsigned int j;  
  151.    for(i=0;i<uiDelayLong;i++)  
  152.    {  
  153.       for(j=0;j<500;j++)  //内嵌循环的空指令数量  
  154.           {  
  155.              ; //一个分号相当于执行一条空语句  
  156.           }  
  157.    }  
  158. }  
  159.   
  160.   
  161. void initial_myself()  //第一区 初始化单片机  
  162. {  
  163.   
  164.   TMOD=0x01;  //设置定时器0为工作方式1  
  165.   
  166.   
  167.   TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f  
  168.   TL0=0x2f;  
  169.   
  170.   
  171. }  
  172.   
  173. void initial_peripheral() //第二区 初始化外围  
  174. {  
  175.   EA=1;     //开总中断  
  176.   ET0=1;    //允许定时中断  
  177.   TR0=1;    //启动定时中断  
  178.   
  179. }   

总结陈词:

这节讲了74HC595的驱动程序,它是一次控制16个LED同时亮灭的,在实际中应用不太方便,如果我们想要像单片机IO口直接控制LED那样方便,我们该怎么编写程序呢?欲知详情,请听下回分解-----把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式。

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

已有0条评论

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

添加一条新评论

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

话题作者

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

x

畅学电子网订阅号