51单片机的串口实验之数码管显示与按键实验(8位数字任意传输)

目标效果:

1、电脑发送任意小于<=8位数字(SUBF只有8位最大只能发送255,但是可以通过数组进行临时存储来实现传输多字节)数字,在数码管上显示对应的数字且同时满足高位是0可以不显示

 2、矩阵按键按下后,电脑接收所按下的按钮


实验器材:

1、普中51单片机。2、STC官方下载器自带的串口调试的功能


相关资料 (普中官方资料)

SCON寄存器的相关介绍


最新的代码(可以实现一次性传输多字节也就是可以传输8位数字)

#include <REGX52.H>
 
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口
 
 
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
 
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口
 
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
u16 shuju[8]=0;
u32 a,key;//a用来接收收到的数字,key是接收到的按键
u8 num=0,flag=0;
void configuart(u16 baud);
 
void delay (u16 time)
{
	while(time--);
}
 
u8 anjian_scan(void)
{
	static u8 keyvalue=0;
	KEY_MATRIX_PORT=0x0f;
	if(KEY_MATRIX_PORT!=0x0f)
	{
		delay(1000);
		if(KEY_MATRIX_PORT!=0x0f)
		{
			KEY_MATRIX_PORT=0x0f;
			switch(KEY_MATRIX_PORT)//保存行为 0,按键按下后的列值
			{
				case 0x07: keyvalue=1;break;
				case 0x0b: keyvalue=2;break;
				case 0x0d: keyvalue=3;break;
				case 0x0e: keyvalue=4;break;
			}
			KEY_MATRIX_PORT=0xf0;
			switch(KEY_MATRIX_PORT)//保存列为 0,按键按下后的键值
			{
				case 0x70: keyvalue=keyvalue;break;
				case 0xb0: keyvalue=keyvalue+4;break;
				case 0xd0: keyvalue=keyvalue+8;break;
				case 0xe0: keyvalue=keyvalue+12;break;
			}
			while(KEY_MATRIX_PORT!=0xf0);
		}
	}
	else
		keyvalue=0;
	return keyvalue;
}
 
void smg_display(u32 b)
{
	u8 i=0,flag=0;
	shuju[0]=b%16;
	shuju[1]=b/16%16;
	shuju[2]=b/16/16%16;
	shuju[3]=b/16/16/16%16;
	shuju[4]=b/16/16/16/16%16;
	shuju[5]=b/16/16/16/16/16%16;
	shuju[6]=b/16/16/16/16/16/16%16;
	shuju[7]=b/16/16/16/16/16/16/16;
	for(i=7;i>=0;i--)
	{
		if(shuju[i]==0)
			shuju[i]=16;
		else if(shuju[i]!=0)//从高位开始检测是不是有0一旦检测到有0退出循环
			break;
	}
	for(i=0;i<8;i++)
	{
		switch(i)//位选
		{
			case 7: LSC=1;LSB=1;LSA=1;break;
			case 6: LSC=1;LSB=1;LSA=0;break;
			case 5: LSC=1;LSB=0;LSA=1;break;
			case 4: LSC=1;LSB=0;LSA=0;break;
			case 3: LSC=0;LSB=1;LSA=1;break;
			case 2: LSC=0;LSB=1;LSA=0;break;
			case 1: LSC=0;LSB=0;LSA=1;break;
			case 0: LSC=0;LSB=0;LSA=0;break;
		}
		SMG_A_DP_PORT=gsmg_code[shuju[i]];//传送段选数据
		delay(100);//延时一段时间,等待显示稳定
		SMG_A_DP_PORT=0x00;//消影
	}
}
 
void main()
{
	EA=1;
	configuart(9600);
	while(1)
	{
		smg_display(a);
		num=0;
		key=anjian_scan();
		if(key!=0)
			SBUF=key-1;
	}
}
 
void configuart(u16 baud)
{
	SCON=0x50;
	TMOD&=0x0f;
	TMOD|=0X20;
	TH1=256-(11059200/12/32/baud);
	TL1=TH1;
	ET1=0;
	TR1=1;
	ES=1;
}
 
void interruptUART() interrupt 4
{
	unsigned long int i,b,c;
	EA=0;
	if(RI==1)
	{
		RI=0;
		shuju[num]=SBUF;
		num++;
		flag=1;
	}
	EA=1;
	if(flag==1)               
	{
		a=0;
		for(i=0;i<num;i++)     
		{
			b=shuju[i]/16;
			c=shuju[i]%16;
			if(b!=0)
			{
				a=a*16*16+shuju[i];
			}else{
				a=a*16+c;
			}
		}
	}
	if(TI==1)
		TI=0;
}

代码(原先第一次写的旧代码只能实现传输<=255的数字)

#include <REGX52.H>

typedef unsigned char u8;
typedef unsigned int u16;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口

u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
u16 shuju[8]=0;
u16 a,key;//a用来接收收到的数字,key是接收到的按键

void configuart(u16 baud);

