RT-Thread Studio学习 74HC595级联驱动多路继电器

74HC595详细资料及使用方法参照以下文章:

https://vuko-wxh.blog.csdn.net/article/details/80500046

https://recclay.blog.csdn.net/article/details/78245642

https://snmplink.blog.csdn.net/article/details/102729009

https://blog.csdn.net/k1ang/article/details/80012686

https://blog.csdn.net/yangmolulu/article/details/79242973

https://blog.csdn.net/k1ang/article/details/80012463

https://blog.csdn.net/k1ang/article/details/80397173

项目使用8片74HC595级联控制64个继电器动作,每片74HC595控制8个继电器。

74HC595的级联电路如下:

74HC595的级联

 

继电器阵列

                                                                IO控制引脚

代码部分如下:

my_74hc595.h:

#ifndef APPLICATIONS_MY_74HC595_H_
#define APPLICATIONS_MY_74HC595_H_


#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define HC595_RCLK  GET_PIN(B,12)//存储寄存器时钟输入引脚
#define HC595_SCLK  GET_PIN(B,13)//移位寄存器时钟引脚
#define HC595_DIO   GET_PIN(B,15)//数据输入
#define HC595_NOE   GET_PIN(C,6) //输出使能控制,低电平使能输出


#define RT_HC595_RCLK_HIGH(x)  x?rt_pin_write(HC595_RCLK, PIN_HIGH):rt_pin_write(HC595_RCLK, PIN_LOW)
#define RT_HC595_SCLK(x)       x?rt_pin_write(HC595_SCLK, PIN_HIGH):rt_pin_write(HC595_SCLK, PIN_LOW)
#define RT_HC595_DIO(x)        x?rt_pin_write(HC595_DIO, PIN_HIGH):rt_pin_write(HC595_DIO, PIN_LOW)
#define RT_HC595_NOE(x)        x?rt_pin_write(HC595_NOE, PIN_HIGH):rt_pin_write(HC595_NOE, PIN_LOW)



void my_hc595_pin_init(void);
void BK1_On_test(void);
void BK2_On_test(void);
void BK3_On_test(void);
void BK4_On_test(void);
void BK5_On_test(void);
void BK6_On_test(void);
void BK7_On_test(void);
void BK8_On_test(void);
void BK1_Off_test(void);
void BK2_Off_test(void);
void BK3_Off_test(void);
void BK4_Off_test(void);
void BK5_Off_test(void);
void BK6_Off_test(void);
void BK7_Off_test(void);
void BK8_Off_test(void);
void All_BK_On_test(void);
void All_BK_Off_test(void);

#endif /* APPLICATIONS_MY_74HC595_H_ */

my_74hc595.c:

#include "my_74hc595.h"

static rt_thread_t tid_hc595 = RT_NULL;

//hc595处理线程
//此线程实现64个继电器间隔1s吸合断开
static void thread_hc595_entry(void )
{

    while (1)
    {
        All_BK_Off_test();
        rt_thread_mdelay(1000);
        All_BK_On_test();
        rt_thread_mdelay(1000);
    }
}

//初始化hc595,并创建hc595线程
int thread_hc595(void)
{

    // 初始化HC595
//    my_hc595_pin_init();//mian中已初始化

    /* 创建线程  */
    tid_hc595 = rt_thread_create("thread hc595",
                                thread_hc595_entry,
                                NULL,
                                512,
                                8, 5);

    if (tid_hc595 != RT_NULL)
    {
        rt_thread_startup(tid_hc595);
        rt_kprintf("tid_hc595 run!\r\n");
    }
    rt_thread_mdelay(100);

    return 0;
}
INIT_APP_EXPORT(thread_hc595);


//控制继电器状态的buf,将64个继电器分为8组,每组8个继电器
//buf中存放向74HC595传送的数据,0xFF为继电器全部吸合,0x00为继电器全部断开
uint8_t BK1_on_buf[1] = {0xAA};
uint8_t BK2_on_buf[2] = {0xff};
uint8_t BK3_on_buf[3] = {0xff};
uint8_t BK4_on_buf[4] = {0xff};
uint8_t BK5_on_buf[5] = {0xff};
uint8_t BK6_on_buf[6] = {0xff};
uint8_t BK7_on_buf[7] = {0xff};
uint8_t BK8_on_buf[8] = {0xff};
uint8_t All_BK_on_buf[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};


