【51单片机】74HC595芯片实现单片机 IO 扩展(串转并)和 LED点阵实验

目录

  • 单片机 IO 扩展(串转并)
    • 74HC595 芯片介绍
    • 硬件设计
    • 软件实验
    • 实验现象
  • LED点阵实验
    • LED 点阵介绍
    • 硬件设计
    • 软件设计
      • LED点阵(点亮一个点)
      • LED 点阵(显示数字)
      • LED 点阵(显示图像)

橙色

单片机 IO 扩展(串转并)

本章就来介绍另外一种 IO 口扩展方式-串转并, 使用的芯片是 74HC595。 开发板板载 1 个 74HC595 芯片, 仅需单片机 3 个 IO 口即可扩展 8 个, 如果需要还可以将 2 个 74HC595 级联扩展出 16 个 IO, 这就实现用少数 IO 资源控制多个设备。

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

为什么不直接通过51单片机的引脚来驱动LED矩阵呢?最重要的一点就是,通过74HC595芯片控制LED矩阵可以大大减少所需的引脚数量。74HC595是一个串行输入、并行输出的移位寄存器,使用三个引脚(时钟、数据、锁存)即可控制多个输出引脚。

74HC595 芯片介绍

74HC595 是一个 8 位串行输入、 并行输出的位移缓存器, 其中并行输出为三态输出(即高电平、 低电平和高阻抗) 。芯片管脚及功能说明如下:
在这里插入图片描述

不同人绘制芯片管脚图时可能命名不一样,但这没什么,主要是看芯片的管脚功能

  • 15 和 1 到 7 脚 QA–QH: 并行数据输出
  • 9 脚 QH 非: 串行数据输出
  • 10 脚 SCLR 非 : 低电平复位引脚
  • 11 脚 SCK : 移位寄存器时钟输入
  • 12 脚 RCK : 存储寄存器时钟输入
  • 13 脚 G 非 : 输出有效
  • 14 脚 SER : 串行数据输入

移位寄存器 (Shift Register):1、移位寄存器用于接收串行输入数据。数据通过一个引脚(通常是DS或SER)以位的形式输入芯片,按照顺序存储在移位寄存器中。通过时钟信号(通常是SHCP或SCK)的边沿触发,数据从输入端串行地移入寄存器。2、当新的数据输入时,原有数据会向左移位,为新的数据腾出空间。这种移位的过程可以持续进行,直到将所有位的数据加载到寄存器中。
存储寄存器 (Storage Register):1、存储寄存器用于存储移位寄存器中的数据,并在需要时并行输出到多个引脚。存储寄存器的更新是通过时钟信号(通常是STCP或RCK)的边沿触发的。当时钟信号触发时,移位寄存器中的数据被复制到存储寄存器中。2、存储寄存器的输出通过并行输出引脚(通常是Q0至Q7)完成。每个输出引脚对应存储寄存器中的一个位,它们可以设置为高电平、低电平或高阻抗状态。

74HC595 是具有 8 位移位寄存器和一个存储器, 三态输出功能。 移位寄存器和存储器是分别的时钟。 数据在 SCK 的上升沿输入, 在 RCK 的上升沿进入到存储器中。 如果两个时钟连在一起, 则移位寄存器总是比存储器早一个脉冲。 移位寄存器有一个串行输入(DS) , 和一个串行输出(Q7 非) , 和一个异步的低电平复位, 存储寄存器有一个并行 8 位的, 具有三态的总线输出, 当 MR 为高电平, OE 为低电平时, 数据在 SHCP 上升沿进入移位寄存器, 在 STCP 上升沿输出到并行端口。

硬件设计

本文使用到硬件资源如下:
(1) 8X8LED 点阵模块
(2) 74HC595 模块

在这里插入图片描述

从上图中可以看出, 74HC595 需要用到的控制管脚 SER、 RCLK、 SRCLK (14、12、11管脚)直接连接到 51 单片机的 P3.4-P3.6 IO 口上, 输出端则是直接连接到 LED 点阵模块的行端口上, 即为 LED 发光二极管的阳极, LED 点阵的列则为发光二极管的阴极。

要想控制 LED 点阵, 可以将单片机管脚按照 74HC595 芯片的通信时序要求来传输数据, 这样即可控制 LED 点阵的行数据。 根据 LED 发光二极管导通原理, 当阳极为高电平, 阴极为低电平则点亮, 否则熄灭。 因此通过单片机 P0 口可控制点阵列, 74HC595 可控制点阵行。

软件实验

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

