74HC595模块原理

OE:当OE置0时该模块才能正常工作

使用模块前需先将模块初始化,将SRCLK和RCLK都置0

                                                        串转并移位寄存器工作原理图

当收到外界的一个数据date时(16进制数),取其第8位放入SER,将SRCLK置1,让移位寄存器向下移动一位,将SER中的数据装入移位寄存器最顶端,然后将SRCLK置0。再取date的第7位放入SER,将ERCLK置1,让移位寄存器向下移动一位,再将SRCLK置0。此时,date的第7位位于移位寄存器的最顶端,第8位位于第7位的下面,重复以上步骤,循环8次后date被存入移位寄存器,此时将RCLK置1,将移位寄存器中的date送到QX各个端口,再将RCLK置1,以便下一个date的发送,这就完成了串行通信转并行通信

相关代码如下:

#include <regx52.h>

sbit RCK=P3^5;      //RCLK
sbit SRCLK=P3^6;
sbit SER=P3^4;


void HC595_write_date(unsigned char date)
{
	unsigned char i;
	SRCLK=0;
	RCK=0;
	for(i=0;i<8;i++)
	{
		SER=date&(0x80>>i);          //date对应位为1则SER=1,若对应位为0,则SER=0,由高到低依次取相应位数值
		SRCLK=1;                     //向下移动一位后,将SER的值写入移位寄存器
		SRCLK=0;                     //将SRCLK置0,以便下一个数据的存入
	}
	RCK=1;                           //将移位寄存器中的数据送入各个端口
	RCk=0;
}