uint8_t BK1_off_buf[1] = {0x00};
uint8_t BK2_off_buf[2] = {0x00};
uint8_t BK3_off_buf[3] = {0x00};
uint8_t BK4_off_buf[4] = {0x00};
uint8_t BK5_off_buf[5] = {0x00};
uint8_t BK6_off_buf[6] = {0x00};
uint8_t BK7_off_buf[7] = {0x00};
uint8_t BK8_off_buf[8] = {0x00};
uint8_t All_BK_off_buf[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

/***
 *74HC595 IO初始化
 *时钟、数据、使能脚
*/
void my_hc595_pin_init(void)
{
    rt_pin_mode(HC595_RCLK, PIN_MODE_OUTPUT);//初始化IO
    rt_pin_mode(HC595_SCLK, PIN_MODE_OUTPUT);//初始化IO
    rt_pin_mode(HC595_DIO, PIN_MODE_OUTPUT);//初始化IO
    rt_pin_mode(HC595_NOE, PIN_MODE_OUTPUT);//初始化IO

    //初始化输出低电平
    rt_pin_write(HC595_RCLK, 0);
    rt_pin_write(HC595_SCLK, 0);
    rt_pin_write(HC595_NOE , 0);

    //IO设置成输出模式
    //此处使用8个引脚直接控制64个继电器之外的其他继电器
    rt_pin_mode(AC1_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC2_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC3_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC4_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC5_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC6_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC7_Ctr,PIN_MODE_OUTPUT);
    rt_pin_mode(AC8_Ctr,PIN_MODE_OUTPUT);

    rt_kprintf("relay_IO_Init Success!\r\n");
}



/***
 *74HC595 发送一个字节
 *即往74HC595的DS引脚发送一个字节
*/
void HC595_Send_Byte(uint8_t byte)
{
    uint8_t i;
    for (i = 0; i < 8; i ++)  //一个字节8位,传输8次,一次一位,循环8次,刚好移完8位
    {
      /****  步骤1:将数据传到DS引脚    ****/
        if (byte & 0x80)          //先传输高位,通过与运算判断第八是否为1
        {
            RT_HC595_DIO(1);      //如果第八位是1,则与 595 DS连接的引脚输出高电平
        }
        else
        {
            RT_HC595_DIO(0);      //否则输出低电平
        }
        /*** 步骤2:SHCP每产生一个上升沿,当前的bit就被送入移位寄存器 ***/
        RT_HC595_SCLK(0);   // SHCP拉低
        rt_thread_delay(1);           // 适当延时
        //rt_hw_us_delay(10);
        RT_HC595_SCLK(1);   // SHCP拉高, SHCP产生上升沿
        rt_thread_delay(1); // RT_TICK_PER_SECOND 1000
        //rt_hw_us_delay(10);

        byte <<= 1;     // 左移一位,将低位往高位移,通过  if (byte & 0x80)判断低位是否为1
    }
}


/**
 *74HC595输出锁存 使能
**/
void HC595_CS(void)
{
    /**  步骤3:STCP产生一个上升沿,移位寄存器的数据移入存储寄存器  **/
    RT_HC595_RCLK_HIGH(0);   // 将STCP拉低
    rt_thread_delay(1);      // 适当延时
//    rt_hw_us_delay(10);
    RT_HC595_RCLK_HIGH(1);   // 再将STCP拉高,STCP即可产生一个上升沿
    rt_thread_delay(1);
//    rt_hw_us_delay(10);
}


/**
 *发送多个字节
 *便于级联时数据的发送
 *级联N级,就需要发送N个字节控制HC595
***/
void HC595_Send_Multi_Byte(uint8_t *data, uint16_t len)
{
    uint8_t i;
    for (i = 0; i < len; i ++ ) // len 个字节
    {
        HC595_Send_Byte(data[i]);
    }

    HC595_CS(); //先把所有字节发送完,再使能输出
}



//以下函数为测试每组继电器吸合状态
void BK1_On_test(void)
{
    HC595_Send_Multi_Byte(BK1_on_buf,1);
}
MSH_CMD_EXPORT(BK1_On_test, bk1_relay_on_test);//自定义msh命令
//FINSH_FUNCTION_EXPORT_ALIAS(BK1_On_test, B1_on, bk1_relay_on_test);//自定义命令重命名,命令导出到 msh 模式
//__cmd_
void BK2_On_test(void)
{
    HC595_Send_Multi_Byte(BK2_on_buf,2);
}
MSH_CMD_EXPORT(BK2_On_test, bk2_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK2_On_test, B2_on, bk2_relay_on_test);//自定义命令重命名,命令导出到 msh 模式


void BK3_On_test(void)
{
    HC595_Send_Multi_Byte(BK3_on_buf,3);
}
MSH_CMD_EXPORT(BK3_On_test, bk3_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK3_On_test, B3_on, bk3_relay_on_test);//自定义命令重命名,命令导出到 msh 模式


void BK4_On_test(void)
{
    HC595_Send_Multi_Byte(BK4_on_buf,4);
}
MSH_CMD_EXPORT(BK4_On_test, bk4_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK4_On_test, B4_on, bk4_relay_on_test);//自定义命令重命名,命令导出到 msh 模式


void BK5_On_test(void)
{
    HC595_Send_Multi_Byte(BK5_on_buf,5);
}
MSH_CMD_EXPORT(BK5_On_test, bk5_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK5_On_test, B5_on, bk5_relay_on_test);//自定义命令重命名,命令导出到 msh 模式


void BK6_On_test(void)
{
    HC595_Send_Multi_Byte(BK6_on_buf,6);
}
MSH_CMD_EXPORT(BK6_On_test, bk6_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK6_On_test, B6_on, bk6_relay_on_test);//自定义命令重命名,命令导出到 msh 模式


void BK7_On_test(void)
{
    HC595_Send_Multi_Byte(BK7_on_buf,7);
}
MSH_CMD_EXPORT(BK7_On_test, bk7_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK7_On_test, B7_on, bk7_relay_on_test);//自定义命令重命名,命令导出到 msh 模式

void BK8_On_test(void)
{
    HC595_Send_Multi_Byte(BK8_on_buf,8);
}
MSH_CMD_EXPORT(BK8_On_test, bk8_relay_on_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK8_On_test, B8_on, bk8_relay_on_test);//自定义命令重命名,命令导出到 msh 模式



void All_BK_On_test(void)
{
    HC595_Send_Multi_Byte(All_BK_on_buf,8);
}
MSH_CMD_EXPORT(All_BK_On_test, All_BK_On_test);

//以下函数为测试每组继电器断开状态

void BK1_Off_test(void)
{
    HC595_Send_Multi_Byte(BK1_off_buf,1);
}
MSH_CMD_EXPORT(BK1_Off_test, bk1_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK1_Off_test, B1_on, bk1_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK2_Off_test(void)
{
    HC595_Send_Multi_Byte(BK2_off_buf,2);
}
MSH_CMD_EXPORT(BK2_Off_test, bk2_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK2_Off_test, B2_on, bk2_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK3_Off_test(void)
{
    HC595_Send_Multi_Byte(BK3_off_buf,3);
}
MSH_CMD_EXPORT(BK3_Off_test, bk3_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK3_Off_test, B3_on, bk3_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK4_Off_test(void)
{
    HC595_Send_Multi_Byte(BK4_off_buf,4);
}
MSH_CMD_EXPORT(BK4_Off_test, bk4_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK4_Off_test, B4_on, bk4_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK5_Off_test(void)
{
    HC595_Send_Multi_Byte(BK5_off_buf,5);
}
MSH_CMD_EXPORT(BK5_Off_test, bk5_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK5_Off_test, B5_on, bk5_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK6_Off_test(void)
{
    HC595_Send_Multi_Byte(BK6_off_buf,6);
}
MSH_CMD_EXPORT(BK6_Off_test, bk6_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK6_Off_test, B6_on, bk6_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK7_Off_test(void)
{
    HC595_Send_Multi_Byte(BK7_off_buf,7);
}
MSH_CMD_EXPORT(BK7_Off_test, bk7_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK7_Off_test, B7_on, bk7_relay_off_test);//自定义命令重命名,命令导出到 msh 模式

void BK8_Off_test(void)
{
    HC595_Send_Multi_Byte(BK8_off_buf,8);
}
MSH_CMD_EXPORT(BK8_Off_test, bk8_relay_off_test);
//FINSH_FUNCTION_EXPORT_ALIAS(BK8_Off_test, B8_on, bk8_relay_off_test);//自定义命令重命名,命令导出到 msh 模式


void All_BK_Off_test(void)
{
    HC595_Send_Multi_Byte(All_BK_off_buf,8);
}
MSH_CMD_EXPORT(All_BK_Off_test, All_BK_Off);


//IO口单独控制其他继电器
void BK10_All_On(void)
{
    RT_AC1_Ctr(1);
    RT_AC2_Ctr(1);
    RT_AC3_Ctr(1);
    RT_AC4_Ctr(1);
    RT_AC5_Ctr(1);
    RT_AC6_Ctr(1);
    RT_AC7_Ctr(1);
    RT_AC8_Ctr(1);
}
MSH_CMD_EXPORT(BK10_All_On, bk10_relay_on_test);

void BK10_All_Off(void)
{
    RT_AC1_Ctr(0);
    RT_AC2_Ctr(0);
    RT_AC3_Ctr(0);
    RT_AC4_Ctr(0);
    RT_AC5_Ctr(0);
    RT_AC6_Ctr(0);
    RT_AC7_Ctr(0);
    RT_AC8_Ctr(0);
}
MSH_CMD_EXPORT(BK10_All_Off, bk10_relay_off_test);

main.c

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "my_74hc595.h"

int main(void)
{

    LOG_D("ChannelCard Test!");
    LOG_D("System Clock information");
    LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());
    LOG_D("HCLK_Frequency   = %d", HAL_RCC_GetHCLKFreq());
    LOG_D("PCLK1_Frequency  = %d", HAL_RCC_GetPCLK1Freq());
    LOG_D("PCLK2_Frequency  = %d", HAL_RCC_GetPCLK2Freq());
    rt_kprintf("\r\n");
    my_hc595_pin_init();//初始化IO
    All_BK_Off_test();//关闭所有继电器
    while (1)
    {
        //LOG_D("Hello RT-Thread!");
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

示波器查看74HC595通信波形如下:

CH1为数据管脚(DS),CH2为 数据输入时钟(SHCP)

向74HC595写入0xAA:

 向两片74HC595分别写入0xFF和0x00:

 向8片74HC595写入0xFF:

8片74HC595控制64个继电器以1s间隔吸合断开:

 

 

 

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值