#include "reg51.h"typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6;	//移位寄存器时钟输入
sbit RCLK=P3^5;		//存储寄存器时钟输入
sbit SER=P3^4; 		//串行数据输入#define LEDDZ_COL_PORT	P0	//点阵列控制端口//0x01: 00000001  0x02: 00000010  0x04: 00000100
u8 ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{while(ten_us--);	
}/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}/*******************************************************************************
* 函 数 名         : hc595_write_data(u8 dat)
* 函数功能		   : 向74HC595写入一个字节的数据
* 输    入         : dat:数据
* 输    出         : 无
*******************************************************************************/
void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{// 74HC595 是先传输字节的高位后传输低位,所以通过右移运算符依次取值SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//依次把低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中	}RCLK=0;delay_10us(1);RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
}/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	u8 i=0;LEDDZ_COL_PORT=0x00;//将LED点阵列全部设置为0,即LED阴极为低电平while(1){		for(i=0;i<8;i++){	//将存储寄存器的输出引脚清零。这样做的目的是确保 LED 矩阵的显示在每次循环的开始时都是从零状态开始//防止LED矩阵在切换显示内容时出现短暂的混乱或残影,保证每一次循环的开始状态是清晰的。hc595_write_data(0x00);//消除前面寄存器缓存数据hc595_write_data(ghc595_buf[i]);//写入新的数据delay_ms(500);//延时500ms	}									}		
}

实验现象

注意: 做 LED 点阵实验时, 一定要将 LED 点阵旁的 J24 黄色跳线帽短接到 GND一端。

在这里插入图片描述

LED点阵实验

本章所要实现的功能是: 在 8*8LED 点阵屏上点亮一个点, 上述功能实现后再显示数字图形等。

LED 点阵介绍

通常应用较多的是 88 点阵, 然后使用多个 88 点阵可组成不同分辨率的 LED点阵显示屏, 比如 1616 点阵可以使用 4 个 88 点阵构成。 因此理解了 88LED点阵的工作原理, 其他分辨率的 LED 点阵显示屏都是一样的。 这里以 88LED 点阵来做介绍。 其内部结构图如下所示:
在这里插入图片描述
8*8 点阵共由 64 个发光二极管组成, 且每个发光二极管是放置在行线和列线的交叉点上, 当对应的某一行置 1 电平, 某一列置 0 电平, 则相应的二极管就亮;如要将第一个点点亮, 则 1 脚接高电平 a 脚接低电平, 则第一个点就亮了; 如果要将第一行点亮, 则第 1 脚要接高电平, 而(a、 b、 c、 d、 e、 f、 g、 h ) 这些引脚接低电平, 那么第一行就会点亮; 如要将第一列点亮, 则第 a 脚接低电平,而(1、 2、 3、 4、 5、 6、 7、 8) 接高电平, 那么第一列就会点亮。 由此可见, LED点阵的使用也是非常简单的。

硬件设计

本实验用到的硬件资源如下:
(1)8*8LED 点阵模块
(2)74HC595 模块

在这里插入图片描述
从上图中可以看出, 74HC595 需要用到的控制管脚 SER、 RCLK、 SRCLK 直接连接到 51 单片机的 P3.4-P3.6 IO 口上, 输出端则是直接连接到 LED 点阵模块的行端口上, 即为 LED 发光二极管的阳极, LED 点阵的列则为发光二极管的阴极。

要想控制 LED 点阵, 可以将单片机管脚按照 74HC595 芯片的通信时序要求来传输数据, 这样即可控制 LED 点阵的行数据。 根据 LED 发光二极管导通原理, 当阳极为高电平, 阴极为低电平则点亮, 否则熄灭。 因此通过单片机 P0 口可控制点阵列, 74HC595 可控制点阵行。

软件设计

本实验所要实现的功能是: 在点阵屏上点亮一个点, 上述功能实现后再显示数字和图形。

LED点阵(点亮一个点)

#include "reg51.h"typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6;	//移位寄存器时钟输入
sbit RCLK=P3^5;		//存储寄存器时钟输入
sbit SER=P3^4; 		//串行数据输入#define LEDDZ_COL_PORT	P0	//点阵列控制端口/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{while(ten_us--);	
}/*******************************************************************************
* 函 数 名         : hc595_write_data(u8 dat)
* 函数功能		   : 向74HC595写入一个字节的数据
* 输    入         : dat:数据
* 输    出         : 无
*******************************************************************************/
void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中	}RCLK=1;delay_10us(1);RCLK=0;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
}void main()
{	u8 i=0;LEDDZ_COL_PORT=0x7f;//将LED点阵左边第一列设置为0,即LED阴极为低电平,其余列为1,即高电平while(1){			hc595_write_data(0x80);//将LED点阵上边第一行设置为1,即LED阳极为高电平,其余行为0,即低电平								}		
}

