esp32通过74HC595控制16个LED灯

1. 74HC595介绍

74HC595是一个8位串行输入、并行输出的位移缓存器:并行输出为三态输出。在SCK 的上升沿,串行数据由数据脚(A)输入到内部的8位位移缓存器,并由Q7’输出,而并行输出则是在LCK的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值

芯片引脚图

2.思路分析

74HC595真值表

由真值表可知:

  1. 当移位寄存器时钟线为上升沿时,会获取当时数据引脚的数据 ,即SDA当时的电平状态,存入移位寄存器中,若 SER引脚为低电平,则从低位开始存储。如果SER引脚为高电平,则从高位开始存储。

  2. 由于移位寄存器只有八位,当数据超过8位时,多出的位数将会通过SQH串行输出,一般将SQH与下一级的数据输入引脚(SDA)相连,实现级联。

  3. 当存储寄存器时钟线为上升沿时,会将移位寄存器中的数据存储到存储寄存器当中。

  4. 当OE脚为低电平时,会将存储寄存器中的数据输出至总线,通过存储寄存器的数据实现对 QA-QH的控制。

根据以上信息,可以得出结论,如果要控制QA-QH的电平输出,控制分为四个步骤:

  1. SDA输入数据。

  2. SCK给一个上升沿,将SDA的一个数据移入移位寄存器,循环八次。

  3. RCK给一个上升沿,将移位寄存器的数据转存到存储寄存器。

  4. OE脚置低,将存储寄存器中的数据输入至数据总线

3. 代码

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>


#include "mdf_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "gpio.h"
#include "stdint.h"
#define SCK_GPIO_PIN	    13	 // 移位寄存器时钟线引脚                  			        
#define RCK_GPIO_PIN	    15   //存储寄存器时钟线引脚
#define SDA_GPIO_PIN        2    //数据引脚

#define _74HC595_LEVEL       2    //74HC595级联数

#define HC595_SCK_Low()      gpio_set_level(SCK_GPIO_PIN,0)     //SCK置低
#define HC595_SCK_High()     gpio_set_level(SCK_GPIO_PIN,1)    //SCK置高

#define HC595_RCK_Low()      gpio_set_level(RCK_GPIO_PIN,0)   //RCK置低
#define HC595_RCK_High()     gpio_set_level(RCK_GPIO_PIN,1)   //RCK置高

#define HC595_Data_Low()      gpio_set_level(SDA_GPIO_PIN,0)  //输入低电平
#define HC595_Data_High()     gpio_set_level(SDA_GPIO_PIN,1)  //输入高电平

/*
@brief : 74HC595控制引脚初始化
*/
void _74hc595_init(void)   
{
         gpio_config_t io_conf = {
        .intr_type = GPIO_PIN_INTR_DISABLE,
        .mode = GPIO_MODE_OUTPUT,
        .pin_bit_mask = (1ULL<<SCK_GPIO_PIN)|(1ULL<<RCK_GPIO_PIN)|(1ULL<<SDA_GPIO_PIN),  
        .pull_down_en = 1,
        .pull_up_en = 0,
    };
    gpio_config(&io_conf);
    HC595_SCK_Low();
    HC595_RCK_Low();
    HC595_Data_Low();
}


/*
 @brief:74HC595输出锁存 使能 
*/
void HC595_Save(void) 
{
	/**  步骤3:RCK产生一个上升沿,移位寄存器的数据移入存储寄存器  **/
	HC595_RCK_Low();   // 将RCK拉低
	delay(10);
	HC595_RCK_High();  // 再将RCK拉高,RCK即可产生一个上升沿
}

/***
 *74HC595 发送一个字节 
 *即往74HC595的SDA引脚发送一个字节
*/
void HC595_Send_Byte(uint8_t byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)  //一个字节8位,传输8次,一次一位,循环8次,刚好移完8位
	{
	  /****  步骤1:将数据传到DS引脚    ****/
	  	HC595_SCK_Low();   // SCK拉低
		if (byte & 0x80){      //先传输高位,通过与运算判断第八是否为1
			HC595_Data_High();    //如果第八位是1,则与 595 DS连接的引脚输出高电平
		}else{                  //否则输出低电平
			HC595_Data_Low();
		}
		
		/*** 步骤2:SCK每产生一个上升沿,当前的bit就被送入移位寄存器 ***/
		byte <<= 1;		// 左移一位,将低位往高位移,通过	if (byte & 0x80)判断低位是否为1
		HC595_SCK_High();  // SHCP拉高, SHCP产生上升沿	
	}
}
/**
 *发送多个字节
 *便于级联时数据的发送
 *级联N级,就需要发送N个字节控制HC595
***/
void HC595_Send_Multi_Byte(uint8_t *data, uint16_t len)
{
	uint8_t i;
	// len 个字节
	for (i = 0; i < len; i ++ ) {
		HC595_Send_Byte(data[i]);
		debug_i("leve  :%d  data:%x",i,data[i]);
	}
	HC595_Save();
	
}

/*
@brief: 测试函数
*/
void _74hc595_test(void)
{
    uint8_t place=0;    //级联位置
    uint8_t floor=0;    //级联层级
    uint8_t ele[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
	while(1)
	{
        uint8_t led_Pos_Buf[_74HC595_LEVEL]; 
		int max_num=_74HC595_LEVEL*8;
		for (int i=1;i<num+1;i++){
            vTaskDelay(300);  //延时500毫秒
			memset(ele_Pos_Buf,0,_74HC595_LEVEL);
            floor=(i-1)/8;
			if(0!=i%8){
            	place=i%8-1;
			}else{
				place=7;
			}
			
            ele_Pos_Buf[_74HC595_LEVEL-floor-1] = ele[7-place];     
			debug_w("floor :%d  place:%d ",floor+1,place);
            HC595_Send_Multi_Byte(ele_Pos_Buf,_74HC595_LEVEL);//将当前数据发送到595
		}
	}
}


  • 9
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值