两片联级74HC595驱动16个LED灯的基本驱动程序

/*74HC595使用方法
74HC595的数据端
QA--QH:八位并行输出端,可以直接控制8个输出位。
Q7S:级联输出端。将它接下一个595的DS端。
DS:串行数据输入端,级联的话接上一级的Q7S。
74HC595的控制端说明
/MR(10脚):低电平时将移位寄存器的数据清零。通常我将它接Vcc。
SH_CP(11脚):上升沿时数据寄存器的数据移位。Q0->Q1->Q2-->Q3-->...-->Q7;下降沿移位寄存器数据不变。(脉冲宽度:5V时,大于几十纳秒就行了。我通常都选微秒级)
ST_CP(12脚):上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。通常我将ST_CP置为低电平,当移位结束后,在ST_CP端产生一个正脉冲(5V时,大于几十纳秒就行了。我通常都选微秒级),更新显示数据。
/OE(13脚):高电平时禁止输出(高阻态)。如果单片机的引脚不紧张,用一个引脚控制它,可以方便地产生闪烁和熄灭效果。比通过数据端移位控制要省时省力。*/

/*8个LED灯交替闪烁*/
#include "REG52.H"
#define const_time_level 200
void initial_myself();
void initial_peripheral();
void delay_short(unsigned int uiDelayShort);
void delay_long(unsigned int uiDelayLong);
void led_flicker();
void hc595_drive(unsigned char ucLedStatusTemp08_01); 
void T0_time(); //定时中断函数
sbit hc595_sh_dr=P3^6;  //上升沿数据寄存器移位,QA->QB;下降沿不变
sbit hc595_st_dr=P3^5;  //上升沿移位寄存器数据进入数据存储寄存器,下降沿数据存储寄存器不变。当移位完后,ST会产生正脉冲,更新显示数据
sbit hc595_ds_dr=P3^4;  //串行数据输入端,联级的话接上一级Q7S
unsigned char ucLedStep=0; //步骤变量
unsigned int uiTimeCnt=0; //统计定时中断次数的延时计数器
void main()
{
 initial_myself();
 delay_long(100);
 initial_peripheral();
 while(1)
 {
  led_flicker();
 }
}
void hc595_drive(unsigned char ucLedStatusTemp08_01)  //1-8位
{
 unsigned char i;
 unsigned char ucTempData;
 hc595_sh_dr=0;
 hc595_st_dr=0;
 
 ucTempData=ucLedStatusTemp08_01; //送8位
 for(i=0;i<8;i++)
 {
  if(ucTempData>=0x80) //更新一次数据,移一次位
   hc595_ds_dr=1;  //串行数据输入,如果是多片联级的话,更新一次,输入一次数据。(我的单片机只用了一个74HC595芯片)
  else
   hc595_ds_dr=0;
  
  hc595_sh_dr=0; 
  delay_short(15);
  hc595_sh_dr=1;  //SH引脚的上升沿把数据送入寄存器
  delay_short(15);
  
  ucTempData=ucTempData<<1;  //左移一位
 }
 
 hc595_st_dr=0;
 delay_short(15);
 hc595_st_dr=1;  //ST引脚负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。上升沿时更新显示数据。
 delay_short(15);
 
 hc595_sh_dr=0; //拉低,抗干扰就增强
 hc595_st_dr=0;
 hc595_ds_dr=0;
}
void led_flicker() // 第三区  LED闪烁应用程序
{
 switch(ucLedStep)
 {
  case 0:
   if(uiTimeCnt>const_time_level) //时间到
   {
    uiTimeCnt=0;
    hc595_drive(0x55);  // 0101  0101
    ucLedStep=1; //切换到下一步骤
   }
   break;
   
  case 1:
   if(uiTimeCnt>const_time_level)
   {
    uiTimeCnt=0;
    hc595_drive(0xaa);  // 1010  1010
    ucLedStep=0; //返回到上一步骤
   }
   break;
 }
void T0_time() interrupt 1
{
 TF0=0; //清除中断标志
 TR0=0; //关中断
 if(uiTimeCnt<0xffff) //设定这个条件,防止uiTimeCnt超范围
 {
  uiTimeCnt++; //累加定时中断的次数
 }
 
 TH0=0xf8;
 TL0=0x2f;
 TR0=1;  //开中断
}
void delay_short(unsigned int uiDelayShort)
{
 unsigned int i;
 for(i=0;i<uiDelayShort;i++)
  ;
}
void delay_long(unsigned int uiDelayLong)
{
 unsigned int i;
 unsigned int j;
 for(i=0;i<uiDelayLong;i++)
  for(j=0;j<500;j++)
   ;
}
void initial_myself()  //第一区  初始化单片机
{
 TMOD=0x01;
 TH0=0xf8;
 TL0=0x2f;
}
void initial_peripheral()
{
 EA=1;
 ET0=1;
 TR0=1; 
}
 
原文地址:https://www.cnblogs.com/TheFly/p/12006744.html