74HC595芯片组成测试工具_流水灯

使用环境是由于我公司生产的运动控制卡需要连接光电传感器,PCBA出来后需要检测,运动控制卡内部是由光电隔离再连接到单片机。如此需要检测电路板电路是否有无虚焊,器件是否能正常工作。如果点击I/O 口就很费时间。由此就需要借助外部的测试工具快速检测。(运动控制卡光耦发光二极管端接地即可点亮)

运动控制卡大概的连接关系
在这里插入图片描述

PCB布局部分

正面
在这里插入图片描述
背面
在这里插入图片描述

芯片手册说明

灯分为三组。每一个通道使用两个595芯片,运行状态是每一个通道同时亮起OUT1。按顺序逐个点亮直到OUT16结束,再以OUT1开始如此的循环,周而复始。旁边的接口可连接被测件。即可检测器件的好坏。

芯片介绍
74HC595A 是一款高速 CMOS 8 位串行移位寄存器,带有存储寄存器和低电平及高阻输出。移位寄存器和存储寄存器分别采用单独的时钟。在 SCK 的上升沿,数据发生移位,而在 RCK 的高电平时间内,数据从每个寄存器中传送到存储寄存器。移位寄存器带有一个串行输入(SER)端和一个串行标准输出(Q7’)端,用于级联。74HC595A 存储寄存器带有 8 个总线驱动输出,数据输出方式为低电平及高阻态。

在这里插入图片描述
在这里插入图片描述

芯片工作原理

由14口接单片机输入信号如00010001,之后信号存入移位寄存器,再通过时钟转换到锁存器中运行,最终通过
Q0 ~ Q7(00010001)八个引脚进行输出

在这里插入图片描述

第一步:目的:将要准备输入的位数据移入74HC595数据输入端上。 方法:送位数据到_595。

第二步:目的:将位数据逐位移入74HC595,即数据串入
方法:SH_CP产生一上升沿,将DS上的数据移入74HC595移位寄存器中,先送低位,后送高位。

第三步:目的:并行输出数据。即数据并出 方法:ST_CP产生一上升沿,将由DS上已移入数据寄存器中的数据 送入到输出锁存器。

74HC595级联说明

QH’: 级联输出端。将它接下一个74HC595芯片的DS引脚。
SER: 串行数据输入端,级联的话接上一级的Q7’。

在这里插入图片描述

电路原理图部分

在这里插入图片描述

代码部分

595驱动核心部分

/**************************************
函数名:74HC595函数初始化
调用:SerialSend();
参数:传递8进制数据
返回值:无
结果:
备注:
***************************************/
 
static void SerialSend(unsigned char ch)                 		  //--- 串并转换函数 ---  
{
  unsigned char i;
  
  for(i=8;i>0;i--)
    {
      if(0 == (ch & (1 << 7)))
				DAT = 0;                       			    	 //--- 高位为0则输出0 ---
      else 
			DAT = 1;                                           //--- 否则输出1 ---
      CLK = 1;                                         		   //--- 产生一个时钟 ---
      _nop_(); 
			CLK = 0;
      _nop_(); 
			ch <<= 1;                                      	   //--- 左移1位 ---
    }
}

static void HC595_CS(void) 
{
	/**  步骤3:STCP产生一个上升沿,移位寄存器的数据移入存储寄存器  **/
	LCK=0;      // 将STCP拉低
	_nop_(); 
//	_nop_();     // 适当延时
	LCK=1;      // 再将STCP拉高,STCP即可产生一个上升沿
//	_nop_();
	_nop_(); 
}

static void HC595_Send_Multi_Byte(u8 *dat, u16 len)
{
	u8 i;
	for (i = 0; i < len; i ++ ) // len 个字节
	{
		SerialSend(dat[i]);
	}
	
	HC595_CS(); //先把所有字节发送完,再使能输出
}

全部代码

#include "reg52.h"
#include "intrins.h"
//#define  unsigned char u16;
//#define  unsigned int u8;
#define MAIN_Fosc		11059200L	//定义主时钟
//LED指示灯
sbit LED=P3^6;

/**********************
595芯片引脚别名定义
***********************/			
sbit DAT=P1^0;
sbit CLK=P1^3;
sbit LCK=P1^2;
sbit SRCLR=P1^1;
sbit KEY=P5^4; 	   //用户按键RES用IO口P54

