第11章 IO扩展-74HC595

第十一章 IO口扩展-74HC595

1. 导入

在前面的章节中,我们直接使用单片机的IO口扩展外围设备,我们已经学习了,如果仅仅要实现一个功能就要多个IO口,但是51单片机的IO口有限,所以本章要介绍一种扩展的方式-串转并(使用74HC595芯片)开发板板载 4 个 74HC595 芯片, 仅需单片机 3 个 IO 口即可扩展 32 个。

过本章的学习, 让大家学会使用 74HC595 芯片来扩展 IO 口。 本章所要实现的功能是: 通过 74HC595 模块控制 LED 点阵以一行循环滚动显示。

2. 74HC595介绍

我们会用就行,不必过多介绍,想要了解可以参考必备资料中的开发板芯片数据手册

3. 硬件设计

本章实验需要用到的硬件资源如下:

  • 16*16LED点阵模块

  • 74HC595模块

从图可知,74HC595模块内使用了四块74HC595芯片, 它们采用了级联方式,即 RCLK 和 SRCLK 管脚并联在一起, 并且 74HC595 ( A) 的输出 QH 非连接到 74HC595( B) 的串行输入口 SER, 而 74HC595( B) 的输出 QH 非又连接到 74HC595( C) 的串行输入口 SER, 依次类推。 并且每块芯片的输出端都连接到对应的端子上, 74HC595( A) 的输出连接到 J27 端子, 74HC595 ( B)的输出连接到 J32 端子, 74HC595( C)的输出连接到 LED 点阵前 8 列, 74HC595 ( D) 的输出连接到 LED 点阵后 8 列。

图上的 NEGx 是网络标号, 与 LED 点阵列相连。 74HC595 需要用到的控制管脚 RCLK、 SRCLK、 SER 并未直接连接到 51 单片机的 IO 上, 而是连接到 J24 端子上。(我们想通过单片机控制74HC595即控制LED点阵,选定单片机引脚与J24端子相连就行了)

要想控制 LED 点阵, 可以将单片机管脚按照 74HC595 芯片的通信时序要求来传输数据, 因为使用了 4 片 74HC595 芯片, A/B 两块控制点阵行 POS1-POS16, C/D两块控制点阵列 NEG1-NEG16。 这样即可控制 LED 点阵。 根据 LED 发光二极管导通原理,当阳极为高电平,阴极为低电平则点亮,否则熄灭。(行为 LED 发光二极管的阳极, LED 点阵的列则为发光二极管的阴极。)

所以我们要通过单片机发送4组数据,通过74HC595将这四组数据分配到对应输出从而控制LED点阵

4. 软件设计

本章所要实现的功能是: 通过 74HC595 模块控制 LED 点阵以一行循环滚动显示

#include <REGX52.H>

// 定义74HC595控制管脚
sbit SC = P3^6; // 串行输入时钟(SCK)
sbit RC = P3^5; // 存储寄存器时钟(RCK)
sbit SE = P3^4; // 串行数据输入(SER)

unsigned char ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; // 段码值

// 延时函数,ten_us=1时,大约延时10us
void delay_10us(unsigned int ten_us)
{
    while(ten_us--);    
}

// ms延时函数,ms=1时,大约延时1ms
void delay_ms(unsigned int ms)
{
    unsigned int i,j;
    for(i=ms;i>0;i--)
        for(j=110;j>0;j--);
}

