基于c8051f020单片机的SPI按键显示接口设计

书接上文,上一篇扫描键盘使用的时查询方式,还有一种识别方式是中断,那么在这一篇中使用中断来进行单片机对按键的识别。
本次实验使用了c8051f020和ZLG_7289芯片
一.实验目的

1.掌握ZLG7289专用按键显示芯片电路设计。
2.掌握SPI通信程序设计方法。
3.掌握基于ZLG7289按键显示驱动程序设计。

二.实验内容

设计一个定时器。要求:能够输入定时时长,定时最长时间为 9 分 59
秒;按启动键后开始计时,数码管显示当前计时时长,显示格式为:X.XX.X;每 200 ms
刷新一次数码管显示的数值;定时时间到达后,用数码管闪烁指示。 定时器的工作状态用功能按键控制,设功能按键为:启动键、暂停键、清零键。

当单片机复位后进入等待输入定时时间状态,用户可以输入定时时间,输入的时间同时在数码管上显示;当输入定时时间后,按启动键,定时器开始计时,数码管显示当前计时时间。再次按暂停键,定时器暂停计时,数码管显示当前计时时间;再次按暂停键,定时器继续计时。按清零键,定时器停止计时,并清零计时值,数码管显示为零,定时器进入等待输入状态。

三. 实验说明

实验使用的ZLG_7289的c和h文件需要从网上下载,完成后需要将.h文件添加至工程中。c文件包含了初始化ZLG_7289的函数,也需要添加至工程中,或者将函数复制到你的代码中。

四.实验代码

#include "ZLG7289.h"
#include "c8051f020.h"
sbit ZLG7289_pinCS=P3^3; //片选信号,低电平有效
sbit ZLG7289_pinCLK=P3^4; //时钟信号,上升沿有效
sbit ZLG7289_pinDIO=P3^5; //数据信号,双向
sbit ZLG7289_pinINT=P3^7; //键盘中断请求信号,低电平(负边沿)有效*/
unsigned int ms;
unsigned char min,s,j,k,x,count;
bit p,w;

