欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

51单片机Proteus仿真+Keil工程-实验2-按键-数码管

程序员文章站 2022-06-21 20:54:18
实验2-单片机数码管按键实验(Proteus仿真+Keil工程):51单片机连接4x4矩阵按键外设,使用矩阵反转扫描方法,按下不同按键,在8段数码管上面显示0~F,十六个按键值。...

实验2-单片机数码管和按键实验

  之前做的一次实验,51单片机通过按键控制单个数码管。如有问题欢迎指正。

实验目标:

  通过建立4x4矩阵按键在8段数码管上面显示0~F,十六个按键值。

Proteus原理图

51单片机Proteus仿真+Keil工程-实验2-按键-数码管
选择元器件:

DEVICES 说明
7SEG-COM-ANODE 1位共阳极数码管
AT89C51 MCU
BUTTON 按键
CAP 普通电容
CAP-ELEC 电解电容
CRYSTAL 晶振
LED-BLUE 蓝色LED灯
RES 电阻
RESPACK-8 排阻

  51单片机的P0口做IO口使用时是漏极开路输出,其引脚一般需要在片外接一定阻值的上拉电阻,此时端口不存在高阻抗的悬浮状态,因此它是一个准双向口。同时,P0口每一位的驱动能力是P1~P3口的两倍,每位可以驱动8个LSTTL(Low-power Schottky TTL,即低功耗肖特基TTL)输入,89C51等单片机任何一个端口想要获得较大的驱动能力,必须采用低电平输出。
  时钟晶体振荡频率为fosc=12MHZf_{osc}=12MHZ
  时钟周期相当于Tosc=1fosc83.33nsT_{osc}=\frac{1}{f_{osc}} \approx 83.33ns
  复位电路的话通过给89C51等单片机的复位引脚RST加上大于2个机器周期的高电平(即24个时钟振荡周期)就可以使单片机复位。

KEIL工程:

主函数:

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SegPort P0
#define KeyPort P1
#define TIME 1000    		/*延时常量(ms)*/
#define SHAKING_TIME 10 	/*消抖时间(ms)*/
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};/*0123456789abcdef*/
void delay(uint i);
void display_digitron(uchar num);
uchar KeyScan(void);/*键盘扫描函数1*/
uchar KeyPro(void); /*键值返回函数1*/
void main(void)
{
	uchar num;
	while(1)
	{
		/*使用函数1*/
		num=KeyPro();
		if(num!=0xff)
		{
			display_digitron(num);
		}
		/*使用函数2:存在问题*/
	}
}
void delay(uint i)
{
	uchar t;
	while(i--)
	{
		for(t=0;t<120;t++);
	}
}

  我使用了两种控制方法,分别是矩阵反转扫描,行扫描,状态量扫描(有bug),放上了比较简洁的矩阵反转扫描。
  数码管显示函数:

void display_digitron(uchar num)
{
	SegPort=seg[num];
}

  键盘扫描函数:

/*键盘扫描函数,使用行列反转扫描法*/
uchar KeyScan(void)  
{
	unsigned char cord_h,cord_l;//行列值中间变量
	KeyPort=0x0f;            //行线输出全为0
	cord_h=KeyPort&0x0f;     //读入列线值
	if(cord_h!=0x0f)    	//先检测有无按键按下
	{
		delay(SHAKING_TIME);        //去抖
		if((KeyPort&0x0f)!=0x0f)
		{
			cord_h=KeyPort&0x0f;  //读入列线值
			KeyPort=cord_h|0xf0;  //输出当前列线值
			cord_l=KeyPort&0xf0;  //读入行线值
			while((KeyPort&0xf0)!=0xf0);//等待松开并输出
			return(cord_h+cord_l);//键盘最后组合码值
		}
	}return(0xff);     //返回该值
}

  按键处理函数:

/*按键处理函数1,返回键值*/
uchar KeyPro(void)
{
	switch(KeyScan())
	{
	case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
	case 0x7d:return 4;break;//4
	case 0x7b:return 8;break;//8
	case 0x77:return 12;break;//c
	case 0xbe:return 1;break;//1
	case 0xbd:return 5;break;//5
	case 0xbb:return 9;break;//9
	case 0xb7:return 13;break;//d
	case 0xde:return 2;break;//2
	case 0xdd:return 6;break;//6
	case 0xdb:return 10;break;//a
	case 0xd7:return 14;break;//e
	case 0xee:return 3;break;//3
	case 0xed:return 7;break;//7
	case 0xeb:return 11;break;//b
	case 0xe7:return 15;break;//f
	default:return 0xff;break;
	}
}

参考文献
1.《单片机原理与接口技术》张毅刚

返回目录

本文地址:https://blog.csdn.net/qq_43353985/article/details/107939728