/*
向74HC595写入4个字节的数据
dat1:对应74HC595(A)输出第1行-第8行
dat2:对应74HC595(B)输出第9行-第16行
dat3:对应74HC595(C)输出第1列-第8列
dat4:对应74HC595(D)输出第9列-第16列
*/
void hc595_write_data(unsigned char dat1, unsigned char dat2, unsigned char dat3, unsigned char dat4)
{
    unsigned char i = 0;

    // 详细分析dat4,其他同理
    for(i = 0; i < 8; i++) // 循环8次即可将一个字节写入寄存器中
    {
        SE = dat4 >> 7; // 将最高位赋给串行输入引脚
        dat4 <<= 1; // 将下一个数据移到最高位
        SC = 0; // 将串行输入时钟置0,准备将数据输入到74HC595寄存器
        delay_10us(1);
        SC = 1; // 将时钟引脚SC置为1,将数据从SE引脚输入到74HC595寄存器
        delay_10us(1); // 移位寄存器时钟上升沿将端口数据送入寄存器中    
    }

    // 分析同上,只是换了输出的地方
    for(i = 0; i < 8; i++)
    {
        SE = dat3 >> 7;
        dat3 <<= 1;
        SC = 0;
        delay_10us(1);
        SC = 1;
        delay_10us(1);    
    }

    for(i = 0; i < 8; i++)
    {
        SE = dat2 >> 7;
        dat2 <<= 1;
        SC = 0;
        delay_10us(1);
        SC = 1;
        delay_10us(1);    
    }

    for(i = 0; i < 8; i++)
    {
        SE = dat1 >> 7;
        dat1 <<= 1;
        SC = 0;
        delay_10us(1);
        SC = 1;
        delay_10us(1);    
    }

    // 这段代码将存储寄存器的时钟引脚RC置为1,然后立即置为0。
    // 这个操作是存储74HC595寄存器中之前输入的所有数据,使其在输出引脚上可用。
    RC = 1;
    delay_10us(1);
    RC = 0; // 存储寄存器时钟上升沿将前面写入到寄存器的数据输出    
}

// 控制一行逐渐滚动输出
void main()
{    
    unsigned char i = 0; // 计数器

    // A和B控制行,C和D控制列
    // 如果我们想一列滚动显示的,你应该知道怎么做的
    while(1)
    {        
        for(i = 0; i < 8; i++)
        {    
            hc595_write_data(ghc595_buf[i], 0, 0, 0); // 使74HC595(A)输出
            delay_ms(500); // 延时500ms    
        }
        for(i = 0; i < 8; i++)
        {    
            hc595_write_data(0,ghc595_buf[i],0,0); // 使74HC595(B)输出
            delay_ms(500);
        }                                    
    }        
}

5. 小结

代码还是比较简单易懂的, 首先定义好 74HC595 控制管脚, 以及点阵列控制口, 代码中重新定义了一个 ms 级延时函数 delay_ms, 该函数与前面 delay_10us类似, 都是利用循环占用 CPU 起到延时效果。

然后又定义了 74HC595 的控制函数hc595_write_data, 该函数完全按照 74HC595 的通信时序要求编写, 主要要注意的是 74HC595 是先传输字节的高位后传输低位, 所以需要将字节低位移动到高位传输, 在传输数据时, 要注意移位寄存器时钟和存储寄存器时钟的先后顺序, 将要写入的数据先传输到 74HC595 寄存器中, 即在准备好每位数据时要将 SRCLK进行一个上升沿变化, 此时即可将数据传输到寄存器内, 待循环 8 次即一个字节传输到寄存器中时, 就可以来一个存储时钟上升沿, 此时就可以将 74HC595 寄存器中的数据全部一次传输到 595 端口输出。

因为板载了 4 个 74HC595 芯片且级联,所以在函数入口有 4 个参数 dat1-dat4, 从函数中可看到, 第一个 for 循环中首先发送 dat4 数据, 然后再发送 dat3, 最后发送 dat1, 因为 595 是移位寄存器,可以理解为一开始发送的数据会被后面的数据向前推走, 通过 4 次 for 循环后dat4 就被移到了 74HC595(D)芯片处, dat3 就被移到了 74HC595(C)芯片处, dat2就被移到了 74HC595(B)芯片处, dat1 就被移到了 74HC595(A)芯片处。

最后就是在 main 函数中调用 74HC595 的控制函数, 将实验中要实现的效果数据写入进去,从而控制 LED 点阵的阳极和阴极。

这一章我们主要学习74HC595,它就是为了扩展IO口而生,并且可以多个串联,可以使用单片机一个IO口可以扩展出多个,我们简单了解一下就行,具体应用看本章工程和后续实验,我们会经常用到的,那个时候已经封装了具体怎么用倒不是很重要了,只需复制粘贴就行、

这个时候我们其实已经接触到相关寄存器操作了:

  • SER:串行数据输入,功能:如其名,可以输入数据给引脚

  • SCK:串行输入时钟,功能:先低再高,产生上升沿,可以将数据从SER引脚送到寄存器中

  • RCK:存储寄存器时钟,功能:先高再低,产生下降沿,将前面写入到寄存器的数据输出

如此形成闭环:SER->SCL->RCK


2024.6.26 第一次修订

2024.8.19 第二次修订,后期不再维护

posted @ 2024-08-20 09:23  hazy1k  阅读(85)  评论(0编辑  收藏  举报