//#include "c8051f020.h"
//定义一个全局变量,用于延时
//该变量在调用函数ZLG7289_Init()时被初始化
unsigned char ZLG7289_Delay_t;
/*
宏定义:ZLG7289_ShortDelay()
功能:短延时
说明:延时(ZLG7289_Delay_t*2+2)个机器周期
*/
#define ZLG7289_ShortDelay() \
{\
unsigned char t = ZLG7289_Delay_t;\
while ( --t != 0 );\
}
/*
宏定义:ZLG7289_LongDelay()
功能:长延时
说明:延时(ZLG7289_Delay_t*12+8)个机器周期
*/
#define ZLG7289_LongDelay() \
{\
unsigned char t = ZLG7289_Delay_t * 6;\
while ( --t != 0 );\
}
/*
函数:ZLG7289_SPI_Write()
功能:向SPI 总线写入1 个字节的数据
参数:
dat:要写入的数据
*/
void ZLG7289_SPI_Write(char dat)    // reentrant//去除可重入属性,否则程序不能正常运行
{
unsigned char t = 8;
do
{
ZLG7289_pinDIO = (bit)(dat & 0x80);
dat <<= 1;
ZLG7289_pinCLK = 1;
ZLG7289_ShortDelay();
ZLG7289_pinCLK = 0;
ZLG7289_ShortDelay();
} while ( --t != 0 );
}
/*
函数:ZLG7289_SPI_Read()
功能:从SPI 总线读取1 个字节的数据
返回:
读取到的数据
*/
char ZLG7289_SPI_Read()      //reentrant //   去除可重入属性,否则程序不能正常运行
{
char dat;
unsigned char t = 8;
ZLG7289_pinDIO = 1; //读取数据之前DIO 引脚要置1 以切换到输入状态
do
{
ZLG7289_pinCLK = 1;
ZLG7289_ShortDelay();
dat <<= 1;
if ( ZLG7289_pinDIO ) dat++;
ZLG7289_pinCLK = 0;
ZLG7289_ShortDelay();
} while ( --t != 0 );
return dat;
}
/*
函数:ZLG7289_cmd()
功能:执行ZLG7289 纯指令
参数:
cmd:命令字
*/
void ZLG7289_cmd(char cmd)
{
char sav = IE;
IE &= 0xFA; //关闭外部中断
ZLG7289_pinCS = 0;
ZLG7289_LongDelay();
ZLG7289_SPI_Write(cmd);
ZLG7289_pinCS = 1;
ZLG7289_LongDelay();
IE = sav; //恢复IE
}
/*
函数:ZLG7289_cmd_dat()
功能:执行ZLG7289 带数据指令
参数:
cmd:命令字
dat:数据
*/
void ZLG7289_cmd_dat(char cmd, char dat)
{
char sav = IE;
IE &= 0xFA; //关闭外部中断
ZLG7289_pinCS = 0;
ZLG7289_LongDelay();
ZLG7289_SPI_Write(cmd);
ZLG7289_LongDelay();
ZLG7289_SPI_Write(dat);
ZLG7289_pinCS = 1;
ZLG7289_LongDelay();
IE = sav; //恢复IE
}
/*
函数:ZLG7289_Download()
功能:下载数据
参数:
mod=0:下载数据且按方式0 译码
mod=1:下载数据且按方式1 译码
mod=2:下载数据但不译码
x:数码管编号(横坐标),取值0~7
dp=0:小数点不亮
dp=1:小数点亮
dat:要显示的数据
说明:
译码方式的具体含义请参考数据手册
*/
void ZLG7289_Download(unsigned char mod, char x, bit dp, char dat)
{
code char ModDat[3] = {0x80,0xC8,0x90};
char d1;
char d2;
if ( mod > 2 ) mod = 2;
d1 = ModDat[mod];
x &= 0x07;
d1 |= x;
d2 = dat & 0x7F;
if ( dp ) d2 |= 0x80;
ZLG7289_cmd_dat(d1,d2);
}
/*
功能:执行ZLG7289 键盘命令
返回:
返回读到的按键值:0~63
如果返回0xFF 则表示没有键按下
*/
char ZLG7289_Key()// reentrant  //去除可重入属性,否则程序不能正常运行
{
char key;
ZLG7289_pinCS=0;
ZLG7289_LongDelay();
ZLG7289_SPI_Write(0x15);
ZLG7289_LongDelay();
key = ZLG7289_SPI_Read();
ZLG7289_pinCS = 1;
ZLG7289_LongDelay();
return key;
}
/*
函数:ZLG7289_Init()
功能:ZLG7289 初始化
参数:
t:SPI 总线的延时值设置,取值1-40(超出范围可能导致错误)
说明:
t的取值可以参照以下公式:t >= 5 * f1 / f2,其中f1 表示80C51 的
晶振频率,f2 表示ZLG7289 的晶振频率
*/
void ZLG7289_Init(unsigned char t)
{
unsigned char x;
//I/O 口初始化
ZLG7289_pinCS = 1;
ZLG7289_pinCLK = 0;
ZLG7289_pinDIO = 1;
ZLG7289_pinINT = 1;
//延时初始化
ZLG7289_Delay_t = t;
//点亮所有数码管
for ( x=0; x<8; x++ )
{
ZLG7289_Download(1,x,1,8);
}
}
void xianshi()  //显示
{
   
	if(count==10)
	{
	    ZLG7289_Download(1,0,1,min);
	    ZLG7289_Download(1,1,0,s/10);
	    ZLG7289_Download(1,2,1,s%10);
	    ZLG7289_Download(1,3,0,ms%100/10/2*2);
	  if(ms==0)
	    ZLG7289_Flash(0xe0);
}

}
void jianjianjian()
{
    if(ms==0)
  {
      TR0=0;
  }
    else
  { 
      ms=ms-2;
  }
   min=ms/6000;
   s=ms%6000/100;
 }
 
 void plus()
 { 
      ms=min*6000+s*100;
 }

 void anjian()
 {
		if(j==0&&TR0==0)
	  {
	   TR0=1;
	   while(!ZLG7289_pinINT);//等待按键释放
	  }
	  else if(j==1)//pause
	  {
	   TR0=0;
	   while(!ZLG7289_pinINT);
	  }
	  else if(j==2)//clear
	  {
	   TR0=0;
	   ms=0;
	   min=0;
	   s=0;
	   for(k=0;k<4;k++)
	   {
	    if(k==0||k==2)
		ZLG7289_Download(1,k,1,0);
			
		else
		ZLG7289_Download(1,k,0,0);
	   }
	   ZLG7289_Flash(0xff);
      while(!ZLG7289_pinINT);
	  }
	else if(j==4)
	  {
	   if(min>=9)
	   {
	    min=0;
	   }
	   else
	   {
	    min++;
	   }
	   plus();
	
	   ZLG7289_Download(1,0,1,min);
	   while(!ZLG7289_pinINT);
	  }
	  else if(j==5)
	  {
	   if(s>=59)
	   {
	    s=0;
	   }
	   else
	   {
	    s++;
	   }
	   plus();
	   ZLG7289_Download(1,1,0,s/10);
	   ZLG7289_Download(1,2,1,s%10);
	   while(!ZLG7289_pinINT);
	 }
}
 void main()
 {
	 
	EA=0;
  WDTCN = 0xDE;
	WDTCN = 0xAD;
  EA=1;
	OSCXCN=0x77;
	OSCXCN=0x88;
	XBR2=0x40;
	P3MDOUT=0xff;
  p=0;
	w=0;
	ZLG7289_Init(40); //调用ZLG7289 的初始化函数
	count=0;
	ms=0;
	min=0;
	s=0;
	CKCON=0x08;//系统时钟
	TMOD=0x01;
	TH0=(65536-20000)/256;
	TL0=(65536-20000)%256;
	TR0=0;
	ET0=1;
	PT0=1;
	EIE2=0x20;
	ZLG7289_ShortDelay();
	for(k=0;k<4;k++)
	{ 
	  if(k==0||k==2)
	  ZLG7289_Download(1,k,1,0);
	  else
	  ZLG7289_Download(1,k,0,0);
	}
	ZLG7289_Hide(0x0f);
	while(1)
	{
		 if(w==1)
	 { 
		 anjian();
		 w=0;
	  }
 	 if(p==1)
 	 { 
		
		 count=10;
	   jianjianjian();
	   xianshi();
	  p=0;
	 } 		
}
	 
}
	 
	  
	void qaq() interrupt 1 using 2
	{
	p=1;
  		while(count)
  		{
	 TH0=(65536-20000)/256;
	 TL0=(65536-20000)%256;
		
	 count=count-1;
 	   }

	}
  
	void aqa() interrupt 19
	{
	  w=1;	
		j=ZLG7289_Key();
		
		 P3IF=0;
	}



另说明一下,这次使用的时钟是外部24MHz,二分频。采用外部中断7,对应的终端控制字是19,主函数中注意对外部中断进行初始化,中断函数内部结束时要对中断清零。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值