第17节:两片联级74HC595驱动16个LED灯的基本驱动程序时间:2015-07-2913赞0评论关键字:单片机驱动程序[导读]从业将近十年!手把手教你单片机程序框架第17讲:开场白:上一节讲了如何把矩阵键盘翻译成独立按键的处理方式。这节讲74HC595的驱动程序。要教会大家两个知识点:第一点:朱兆祺的学习板是用74HC595控制LED,因此可以从业将近十年!手把手教你单片机程序框架第17讲:开场白:上一节讲了如何把矩阵键盘翻译成独立按键的处理方式。这节讲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)源代码讲解如下:#includeREG52.H#defineconst_time_level200voidinitial_myself();voidinitial_peripheral();voiddelay_short(unsignedintuiDelayShort);voiddelay_long(unsignedintuiDelaylong);voidled_flicker();voidhc595_drive(unsignedcharucLedStatusTemp16_09,unsignedcharucLedStatusTemp08_01);voidT0_time();//定时中断函数/*注释一:*朱兆祺的学习板是用74HC595控制LED,因此可以直接把595的OE引脚接地。如果在工控中,用来控制继电器,*那么此芯片的片选脚OE不要为了省一个IO口而直接接地,否则会引起上电瞬间继电器莫名其妙地动作。*为了解决这个问题,OE脚应该用一个IO口单独驱动,并且千万要记住,此IO必须接一个15K左右的*上拉电阻,然后在程序刚上电运行时,先把OE置高,并且尽快把所有的74HC595输出口置低,然后再把OE置低.*当然还有另外一种解决办法,就是用一个10uF的电解电容跟一个100K的下拉电阻,组成跟51单片机外围复位电路原理*一样的电路,连接到OE口,这样确保上电瞬间OE口有一小段时间是处于高电平状态,在此期间,*尽快通过软件把74hc595的所有输出口置低。*/sbithc595_sh_dr=P2^3;sbithc595_st_dr=P2^4;sbithc595_ds_dr=P2^5;unsignedcharucLedStep=0;//步骤变量unsignedintuiTimeCnt=0;//统计定时中断次数的延时计数器voidmain(){initial_myself();delay_long(100);initial_peripheral();while(1){led_flicker();}}/*注释二:*两个联级74HC595的工作过程:*每个74HC595内部都有一个8位的寄存器,两个联级起来就有两个寄存器。ST引脚就相当于一个刷新*信号引脚,当ST引脚产生一个上升沿信号时,就会把寄存器的数值输出到74HC595的输出引脚并且锁存起来,*DS是数据引脚,SH是把新数据送入寄存器的时钟信号。也就是说,SH引脚负责把数据送入到寄存器里,ST引脚*负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。*/voidhc595_drive(unsignedcharucLedStatusTemp16_09,unsignedcharucLedStatusTemp08_01){unsignedchari;unsignedcharucTempData;hc595_sh_dr=0;hc595_st_dr=0;ucTempData=ucLedStatusTemp16_09;//先送高8位for(i=0;i8;i++){if(ucTempData=0x80)hc595_ds_dr=1;elsehc595_ds_dr=0;hc595_sh_dr=0;//SH引脚的上升沿把数据送入寄存器delay_short(15);hc595_sh_dr=1;delay_short(15);ucTempData=ucTempData1;}ucTempData=ucLedStatusTemp08_01;//再先送低8位for(i=0;i8;i++){if(ucTempData=0x80)hc595_ds_dr=1;elsehc595_ds_dr=0;hc595_sh_dr=0;//SH引脚的上升沿把数据送入寄存器delay_short(15);hc595_sh_dr=1;delay_short(15);ucTempData=ucTempData1;}hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来delay_short(15);hc595_st_dr=1;delay_short(15);hc595_sh_dr=0;//拉低,抗干扰就增强hc595_st_dr=0;hc595_ds_dr=0;}voidled_flicker()////第三区LED闪烁应用程序{switch(ucLedStep){case0:if(uiTimeCnt=const_time_level)//时间到{uiTimeCnt=0;//时间计数器清零hc595_drive(0x55,0x55);ucLedStep=1;//切换到下一个步骤}break;case1:if(uiTimeCnt=const_time_level)//时间到{uiTimeCnt=0;//时间计数器清零hc595_drive(0xaa,0xaa);ucLedStep=0;//返回到上一个步骤}break;}}voidT0_time()interrupt1{TF0=0;//清除中断标志TR0=0;//关中断if(uiTimeCnt0xffff)//设定这个条件,防止uiTimeCnt超范围。{uiTimeCnt++;//累加定时中断的次数,}TH0=0xf8;//重装初始值(65535-2000)=63535=0xf82fTL0=0x2f;TR0=1;//开中断}voiddelay_short(unsignedintuiDelayShort){unsignedinti;for(i=0;iuiDelayShort;i++){;//一个分号相当于执行一条空语句}}voiddelay_long(unsignedintuiDelayLong){unsignedinti;unsignedintj;for(i=0;iuiDelayLong;i++){for(j=0;j500;j++)//内嵌循环的空指令数量{;//一个分号相当于执行一条空语句}}}voidinitial_myself()//第一区初始化单片机{TMOD=0x01;//设置定时器0为工作方式1TH0=0xf8;//重装初始值(65535-2000)=63535=0xf82fTL0=0x2f;}voidinitial_peripheral()//第二区初始化外围{EA=1;//开总中断ET0=1;//允许定时中断TR0=1;//启动定时中断}总结陈词:这节讲了74HC595的驱动程序,它是一次控制16个LED同时亮灭的,在实际中应用不太方便,如果我们想要像单片机IO口直接控制LED那样方便,我们该怎么编写程序呢?欲知详情,请听下回分解-----把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式。