51单片机通过两片74HC595级联,用8位LED数码管,分别显示当前日期,如:“2”、“0”、“-”、“0”、“5”、“-”、“2”、“6”,用Proteus仿真实现。

1.先上仿真图,但这么连仿真图是不太正确的,要注意。展示的话能用就行。

2.从上到下依次放上数据手册上的引脚解释和逻辑功能和时序图

 

 3.贴上代码:写了发送一字节数据函数,发送全部字节函数,加上一些写了很久的解释(求赞)。

#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#define uint unsigned int 
#define uchar unsigned char
#define p0 P0
#define p1 P1
#define p2 P2
#define p3 P3
//参考数据手册对引脚功能进行理解,
//老师发的数据手册的第3和6页解释了各输入引脚与输出引脚的电平关系,第七页解释了每个引脚的时序关系;
//级联需要两个芯片接同个STCP和SHCP时钟,第二个的DS引脚接在第一个芯片引脚的最高位的取反脚。
//第一个u6芯片控制段选,第二个芯片控制位选;

sbit STCP=P2^0;//第三,STCP的英语解释是storage register— clock input
//意思是储存寄存器的每一位输入值用来准备输出,1为真,而OE引脚低电平就会允许输出寄存器的内容;
//如果stcp的处于低电平,寄存的值就不会允许输出,

sbit SHCP=P2^1;//第一,SHCP的英语解释是 shift register_ clock input,
//移位寄存器,可以理解为允许且给寄存器输入一位又一位的二进制数据,是总的时钟信号
sbit DS	 =P2^2;//第二,ds下降的时候,stcp上升,stcp下降一会ds再上升
//ds在shcp下降时触发上边沿

//结合第6页的逻辑功能解释,加上数据手册第七页的时序图,可以明白一下操作规则
//DS先置为高电平,引来SHCP的第一次上升沿的时候就会将数据放置进入74HC芯片移位寄存器;
//有8位,进行移位操作,相当于<<1和crol函数,通过移位也能实现串行级联
//如果STCP迎来上升沿,会将移位寄存器内部的值准备通过并行输出8位的值


uchar code data2[]={0xa4,0xb0,0xbf,0xc0,0x99,0xbf,0xa4,0x99};//段选
uchar code data1[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//位选
//data1放位码,data2放段码

//一个延时函数
	void delay(uint i)
{
	uchar m,n;
	for(m=0;m<i;m++)
	for(n=0;n<i;n++);
}


//一个传输一字节(8位二进制数字)的函数
void send_byte(uchar data1)
{
	
	uchar i;
	for(i=0;i<8;i++)
	{
		SHCP=0;//每次开始传输前先把SCHP置0,
		DS=(data1)&0x80;//开始通过DS,data1的长度是一个字节,即8位二进制数字
		//data1和0x80求与的作用:
		//1.0x80的二进制数为:1000 0000
		//2.和data1求与只会有两个结果,为真或者为0;求与的结果是最高位由data1决定,而其他位全部置零
		//3.通过位求与的方式屏蔽掉数据data1转为二进制后最左边即最高位以外的其他7位。
		//为方便理解,可以写为:
		//if((data1&0x80)!=0)
		//		DS=1;
		//else 
		//		DS=0;
		data1=(data1)<<1;//通过对data1二进制的不断左移位,判断出data1每一位的值为0或者为1;
		
		SHCP=1;//通过一个上升沿,允许DS数据输入移位寄存器;
		_nop_();//等待一个机器周期,保证符合时序图。
	}
	_nop_();
	_nop_();
}

//写一个显示函数,通过将位码和段码先后输入两个74HC595芯片来显示内容。
void display()
{
	uchar i;
	SHCP=0;//将三个可控输入都初始化值为0。
	STCP=0;
	DS=0;
	//正如前面所述,开发板上有两个595芯片,并且已经是级联和OE MR等线都连好了的。
	//我们需要控制的只有shcp,stcp,ds三个引脚的高低电平输入时序,
	//板上有两片595,第一个595用来控制一个数码管上显示的内容,第二个用来控制要让8个数码管哪个点亮
	//单片机的输出频率很快,虽然我们是一个个数码管依次显示,但是因为频率太快,人眼无法分辨
	
	//通过上述解释,我们可以理解:
	//1.每次我们要选择第几个数码管显示什么样的内容,我们要输入段码和位码两次数据一个给芯片1,一个给芯片2;
	//2.因为595是移位寄存器,即在允许串行输出的情况下,最先进入移位寄存器的值最终会被通过串行输出引脚发送到下一个移位寄存器,即芯片2
	//3.根据版图所接引脚,我们要先输入位码,再输入段码。
	for(i=0;i<8;i++)
	{
	  send_byte(data1[i]);//位码
		send_byte(data2[i]);//段码
		STCP=1;//置2,允许输出全部8位寄存器的数据
  	_nop_();//延时一个机器周期再置0
	  STCP=0;
	 delay(2);//数据手册的时序图上看得出延时2us或者两个机器周期以上才能再输入DS。
	}
}
void main(void)
{
	//p2=0xff;

	delay(10);
	while(1)
	{
		display();
	}
}
	
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
51单片机八位数码管同时显示需要使用到多路数码管显示驱动芯片,如常用的TM1638、MAX7219等。以下是使用TM1638驱动芯片的示例代码: ```c #include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit TM1638_DIO = P1^0; // 定义TM1638数据线引脚 sbit TM1638_CLK = P1^1; // 定义TM1638时钟线引脚 sbit TM1638_STB = P1^2; // 定义TM1638片选线引脚 uchar code DIGITS[] = { // 定义数字0-9、A-F的编码 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; void delay(uint ms) // 延时函数 { uint i, j; for(i=0; i<ms; i++) for(j=0; j<125; j++); } void TM1638_SendByte(uchar data) // 发送一个字节数据 { uchar i; for(i=0; i<8; i++) { TM1638_DIO = (data & 0x01); data >>= 1; TM1638_CLK = 1; _nop_(); _nop_(); TM1638_CLK = 0; } } void TM1638_SendCommand(uchar command) // 发送命令 { TM1638_STB = 0; TM1638_SendByte(command); TM1638_STB = 1; } void TM1638_Init() // 初始化TM1638 { TM1638_SendCommand(0x8f); // 打开显示,设置亮度为最高 TM1638_SendCommand(0x44); // 设置地址自动加1 TM1638_STB = 0; TM1638_SendByte(0xc0); // 设置起始地址为0 for(uchar i=0; i<16; i++) TM1638_SendByte(0x00); // 清空显示缓存 TM1638_STB = 1; } void TM1638_Display(uchar* digits) // 显示函数 { TM1638_STB = 0; TM1638_SendByte(0xc0); // 设置起始地址为0 for(uchar i=0; i<8; i++) { TM1638_SendByte(digits[i]); // 发送显示数据 TM1638_SendByte(DIGITS[10+i]); // 发送小数点数据(没有小数点可省略) } TM1638_STB = 1; } void main() { uchar digits[8] = { // 要显示的数字 1, 2, 3, 4, 5, 6, 7, 8 }; TM1638_Init(); // 初始化TM1638 while(1) { TM1638_Display(digits); // 显示数字 delay(100); // 延时100ms } } ``` 在上述代码中,通过定义TM1638_DIO、TM1638_CLK、TM1638_STB三个引脚来控制TM1638驱动芯片的数据、时钟和片选信号。在TM1638_Init()函数中,设置了TM1638的工作模式、亮度和起始地址,并清空了显示缓存。在TM1638_Display()函数中,通过循环发送8位数字数据和小数点数据来实现八位数码管显示。在主函数中,循环调用TM1638_Display()函数并延时100ms来更新显示内容。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值