代码很简单, 与上一章核心代码是一样的, 这里主要是理解如何让 LED 点阵的左上角第一个点点亮, 实际上就是将第一个点对应的行为高电平, 列为低电平即可。 也就是让 74HC595 输出 0X80(1000 0000) , 这样点阵第一行就是高电平,而 P0 口输出 0X7F(0111 1111),这样点阵第一列就是低电平, 从而让 LED 点阵第一个点点亮。

LED 点阵(显示数字)

要实现行列不同位置亮灯, 需要使用动态显示的方法, 也要结合扫描的方法。在第一行亮灯一段时间以后灭掉, 点亮第二行一段时间以后灭掉, 点亮第三行一段时间以后灭掉, 如此点亮, 直到八行全部点亮一次, 在第一行点亮到最后一行灭掉的总时间不能超过人肉眼可识别的时间, 即 24 毫秒。 在每一行点亮的时候,给列一个新的数据, 此时对应列的数据就可以体现在这行上要点亮的灯上。 这样就和动态数码管的显示一样, 只不过数码管的 LED 灯是段值。 这里使用 LED 点阵显示数字, 也是多个 LED 同时点亮。

要想在点阵上显示数字等字符, 首先要获取在 LED 点阵上显示数字字符所需的数据, 即一个数字字符在 LED 点阵上显示, 对应的每行每列都会有一些灯点亮或者熄灭, 这样就会构成一组数据, 也就是数字字符的显示数据, 我们只要将这些数据通过 74HC595 发送到点阵对应的行或列就能显示数字字符。

数字字符的显示数据如何获取呢?这里用到了一个取字模软件,不详细介绍,大家可以去搜索。通过该软件可得,
LED 点阵显示数字 0 的行数据为{0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0x00},这些数据其实就是上述描绘的数字 0 从左到右依次每列对应的行数据。

既然是动态扫描, 就需要不断的扫描每列, 因此可以把 LED 点阵的列控制也用数组存储起来, 为后面循环调用提供方便。根据数字 0 取模的数据特点是从左至右每列对应的行数据, 因此扫描时也应该从左至右的顺序, 如下:

u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED 点阵显示数字 0 的列数据

#include "reg51.h"typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6;	//移位寄存器时钟输入
sbit RCLK=P3^5;		//存储寄存器时钟输入
sbit SER=P3^4; 		//串行数据输入#define LEDDZ_COL_PORT	P0	//点阵列控制端口u8 gled_row[8]={0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0x00};//LED点阵显示数字0的行数据
u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示数字0的列数据/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{while(ten_us--);	
}/*******************************************************************************
* 函 数 名         : hc595_write_data(u8 dat)
* 函数功能		   : 向74HC595写入一个字节的数据
* 输    入         : dat:数据
* 输    出         : 无
*******************************************************************************/
void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中	}RCLK=1;delay_10us(1);RCLK=0;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
}/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	u8 i=0;while(1){			for(i=0;i<8;i++)//循环8次扫描8行、列{LEDDZ_COL_PORT=gled_col[i];//传送列选数据hc595_write_data(gled_row[i]);//传送行选数据delay_10us(100);//延时一段时间,等待显示稳定hc595_write_data(0x00);//消影	}								}		
}

实验代码与前面点亮一个点的核心代码是一样的, 这里重点要理解动态扫描。 main 函数中主要是在 while 循环内从上至下, 从左至右不断扫描 8 行、 列, 即首先设置左边第一列有效(P07 输出低电平) , 其余列无效(P06-P00 输出高电平) , 然后通过74HC595 输出该列对应的行数据, 延时一段时间等待显示稳定, 最后清除列对应的行数据, 即消影。 从整个流程下来与动态数码管显示程序是很相似的

LED 点阵(显示图像)

同样是通过取模软件获取图像数据,这里以“心” 形图像为例,LED 点阵显示数字 0 的行数据为{0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38},把该行数据替换为数字 0 的数据即可。其余代码与显示数字完全一样, 这里就不再列出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/451531.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为电信应用选择电阻器

用于电信应用的高规格电阻器可用于网络设备、语音通信、VOIP、路由器、网桥、多路复用器、光纤/有线转换器、滤波、阻抗匹配、信号调理和电源管理。 物联网 &#xff08;IoT&#xff09; 设备的采用、5G 等技术的发展以及向 VOIP 的转变产生了对更小&#xff08;表面贴装&#…

