LED点阵
普中51单片机的8x8LED点阵的引脚接线方式是左边的,每一列都是共阴极,每一行都是共阳极,从上往下依次是D7-D0,从左往右依次是P07-P00,
而D7-D0又是由P34、P35、P36进行串行控制(和38译码器一样,不同组合共有8种情况),P07-P00又是由P0口并行控制。
P34是串行数据输入口,用来发送数据的,P36是高电平时数据移位,低电平时数据不变
实验一:点亮左上角的一个LED灯
分析:左上角的LED灯对应的坐标是:第一行(D7),第一列(P07),因此,对于列输出:10000000,转换成十六进制就是0x80
再把第一行的第一个灯置为低电平,其他为低电平,这样LED灯阳极为高电平,阴极为低电平,就会点亮
Keil代码:
/************************************************************************************** 8×8LED点阵———点亮一个点实验 实现现象:下载程序后点阵左上角第一个点点亮 注意事项:一定要将74HC595模块上的JP595短接片短接,并且将JOE短接片短接到GND端。 **************************************************************************************/ #include <reg51.h> #include <intrins.h> #define u16 unsigned int #define u8 unsigned char // 定义管脚(结合单片机的74HC595移位寄存器和LED点阵) sbit SRCLK = P3^6; // 数据移位 sbit RCLK = P3^5; // 将数据从移位寄存器传输到存储寄存器 sbit SER = P3^4; // 发送数据 /******************************************************************************* * 函数名 : hc595SendByte(u8 data) * 函数功能 : 向74HC595发送一个字节的数据 * 输入 : 无 * 输出 : 无 * 注意 : 根据单片机原理图和74HC595原理图与说明书写这个方法 *******************************************************************************/ void hc595SendByte(u8 dat) // 这里不能写成data,因为data是Keil中的关键字 { u8 i; // 初始状态,拉点电平 SRCLK = 0; RCLK = 0; // 总共发送一个字节(8位二进制数),而且74HC595移位寄存器是移位发送,每次发送一位,所以要发送8次 for(i=0; i<8; i++) { /** 比如要发送的数据是:10011001,只是打个比方,不一定是这个数据, 要发送最高位1,操作:先把10011001右移七位,剩下最高位1,再发送 */ SER = dat >> 7; // 把次高位作为最高位,为下一次循环做准备 dat <<= 1; // 或dat = dat << 1; // 由74HC595原理图可知,数据移位电平拉高才能将数据传输到移位寄存器中 SRCLK = 1; /** 延迟操作,数据移位口复位,这里调用intrins.h库文件的函数进行延迟,表示延迟一个机器周期, 如果是12M晶振,就是1us,使用这个函数只是为了更精确的时间延迟操作 */ _nop_(); _nop_(); SRCLK = 0; } // 将数据从移位寄存器传输到存储寄存器,上升沿时数据进行传输,下降沿时保持不变 RCLK = 1; // 需要拉高电平 _nop_(); // 延迟后拉低电平,进行软件消抖,具体时间看原理图资料 _nop_(); RCLK = 0; } // 主函数 void main() { // P07:阴极,即最高位输出低电平,其他位输出高电平,即01111111,转十六进制是0x7f P0 = 0x7f; // 左上角灯亮,对应坐标:行D7,列P07,即10000000,转十六进制是0x80 // 死循环,LED灯保持点亮 while(1) { hc595SendByte(0x80); } }
实验效果:
实验改进:显示一个“X”
/************************************************************************************** 8×8LED点阵———点亮一个点实验 实现现象:下载程序后点阵左上角第一个点点亮 注意事项:一定要将74HC595模块上的JP595短接片短接,并且将JOE短接片短接到GND端。 **************************************************************************************/ #include <reg51.h> #include <intrins.h> #define u16 unsigned int #define u8 unsigned char // 定义管脚(结合单片机的74HC595移位寄存器和LED点阵) sbit SRCLK = P3^6; // 数据移位 sbit RCLK = P3^5; // 将数据从移位寄存器传输到存储寄存器 sbit SER = P3^4; // 发送数据 u8 code P0_data[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; u8 code D0_data[8] = {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}; void delay(u16 time) { while(time--); } /******************************************************************************* * 函数名 : hc595SendByte(u8 data) * 函数功能 : 向74HC595发送一个字节的数据 * 输入 : 无 * 输出 : 无 * 注意 : 根据单片机原理图和74HC595原理图与说明书写这个方法 *******************************************************************************/ void hc595SendByte(u8 dat) // 这里不能写成data,因为data是Keil中的关键字 { u8 i; // 初始状态,拉点电平 SRCLK = 0; RCLK = 0; // 总共发送一个字节(8位二进制数),而且74HC595移位寄存器是移位发送,每次发送一位,所以要发送8次 for(i=0; i<8; i++) { /** 比如要发送的数据是:10011001,只是打个比方,不一定是这个数据, 要发送最高位1,操作:先把10011001右移七位,剩下最高位1,再发送 */ SER = dat >> 7; // 把次高位作为最高位,为下一次循环做准备 dat <<= 1; // 或dat = dat << 1; // 由74HC595原理图可知,数据移位电平拉高才能将数据传输到移位寄存器中 SRCLK = 1; /** 延迟操作,数据移位口复位,这里调用intrins.h库文件的函数进行延迟,表示延迟一个机器周期, 如果是12M晶振,就是1us,使用这个函数只是为了更精确的时间延迟操作 */ _nop_(); _nop_(); SRCLK = 0; } // 将数据从移位寄存器传输到存储寄存器,上升沿时数据进行传输,下降沿时保持不变 RCLK = 1; // 需要拉高电平 _nop_(); // 延迟后拉低电平,进行软件消抖,具体时间看原理图资料 _nop_(); RCLK = 0; } // 主函数 void main() { u8 x; while(1) { for(x=0; x<8; x++) { P0 = P0_data[x]; hc595SendByte(D0_data[x]); delay(10); //1s P0 = 0xff; hc595SendByte(0x00); } } }
效果:
实验二:显示 数字0
/************************************************************************************** 8×8LED点阵———点亮一个点实验 实现现象:下载程序后点阵左上角第一个点点亮 注意事项:一定要将74HC595模块上的JP595短接片短接,并且将JOE短接片短接到GND端。 **************************************************************************************/ #include <reg51.h> #include <intrins.h> #define u16 unsigned int #define u8 unsigned char // 定义管脚(结合单片机的74HC595移位寄存器和LED点阵) sbit SRCLK = P3^6; // 数据移位 sbit RCLK = P3^5; // 将数据从移位寄存器传输到存储寄存器 sbit SER = P3^4; // 发送数据 // 显示数字0 u8 code P0_data[] = {0x00, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00}; // 列 u8 code D0_data[] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; // 行 // 延迟函数 void delay(u16 time) { while(time--); } /******************************************************************************* * 函数名 : hc595SendByte(u8 data) * 函数功能 : 向74HC595发送一个字节的数据 * 输入 : 无 * 输出 : 无 * 注意 : 根据单片机原理图和74HC595原理图与说明书写这个方法 *******************************************************************************/ void hc595SendByte(u8 dat) // 这里不能写成data,因为data是Keil中的关键字 { u8 i; // 初始状态,拉点电平 SRCLK = 0; RCLK = 0; // 总共发送一个字节(8位二进制数),而且74HC595移位寄存器是移位发送,每次发送一位,所以要发送8次 for(i=0; i<8; i++) { /** 比如要发送的数据是:10011001,只是打个比方,不一定是这个数据, 要发送最高位1,操作:先把10011001右移七位,剩下最高位1,再发送 */ SER = dat >> 7; // 把次高位作为最高位,为下一次循环做准备 dat <<= 1; // 或dat = dat << 1; // 由74HC595原理图可知,数据移位电平拉高才能将数据传输到移位寄存器中 SRCLK = 1; /** 延迟操作,数据移位口复位,这里调用intrins.h库文件的函数进行延迟,表示延迟一个机器周期, 如果是12M晶振,就是1us,使用这个函数只是为了更精确的时间延迟操作 */ _nop_(); _nop_(); SRCLK = 0; } // 将数据从移位寄存器传输到存储寄存器,上升沿时数据进行传输,下降沿时保持不变 RCLK = 1; // 需要拉高电平 _nop_(); // 延迟后拉低电平,进行软件消抖,具体时间看原理图资料 _nop_(); RCLK = 0; } // 主函数 void main() { // P07:阴极,即最高位输出低电平,其他位输出高电平,即01111111,转十六进制是0x7f //P0 = 0x7f; // 左上角灯亮,对应坐标:行D7,列P07,即10000000,转十六进制是0x80 // 死循环,LED灯保持点亮 u8 t; while(1) { P0=0x7f; for(t=0; t<8; t++) { P0 = D0_data[t]; hc595SendByte(P0_data[t]); delay(100); // 消影 hc595SendByte(0x00); } } }
效果: