51单片机Proteus仿真+Keil工程-实验6-单片机扩展RAM6264实验

实验6-单片机扩展RAM6264实验

  之前做的一次实验,51单片机扩展RAM6264实验。如有问题欢迎指正。

实验目的:

  掌握单片机扩展芯片的方法;掌握RAM6264的写入和读取;

实验内容:

  单片机、74LS573,82C55(A口和B口作为输出,C口作为输入)、8个数码管、按键信息从C口输入,端口地址A~控制寄存器依次为 ff7c,ff7d,ff7e,ff7cf(可以使用RAM6264)。按键做成4x4的矩阵按键,显示内容为你做实验的日期:例如: 2020.05.13。

实验环境:

   MDK-ARM V5.21a、Proteus 8.6

Proteus原理图

51单片机Proteus仿真+Keil工程-实验6-单片机扩展RAM6264实验_第1张图片
暂停仿真开始观察RAN区
51单片机Proteus仿真+Keil工程-实验6-单片机扩展RAM6264实验_第2张图片

选择元器件:

DEVICES 说明
7SEG-MPX8-CC-BLUE 八位共阴数码管
74HC573 锁存器
74LS373 锁存器
6264 RAM
AT89C51 MCU
BUTTON 按键
CAP 普通电容
CAP-ELEC 电解电容
CRYSTAL 晶振
RES 电阻
RESPACK-8 排阻

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

KEIL工程:

  1.鉴于51单片机的端口可能不够,我采用了两片74hc573芯片来进行数码管段码和位码的锁存,P2^ 5控制段选,P2^ 6控制位选。其中数码管使用共阴极数码管,注意数码管的二重消隐。
  2.单片机外部扩展1片外部数据存储器RAM6264。
  3.使用定时器t0工作方式1,在中断函数中对数码管进行扫描。
  4.键盘扫描使用矩阵反转扫描,并有与之匹配的按键处理函数。
  5.通过按下矩阵键盘,输入本次实验的日期,将本次日期写入RAM6264,并在数码管上显示。其中,为了节省端口,数码管采用两片74HC573;按键输入时,数码管会从右到左移位,当按第9次时输入无效,用来清屏。
  6.本程序有两种写入方式,一种是直接写入RAM6264在数码管显示,一种是按键输入,为了符合要求,我选择了后者。
  头文件以及宏定义等:

#include "reg52.h"
#include "absacc.h"//定义地址所需的头文件
#define uchar unsigned char
#define uint unsigned int
#define KeyPort P1
#define DataPort P0	
#define TIME 1000    		/*延时常量(ms)*/
#define SHAKING_TIME 10 	/*消抖时间(ms)*/
sbit LATCH1=P2^5;//定义锁存使能端口 段锁存
sbit LATCH2=P2^6;//                 位锁存
uchar code Duanma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};/*0123456789abcdef*/
uchar code Weima[] ={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};/*自左向右*/
uchar code Mydate[]={0x5b,0x3f,0x5b,0x3f,0x3f,0x7d,0x06,0x6f};	//用来事先直接写入RAM
uchar TempData[8];		
sbit LED=P2^7;
uchar num;//按键返回值

  主函数:

void main()
{
	uint i,j;
	uchar temp[8];
	Init_Timer0();

	/*1:直接写入RAM*/
//	LED=1;
//	/*在RAM6264写入数据*/
//	for(i=0;i<8;i++)					//向6264的0x0000地址开始写入实验日期:20200619
//	{
//		XBYTE[i]=Mydate[i];
//		delayMs(150);
//	}
//	LED=0;								//写入完毕,LED灯亮起
//	/*读取RAM数据到数码管段码数据缓存数组*/
//	for(i=0;i<8;i++)
//	{
//		TempData[i]=XBYTE[i];			//读取数据
//	}
//	while(1)
//	{
//		Display(0,8);
//	}
	
	/*2:按键输入写入RAM*/
	while (1)         //主循环
	{
		num=KeyPro();
		if(num!=0xff)
		{
			if(i==0)
			{
				for(j=0;j<8;j++)//清屏
					TempData[j]=0;
			}
			if(i<8)
			{
				XBYTE[i]=temp[i]=Duanma[num];	//把按键值输入到临时数组中,并写入RAM
				for(j=0;j<=i;j++)         		//把临时数组中的值赋值到显示缓冲区,从右往左输入
					TempData[7-i+j]=temp[j]; 
			}
			i++;   								//输入数值累加
			if(i==9)							//按的第9次用于清屏,此时按键不做输入值
			{
				i=0;
				
				for(j=0;j<8;j++)
				{
					TempData[j]=0;//清屏
					/*此处可以修改RAM:eg.XBYTE[i]=0;如果不修改,在下次输入时相当于覆盖0x0000~0x0008原来的值*/
				}
					

			}
		}	
	}
	
}

  中断初始化及子函数:

void Init_Timer0(void)
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	//TH0=0x00;	      //给定初值
	//TL0=0x00;
	EA=1;            //总中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}
void Timer0_isr(void) interrupt 1 
{
	TH0=(65536-2000)/256;		  //重新赋值 2ms
	TL0=(65536-2000)%256;
	Display(0,8);       		  //调用数码管扫描
}

  显示函数:

void Display(uchar FirstBit,uchar Num)
{
	static uchar i=0;
	DataPort=0;   				 //清空数据,防止有交替重影
	LATCH1=1;    				 //段锁存
	LATCH1=0;

	DataPort=Weima[i+FirstBit];  //取位码 
	LATCH2=1;     				 //位锁存
	LATCH2=0;

	DataPort=TempData[i]; 		 //取显示数据,段码
	LATCH1=1;     				 //段锁存
	LATCH1=0;

	i++;
	if(i==Num)
		i=0;
}

  键盘扫描函数:

/*键盘扫描函数,使用行列反转扫描法*/
uchar KeyScan(void)  
{
	unsigned char cord_h,cord_l;//行列值中间变量
	KeyPort=0x0f;            	//行线输出全为0
	cord_h=KeyPort&0x0f;     	//读入列线值
	if(cord_h!=0x0f)    		//先检测有无按键按下
	{
		delayMs(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);     //返回该值
}

  按键处理函数:

/*按键处理函数,返回键值*/
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;
	}
}
/*uS级延时函数*/
void DelayUs2x(uchar t)
{   
	while(--t);
}
/*MS级延时函数*/
void delayMs(uchar t)
{ 
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

更新补充

关于RAM数据的查看

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

返回目录

你可能感兴趣的:(51单片机,Proteus仿真,Keil工程,单片机,proteus,51单片机)