大小姐驾到!高德地图联合《王者荣耀》推出孙尚香导航语音包

“大小姐驾到&#xff01;统统闪开&#xff01;”如果你是一个手游爱好者&#xff0c;多半会对这句话耳熟能详&#xff0c;来自于国内手游界顶流《王者荣耀》中的高人气角色——孙尚香&#xff0c;并成为一代玩家们的记忆。 如今&#xff0c;随着高德地图与《王者荣耀》达成合…

26条prompt规则应用于大模型

1、引入动机 llm大模型在回答一些问题上表现出了惊人的能力&#xff0c;例如数学逻辑推理&#xff0c;代码生成&#xff0c;问题答复等。提词工程是和大预言模型交流的一门艺术。 大模型的返回结合和用户的指令和输入直接相关prompts是用户和大模型沟通的一种编码方式 一般地…

day3作业

第三章 类与构造函数 一&#xff0e;选择题 1、下列不能作为类的成员的是&#xff08;A&#xff09; A. 自身类对象的指针 B. 自身类对象 C. 自身类对象的引用 D. 另一个类的对象 2、假定AA为一个类&#xff0c;a()为该类公有的函数成员&#xff0c;x为该类的一个对象&#xf…

总观看量已超千万!新就业形态劳动者新春联谊会成功播出

春节到来之际,由中华全国总工会主办,中国海员建设工会、中国国防邮电工会、中国财贸轻纺烟草工会、中华全国总工会文工团联合承办,中国职工发展基金会协办,北京市总工会支持的“温暖有你 共赴美好”2024年新就业形态劳动者新春联谊会,于2月2日晚8点在新华网、央视频、全国总工会…

当前页面的脚本发生错误如何解决

在使用互联网进行日常浏览或工作时&#xff0c;我们有时会遇到“当前页面的脚本发生错误”这样的提示。这可能会使我们的网页浏览体验变得不顺畅&#xff0c;甚至影响到一些在线功能的正常使用。那么&#xff0c;当遇到这类问题时&#xff0c;我们应该如何解决呢&#xff1f;下…

逸学区块链【solidity】真随机数

参考Get a Random Number | Chainlink Documentation 但是很贵&#xff0c;价格 Gas Price&#xff1a;当前gas价格&#xff0c;根据网络状况而波动。Callback gas &#xff1a;返回您所请求的随机值时&#xff0c;回调请求消耗的gas 量。验证gas &#xff1a;量gas 用于验证…

SpringBoot大学生就业信息管理

项目技术: SpringBoot SSM layui 功能描述&#xff1a; 实现了就业信息管理、就业统计、用户管理等功能。 有普通用户和管理员两种角色 普通用户账号&#xff1a;test 密码&#xff1a;123456 管理员账号&#xff1a;admin 密码&#xff1a;123456 效果图&#xff1…

云微呼掌握短信营销的艺术:策略、技巧与实践

引言 短信营销作为一种直接、高效的营销工具&#xff0c;为品牌和营销人员提供了与受众建立密切联系的机会。然而&#xff0c;要想取得成功&#xff0c;除了熟悉其优势外&#xff0c;还需要掌握精准的策略和创新的实践方法。本文将深入探讨短信营销的艺术&#xff0c;带领读者…

GMT绘图笔记

(1)图框设置。在利用GMT绘制图件时&#xff0c;需要设置边框的类型&#xff0c;字体的大小&#xff0c;标记距离边框的距离。主要涉及的参数有&#xff1a; gmt set MAP_FRAME_TYPE plain/fancy 可以调整边框为火车轨道或者线段。 (2)调整图框的粗细&#xff1a;主要是包含有…

【vue3学习P5-P10】vue3语法;vue响应式实现

0、vue2和vue3对比 框架版本API方式双向绑定原理domFragmentsTree-Shakingvue2选项式API&#xff08;Options API&#xff09;基于Object.defineProperty&#xff08;监听&#xff09;实现&#xff0c;不能双向绑定对象类型的数据【通过Object.defineProperty里面的set和get做…

Django的web框架Django Rest_Framework精讲(四)

文章目录 1.DRF认证组件Authentication2.权限Permissions3.限流Throttling4.过滤Filtering5.排序6.分页Pagination7.异常处理 Exceptions8.自动生成接口文档 大家好&#xff0c;我是景天&#xff0c;今天我们继续DRF的最后一讲&#xff0c;Django的web框架Django Rest_Framewor…