<think>我们使用74HC595模块来扩展输出,控制8x8LED点阵。74HC595是一个8位串行输入、并行输出的移位寄存器,可以级联使用。硬件连接:-数据线(DS)连接到单片机的某个IO口(如P3.4)-移位时钟(SH_CP)连接到另一个IO(如P3.5)-锁存时钟(ST_CP)连接到另一个IO(如P3.6)这样,我们可以通过串行方式将两个8位数据(行和列)发送到两个74HC595芯片(级联),一个控制行,一个控制列。注意:8x8LED点阵有行和列,通常行是高电平有效,列是低电平有效(或者相反,具体看模块)。这里我们假设:-行为高电平有效(即给行输出高电平,该行被选中)-列为低电平有效(即给列输出低电平,该列被点亮)因此,我们需要两个74HC595级联,第一个(输出Q0-Q7)控制列,第二个(输出Q0-Q7)控制行。实现功能与之前相同:切换显示信息、切换显示模式、调整速度、息屏。由于8051资源有限,我们将使用定时器中断进行显示刷新,同时处理按键和显示逻辑。代码结构:1.定义引脚2.全局变量(状态、缓冲区、字模等)3.函数:发送数据到595、定时器初始化、显示扫描、按键处理、更新显示内容等4.主循环注意:74HC595的级联方式:第一个595的串行输出(Q7')连接到第二个595的串行输入(DS)。我们发送16位数据时,先发送第二个595的数据(行),再发送第一个595的数据(列)。由于我们使用共阳LED点阵(行选通为高电平,列数据为低电平点亮),所以:-行选择:8位,每次只有1位为1(选择一行)-列数据:8位,对应点亮的点为0下面给出具体代码:</think>下面我将提供一个基于74HC595移位寄存器驱动8x8 LED点阵的完整解决方案,实现按键控制的多功能显示系统。这种方案可以显著减少单片机IO口占用,提高系统扩展性。 ### 完整代码实现 ```c #include <reg52.h> #include <intrins.h> // 74HC595控制引脚定义 sbit DS = P2^0; // 串行数据输入 sbit SHCP = P2^1; // 移位寄存器时钟 sbit STCP = P2^2; // 存储寄存器时钟 // 按键引脚定义 sbit K1 = P3^0; sbit K2 = P3^1; sbit K3 = P3^2; sbit K4 = P3^3; // 全局状态变量 unsigned char displayMode = 0; // 显示模式: 0-静止, 1-幻灯片, 2-滚动 unsigned char currentInfo = 0; // 当前信息: 0-个人信息, 1-Hello World unsigned char speedLevel = 0; // 速度等级: 0-0.2s, 1-0.5s, 2-1.0s, 3-2.0s bit displayOn = 1; // 显示开关: 1-开启, 0-关闭 // 速度数组 (单位: 毫秒) unsigned int speeds[4] = {200, 500, 1000, 2000}; // 显示缓冲区 unsigned char colData = 0xFF; // 列数据 (低电平点亮) unsigned char rowData = 0x00; // 行数据 (高电平选中) // 个人信息字模 (班级+姓名+学号) unsigned char code personalInfo[] = { // 'C' 'S' '1' '0' '1' '张' '三' '2' '0' '2' '1' '0' '0' '0' '1' 0x7E, 0x11, 0x11, 0x11, 0x7E, 0x00, // C 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, // S 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 1 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 1 // 汉字"张"的简化表示 (8x8) 0x10, 0x08, 0x7F, 0x44, 0x44, 0x7F, 0x44, 0x00, // 汉字"三"的简化表示 (8x8) 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, // 后续数字 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 2 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 2 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 1 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 0 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 0 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00 // 1 }; // Hello World字模 unsigned char code helloWorld[] = { // 'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' '!' 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, // H 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, // e 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, // l 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, // l 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, // o 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 空格 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, // W 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, // o 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, // r 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, // l 0x20, 0x40, 0x44, 0x3D, 0x00, 0x00, // d 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 // ! }; // 定时器计数器 unsigned int timerCount = 0; unsigned char currentChar = 0; unsigned int scrollPosition = 0; unsigned char currentRow = 0; // 按键防抖计数器 unsigned char keyDebounce[4] = {0}; // 函数声明 void Timer0Init(void); void SendTo595(unsigned char row, unsigned char col); void ProcessKeys(void); void UpdateDisplay(void); void LoadCharacter(unsigned char index); void ShiftOut(unsigned char data); // 主函数 void main() { Timer0Init(); // 初始化定时器 EA = 1; // 开启总中断 while(1) { ProcessKeys(); // 处理按键 UpdateDisplay(); // 更新显示 } } // 定时器0初始化 void Timer0Init() { TMOD = 0x01; // 设置定时器0为模式1 TH0 = 0xFC; // 1ms定时 TL0 = 0x18; ET0 = 1; // 开启定时器0中断 TR0 = 1; // 启动定时器0 } // 定时器0中断服务函数 void Timer0() interrupt 1 { TH0 = 0xFC; // 重新加载初值 TL0 = 0x18; // 发送显示数据到74HC595 SendTo595(rowData, colData); // 按键防抖计数 for(unsigned char i = 0; i < 4; i++) { if(keyDebounce[i] > 0) keyDebounce[i]--; } // 模式计时 timerCount++; // 行扫描计数器 currentRow = (currentRow + 1) % 8; } // 发送数据到74HC595 void SendTo595(unsigned char row, unsigned char col) { STCP = 0; // 准备锁存数据 // 先发送列数据(控制点亮点) ShiftOut(col); // 再发送行数据(控制选择行) ShiftOut(row); STCP = 1; // 锁存输出 } // 串行移位输出 void ShiftOut(unsigned char data) { unsigned char i; for(i = 0; i < 8; i++) { SHCP = 0; // 准备移位 // 输出数据位 DS = (data & 0x80) ? 1 : 0; data <<= 1; SHCP = 1; // 上升沿移位 } } // 按键处理函数 void ProcessKeys() { // K1: 切换显示信息 if(!K1 && keyDebounce[0] == 0) { keyDebounce[0] = 20; // 防抖延时 currentInfo = !currentInfo; currentChar = 0; scrollPosition = 0; } // K2: 切换显示模式 if(!K2 && keyDebounce[1] == 0) { keyDebounce[1] = 20; displayMode = (displayMode + 1) % 3; currentChar = 0; scrollPosition = 0; } // K3: 调整速度 if(!K3 && keyDebounce[2] == 0) { keyDebounce[2] = 20; speedLevel = (speedLevel + 1) % 4; } // K4: 开关显示 if(!K4 && keyDebounce[3] == 0) { keyDebounce[3] = 20; displayOn = !displayOn; } } // 更新显示内容 void UpdateDisplay() { static unsigned int lastUpdate = 0; if(!displayOn) { // 息屏状态 rowData = 0x00; colData = 0xFF; return; } // 检查是否需要更新显示 if(timerCount - lastUpdate < speeds[speedLevel]) return; lastUpdate = timerCount; switch(displayMode) { case 0: // 静止模式 if(currentInfo == 0) { LoadCharacter(0); // 显示第一个字符 } else { LoadCharacter(0); // 显示第一个字符 } break; case 1: // 幻灯片模式 if(currentInfo == 0) { LoadCharacter(currentChar); currentChar = (currentChar + 1) % (sizeof(personalInfo)/6); } else { LoadCharacter(currentChar); currentChar = (currentChar + 1) % (sizeof(helloWorld)/6); } break; case 2: // 滚动模式 (仅对Hello World有效) if(currentInfo == 1) { // 实现滚动效果 unsigned int pos = scrollPosition + currentRow; if(pos < sizeof(helloWorld)) { colData = helloWorld[pos]; } else { colData = 0x00; // 空白 } rowData = (1 << currentRow); // 选择当前行 scrollPosition = (scrollPosition + 1) % (sizeof(helloWorld) - 7); } else { LoadCharacter(0); // 显示静态信息 } break; } } // 加载字符到显示缓冲区 void LoadCharacter(unsigned char index) { unsigned int offset = index * 6; // 每个字符6字节 if(offset + currentRow < sizeof(personalInfo) && currentInfo == 0) { colData = personalInfo[offset + currentRow]; } else if(offset + currentRow < sizeof(helloWorld) && currentInfo == 1) { colData = helloWorld[offset + currentRow]; } else { colData = 0x00; // 空白 } // 选择当前行 rowData = (1 << currentRow); } ``` ### 代码详细解释 #### 1. 74HC595驱动原理 74HC595是串行输入/并行输出的移位寄存器,通过3个控制引脚实现多路输出: - **DS**:串行数据输入 - **SHCP**:移位时钟(上升沿时数据移位) - **STCP**:锁存时钟(上升沿时数据输出到并行端口) 系统使用两个74HC595级联: - 第一个595控制列数据(点亮点) - 第二个595控制行选择(扫描行) #### 2. 核心功能实现 **a. 按键功能**: - **K1**:切换显示信息(个人信息 ↔ Hello World) - **K2**:循环切换显示模式(静止 → 幻灯片 → 滚动) - **K3**:循环切换四种速度(0.2s → 0.5s → 1.0s → 2.0s) - **K4**:显示开关(亮屏 ↔ 息屏) **b. 显示模式**: - **静止模式**:显示信息的第一个字符 - **幻灯片模式**:轮流显示信息中的每个字符 - **滚动模式**:仅对"Hello World"有效,实现从右向左的滚动效果 #### 3. 关键技术点 **a. 74HC595驱动**: - `ShiftOut()`函数实现8位数据串行输出 - `SendTo595()`函数控制两个级联的595芯片 - 先发送列数据,再发送行数据 **b. 动态扫描**: - 定时器每1ms中断一次 - 每次中断更新一行显示 - 8ms完成整个点阵的刷新(约125Hz刷新率) **c. 字模处理**: - 预定义字符点阵数据(每个字符6字节) - 滚动模式通过动态偏移显示位置实现 - 支持英文字符和简化汉字显示 #### 4. 关键函数说明 - **Timer0Init()**:初始化定时器0为1ms定时 - **ShiftOut()**:通过74HC595串行输出8位数据 - **SendTo595()**:控制两个级联的595芯片 - **ProcessKeys()**:处理按键输入并更新状态 - **UpdateDisplay()**:根据当前模式更新显示内容 - **LoadCharacter()**:加载指定字符到显示缓冲区 ### 硬件连接示意图 ``` 74HC595芯片1 (列控制) 8051单片机 DS --------------------- P2.0 SHCP -------------------- P2.1 STCP -------------------- P2.2 VCC -------------------- 5V GND -------------------- GND 74HC595芯片2 (行控制) DS -------------------- 芯片1的Q7' (串行输出) SHCP ------------------- P2.1 STCP ------------------- P2.2 VCC ------------------- 5V GND ------------------- GND 8x8 LED点阵 行引脚 ----------------- 芯片2的并行输出 (Q0-Q7) 列引脚 ----------------- 芯片1的并行输出 (Q0-Q7) 独立按键模块 K1 -------------------- P3.0 K2 -------------------- P3.1 K3 -------------------- P3.2 K4 -------------------- P3.3 ``` ### 系统优势 1. **IO口高效利用**:仅需3个IO口控制整个点阵 2. **扩展性强**:可轻松级联更多595芯片控制更大点阵 3. **刷新率高**:125Hz刷新率避免闪烁 4. **功耗低**:动态扫描降低系统功耗 ### 优化建议 1. 添加亮度调节功能 2. 实现更流畅的滚动效果 3. 使用外部EEPROM存储更多字模数据 4. 添加显示内容保存功能
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值