u8 pos; // led位置
u8 Led_Pos_Buf[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //存储要发送的指令字节
u8 LED_G;//按钮按下切换状态
//第pos个led亮: 1     2    3      4    5     6     7     8
//u8 Led[32] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, //控制第二级74HC595
//							 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //第一级的led全灭
//							 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //第二级的led全灭
//							 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//控制第一级74HC595	


//u8 Led[16] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000};//控制第一级74HC595	
//u8 Led[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//控制第一级74HC595	
//u8 Led[16] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//控制第一级74HC595	
u8 Led[16] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF,0x7F,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//控制第一级74HC595	
/**************************************
函数名:74HC595函数初始化
调用:SerialSend();
参数:传递8进制数据
返回值:无
结果:
备注:
***************************************/
 
static void SerialSend(unsigned char ch)                   //--- 串并转换函数 ---  
{
  unsigned char i;
  
  for(i=8;i>0;i--)
    {
      if(0 == (ch & (1 << 7)))
				DAT = 0;                       				 //--- 高位为0则输出0 ---
      else 
			DAT = 1;                                        //--- 否则输出1 ---
      CLK = 1;                                         	    //--- 产生一个时钟 ---
      _nop_(); 
			CLK = 0;
      _nop_(); 
			ch <<= 1;                                      	   //--- 左移1位 ---
    }
}

static void HC595_CS(void) 
{
	/**  步骤3:STCP产生一个上升沿,移位寄存器的数据移入存储寄存器  **/
	LCK=0;      // 将STCP拉低
	_nop_(); 
//	_nop_();     // 适当延时
	LCK=1;      // 再将STCP拉高,STCP即可产生一个上升沿
//	_nop_();
	_nop_(); 
}

static void HC595_Send_Multi_Byte(u8 *dat, u16 len)
{
	u8 i;
	for (i = 0; i < len; i ++ ) // len 个字节
	{
		SerialSend(dat[i]);
	}
	
	HC595_CS(); //先把所有字节发送完,再使能输出
}


static void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 43;
	j = 6;
	k = 203;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

static void  delay_ms(unsigned char ms)
{
     unsigned int i;
		 do
		 {
	      i = MAIN_Fosc / 13000;
				while(--i)	;   //14T per loop
     }
		 while(--ms);
}

void KEY_Scan(void)
{
			if(KEY == 0)
	  {
	    delay_ms(10);
	    if(KEY== 0)	     //按键按下
	    {
		    while(KEY == 0);   //等待按键释放
        LED_G=1;	         //熄灭绿色指示灯
	    }
	  }
	
}


void main()
{
		P0M1 &= 0x00;	P0M0 &= 0xFF;	  //设置P0.5~P0.7为准双向口
		P1M1 = 0x00;	P1M0 = 0xFF;	  //设置P0.5~P0.7为准双向口
	
    P5M0 = 0x10;
    P5M1 = 0x10;
		
    SRCLR  = 1;
		LED_G  = 0;
	

				Led_Pos_Buf[5] = 0x00;//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				Led_Pos_Buf[4] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[3] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[2] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[1] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[0] = 0x00; //存放第二级74HC595的数据
				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595		
				Delay1000ms;	
				Delay1000ms;
				Delay1000ms;
				Delay1000ms;
				Led_Pos_Buf[5] = 0xFF;//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				delay_ms(500);	
				Led_Pos_Buf[4] = 0xFF; //存放第二级74HC595的数据
				delay_ms(500);	
				Led_Pos_Buf[3] = 0xFF; //存放第二级74HC595的数据
				delay_ms(500);	
				Led_Pos_Buf[2] = 0xFF; //存放第二级74HC595的数据
				delay_ms(500);	
				Led_Pos_Buf[1] = 0xFF; //存放第二级74HC595的数据
				delay_ms(500);	
				Led_Pos_Buf[0] = 0xFF; //存放第二级74HC595的数据
				delay_ms(500);	
				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595		
				Delay1000ms;
				Delay1000ms;
				Delay1000ms;
				Delay1000ms;
				Led_Pos_Buf[5] = 0x00;//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				Led_Pos_Buf[4] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[3] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[2] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[1] = 0x00; //存放第二级74HC595的数据
				Led_Pos_Buf[0] = 0x00; //存放第二级74HC595的数据
				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595	
				Delay1000ms;
				Delay1000ms;
				Delay1000ms;
				Delay1000ms;
	
	
    while (1)
		{
			KEY_Scan();
			if (LED_G==0)
			{
				for (pos = 0; pos < 8; pos ++) //第pos个灯,实现流水灯效果
			{
				delay_ms(500);	
				Led_Pos_Buf[5] = Led[pos];//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				delay_ms(500);
				Led_Pos_Buf[4] = Led[pos+8]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[3] = Led[pos]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[2] = Led[pos+8]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[1] = Led[pos]; //存放第二级74HC595的数据

				Led_Pos_Buf[0] = Led[pos+8]; //存放第二级74HC595的数据

				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595
					
			}
			for (pos = 0; pos < 8; pos ++) //第pos个灯,实现流水灯效果
			{
				delay_ms(500);
				Led_Pos_Buf[5] = Led[pos+8];//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				delay_ms(500);
				Led_Pos_Buf[4] = Led[pos]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[3] = Led[pos+8]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[2] = Led[pos]; //存放第二级74HC595的数据
				delay_ms(500);
				Led_Pos_Buf[1] = Led[pos+8]; //存放第二级74HC595的数据
				Led_Pos_Buf[0] = Led[pos]; //存放第二级74HC595的数据

				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595			
			}
			}
			else
			{
				for (pos = 0; pos < 8; pos ++) //第pos个灯,实现流水灯效果
			{
				delay_ms(500);
				Led_Pos_Buf[5] = Led[pos];//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				Led_Pos_Buf[4] = Led[pos+8]; //存放第二级74HC595的数据
				Led_Pos_Buf[3] = Led[pos]; //存放第二级74HC595的数据
				Led_Pos_Buf[2] = Led[pos+8]; //存放第二级74HC595的数据
				Led_Pos_Buf[1] = Led[pos]; //存放第二级74HC595的数据
				Led_Pos_Buf[0] = Led[pos+8]; //存放第二级74HC595的数据
				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595
					
			}
				for (pos = 0; pos < 8; pos ++) //第pos个灯,实现流水灯效果
			{
				delay_ms(500);
				Led_Pos_Buf[5] = Led[pos+8];//存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]
				Led_Pos_Buf[4] = Led[pos]; //存放第二级74HC595的数据
				Led_Pos_Buf[3] = Led[pos+8]; //存放第二级74HC595的数据
				Led_Pos_Buf[2] = Led[pos]; //存放第二级74HC595的数据
				Led_Pos_Buf[1] = Led[pos+8]; //存放第二级74HC595的数据
				Led_Pos_Buf[0] = Led[pos]; //存放第二级74HC595的数据
				HC595_Send_Multi_Byte(Led_Pos_Buf,6);//将当前数据发送到595		
				
			}
					
			}
		}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢谢~谢先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值