void delay (u16 time)
{
	while(time--);
}

u8 anjian_scan(void)
{
	static u8 keyvalue=0;
	KEY_MATRIX_PORT=0x0f;
	if(KEY_MATRIX_PORT!=0x0f)
	{
		delay(1000);
		if(KEY_MATRIX_PORT!=0x0f)
		{
			KEY_MATRIX_PORT=0x0f;
			switch(KEY_MATRIX_PORT)//保存行为 0,按键按下后的列值
			{
				case 0x07: keyvalue=1;break;
				case 0x0b: keyvalue=2;break;
				case 0x0d: keyvalue=3;break;
				case 0x0e: keyvalue=4;break;
			}
			KEY_MATRIX_PORT=0xf0;
			switch(KEY_MATRIX_PORT)//保存列为 0,按键按下后的键值
			{
				case 0x70: keyvalue=keyvalue;break;
				case 0xb0: keyvalue=keyvalue+4;break;
				case 0xd0: keyvalue=keyvalue+8;break;
				case 0xe0: keyvalue=keyvalue+12;break;
			}
			while(KEY_MATRIX_PORT!=0xf0);
		}
	}
	else
		keyvalue=0;
	return keyvalue;
}

void smg_display(u16 b)
{
	u8 i=0,flag=0;
	shuju[0]=b%10;
	shuju[1]=b/10%10;
	shuju[2]=b/100%10;
	shuju[3]=b/1000%10;
	shuju[4]=b/10000%10;
	shuju[5]=b/100000%10;
	shuju[6]=b/1000000%10;
	shuju[7]=b/10000000;
	for(i=7;i>=0;i--)
	{
		if(shuju[i]==0)
			shuju[i]=16;
		else if(shuju[i]!=0)//从高位开始检测是不是有0一旦检测到有0退出循环
			break;
	}
	for(i=0;i<8;i++)
	{
		switch(i)//位选
		{
			case 7: LSC=1;LSB=1;LSA=1;break;
			case 6: LSC=1;LSB=1;LSA=0;break;
			case 5: LSC=1;LSB=0;LSA=1;break;
			case 4: LSC=1;LSB=0;LSA=0;break;
			case 3: LSC=0;LSB=1;LSA=1;break;
			case 2: LSC=0;LSB=1;LSA=0;break;
			case 1: LSC=0;LSB=0;LSA=1;break;
			case 0: LSC=0;LSB=0;LSA=0;break;
		}
		SMG_A_DP_PORT=gsmg_code[shuju[i]];//传送段选数据
		delay(100);//延时一段时间,等待显示稳定
		SMG_A_DP_PORT=0x00;//消影
	}
}

void main()
{
	EA=1;
	configuart(9600);
	while(1)
	{
		smg_display(a);
		key=anjian_scan();
		if(key!=0)
			SBUF=key-1;
	}
}

void configuart(u16 baud)
{
	SCON=0x50;
	TMOD&=0x0f;
	TMOD|=0X20;
	TH1=256-(11059200/12/32/baud);
	TL1=TH1;
	ET1=0;
	TR1=1;
	ES=1;
}

void interruptUART() interrupt 4
{
	if(RI==1)//接收到字节
	{
		RI=0;
		a=SBUF;
	}
	if(TI==1)
		TI=0;
}

高位不显示的代码

原理:通过循环检测是否有0,如果检测到有0,则将该位赋值为16,对应数码管的就是0x00

注意的是我们数码管采用的是共阴数码管,所以0x00才是不显示。

for(i=7;i>=0;i--)
	{
		if(shuju[i]==0)
			shuju[i]=16;
		else if(shuju[i]!=0)//从高位开始检测是不是有0一旦检测到有0退出循环
			break;
	}

 注意还要在数码管数组那里补充一个0x00。

u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

特别注意:

在传输大于4位的时候要使用long int数据类型,如果使用int会导致长度不够而储存不下


实验步骤:

1、首先要打开串口助手页面,并打开串口

2、选择合适的波特率,这里根据代码我选择9600

 3、在发送缓冲区选择hex模式,注意这里填入的数字是以16进制返回,这就意味着填入10,数码管显示的是16,(如果我们想要达到输入10返回也是10,则需要在用数组重新变回原数字的时候/16,%16处理)(最新代码已经实现)且因为SBUF寄存器只有8位,所以最大只能填入FF,对应的10进制就是255(但是可以通过数组的形式暂时储存数据,然后等所有数据也就是带个字节都接受过来再处理重新组合成原来的数字)(最新代码已经实现)

4、在发送缓冲区填入数字即可看到对应的结果

5、任意按下对应的按钮即可看到接收缓冲区收到的数据


实验现象:

电脑在发送缓冲区输入9,数码管显示9

旧版代码效果最大只能传输255 

新版代码可以传输8位数下面是效果图(电脑端输入11223344)

 这是按钮0到7按下后收到的数据

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机的串口实验之数码管显示与按键实验(8位数字任意传输)

发表评论