⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlg7290.c

📁 zlg7290的程序
💻 C
字号:
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <stdio.h>
#include <math.h>

#define uint  unsigned int
#define uchar unsigned char
#define x     0x80
#define y     0x80
#define comm  0
#define dat1   1

#define ZLG7290_I2C_ADDR	0x38 //ZLG7290的IIC地址
#define ZLG7290_Key			0x01		//键值寄存器
#define I2C_DELAY_VALUE		12
#define I2C_STOP_WAIT_VALUE	120
sbit 	I2C_SDA=P1^3;            //模拟I2C数据传送位
sbit I2C_SCL=P1^4;            //模拟I2C时钟控制位
           
 
#define  _Nop()  _nop_()        //定义空指令
volatile bit flagint0 = 0;
sbit rs = P1^1;   //H=data; L=command;
sbit rw = P1^0;   //H=read; L=write;
sbit  e = P1^7;   //input enable;
sbit busy=P0^7;   //lcd busy bit

void wr_lcd (uchar dat_comm,uchar content);
void chk_busy (void);
void delay (uint us);
//I2C总线初始化,使总线处于空闲状态

void I2C_Stop();


//I2C总线综合发送函数,向从机发送多个字节的数据
 void I2C_Delay();
void I2C_Start();
void I2C_Write(uchar dat);
char I2C_Read();
bit I2C_GetAck();
void I2C_PutAck(bit ack);

//I2C总线综合接收函数,从从机接收多个字节的数据
bit I2C_Gets(unsigned char SlaveAddr,unsigned int SubAddr,unsigned char SubMod,uchar *dat,unsigned char Size);


bit ZLG7290_ReadReg(unsigned char RegAddr, uchar *dat);

void chn_disp (uchar code *chn);
void init_lcd (void);
void clrram (void);
void wr_lcd (uchar dat_comm,uchar content);
void chk_busy (void);
void delay (uint us);
 void del(uchar i,uchar *p);
uchar code tab1[]={
"输入值:"};

uchar code tab2[]={
"输出值:"};

unsigned char data I2C_Delay_t;

/*
宏定义:I2C_Delay()
功能:延时,模拟I2C总线专用
*/
void I2C_Delay()
{
	I2C_Delay_t=(I2C_DELAY_VALUE);
	while (--I2C_Delay_t!=0);
}
/*
函数:I2C_Init()
功能:I2C总线初始化,使总线处于空闲状态
说明:在main()函数的开始处,通常应当要执行一次本函数
*/
/*void I2C_Init()
{
	I2C_SCL =1;
	I2C_Delay();
	I2C_SDA =1;
	I2C_Delay();
}
/*
函数:I2C_Start()
功能:产生I2C总线的起始状态
说明:
	SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
	不论SDA和SCL处于什么电平状态,本函数总能正确产生起始状态
	本函数也可以用来产生重复起始状态
	本函数执行后,I2C总线处于忙状态
*/
void I2C_Start()
{
	I2C_SDA=1;
	I2C_Delay();
	I2C_SCL=1;
	I2C_Delay();
	I2C_SDA =0;
	I2C_Delay();
	I2C_SCL=0;
	I2C_Delay();
}
/*
函数:I2C_Write()
功能:向I2C总线写1个字节的数据
参数:
	dat:要写到总线上的数据
*/
void I2C_Write(uchar dat)
{
	unsigned char t=8;
	do
	{
		I2C_SDA=(bit)(dat&0x80);
		dat <<=1;
		I2C_SCL=1;
		I2C_Delay();
		I2C_SCL=0;
		I2C_Delay();
	} while (--t!=0);
}
/*
函数:I2C_Read()
功能:从从机读取1个字节的数据
返回:读取的一个字节数据
*/
char I2C_Read()
{
	uchar dat;
	unsigned char t=8;
	I2C_SDA=1;	
	do
	{
		I2C_SCL=1;
		I2C_Delay();
		dat<<=1;
		if (I2C_SDA)dat|=0x01;
		I2C_SCL=0;
		I2C_Delay();
	} while(--t!=0);
	return dat;
}
/*函数:I2C_GetAck()
功能:读取从机应答位
返回:
	0:从机应答
	1:从机非应答
说明:
	从机在收到每个字节的数据后,要产生应答位
	从机在收到最后1个字节的数据后,一般要产生非应答位
*/
bit I2C_GetAck()
{
	bit ack;
	I2C_SDA = 1;
	I2C_Delay();
	I2C_SCL = 1;
	I2C_Delay();
	ack = I2C_SDA;
	I2C_SCL = 0;
	I2C_Delay();
	return ack;
}
/*
函数:I2C_PutAck()
功能:主机产生应答位或非应答位
参数:
	ack=0:主机产生应答位
	ack=1:主机产生非应答位
说明:
	主机在接收完每一个字节的数据后,都应当产生应答位
	主机在接收完最后一个字节的数据后,应当产生非应答位
*/
void I2C_PutAck(bit ack)
{
	I2C_SDA = ack;
	I2C_Delay();
	I2C_SCL = 1;
	I2C_Delay();
	I2C_SCL = 0;
	I2C_Delay();
}

/*
函数:I2C_Stop()
功能:产生I2C总线的停止状态
说明:
	SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
	不论SDA和SCL处于什么电平状态,本函数总能正确产生停止状态
	本函数执行后,I2C总线处于空闲状态
*/
void I2C_Stop()
{
	unsigned int t = I2C_STOP_WAIT_VALUE;
	I2C_SDA = 0;
	I2C_Delay();
	I2C_SCL = 1;
	I2C_Delay();
	I2C_SDA = 1;
	I2C_Delay();
	while ( --t != 0 );		//在下一次产生Start之前,要加一定的延时
}
/*
函数:I2C_Puts()
功能:I2C总线综合发送函数,向从机发送多个字节的数据
参数:
	SlaveAddr:从机地址(7位纯地址,不含读写位)
	SubAddr:从机的子地址
	SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
	*dat:要发送的数据
	Size:数据的字节数
返回:
	0:发送成功
	1:在发送过程中出现异常
说明:
	本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址
	当从机没有子地址时,参数SubAddr任意,而SubMod应当为0
*/
/*bit I2C_Puts
(
	unsigned char SlaveAddr,
	unsigned int SubAddr,
	unsigned char SubMod,
	char *dat,
	unsigned int Size
)
{
//定义临时变量
	unsigned char i;
	char a[3];
//检查长度
	if ( Size == 0 ) return 0;
//准备从机地址
	a[0] = (SlaveAddr << 1);
//检查子地址模式
	if ( SubMod > 2 ) SubMod = 2;
//确定子地址
	switch ( SubMod )
	{
	case 0:
		break;
	case 1:
		a[1] = (char)(SubAddr);
		break;
	case 2:
		a[1] = (char)(SubAddr >> 8);
		a[2] = (char)(SubAddr);
		break;
	default:
		break;
	}
//发送从机地址,接着发送子地址(如果有子地址的话)
	SubMod++;
	I2C_Start();
	for ( i=0; i<SubMod; i++ )
	{
		I2C_Write(a[i]);
		if ( I2C_GetAck() )
		{
			I2C_Stop();
			return 1;
		}
	}
//发送数据
	do
	{
		I2C_Write(*dat++);
		if ( I2C_GetAck() ) break;
	} while ( --Size != 0 );
//发送完毕,停止I2C总线,并返回结果
	I2C_Stop();
	if ( Size == 0 )
	{
		return 0;
	}
	else
	{
		return 1;
	}
}    

/*
函数:I2C_Gets()
功能:I2C总线综合接收函数,从从机接收多个字节的数据
参数:
	SlaveAddr:从机地址(7位纯地址,不含读写位)
	SubAddr:从机的子地址
	SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
	*dat:保存接收到的数据
	Size:数据的字节数
返回:
	0:接收成功
	1:在接收过程中出现异常
说明:
	本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址
	当从机没有子地址时,参数SubAddr任意,而SubMod应当为0
*/
bit I2C_Gets(unsigned char SlaveAddr,unsigned int SubAddr,unsigned char SubMod,uchar *dat,unsigned int Size)
{

	unsigned char i;
	uchar a[3];
   if (Size==0)return 0;
   a[0]=(SlaveAddr<<1);

	if (SubMod >2 )SubMod = 2;

	if ( SubMod != 0 )
	{

		if (SubMod==1)
		{
			a[1]=(uchar)(SubAddr);
		}
		else
		{
			a[1]=(uchar)(SubAddr >>8);
			a[2]=(uchar)(SubAddr);
		}
	
		SubMod++;
		I2C_Start();
		for ( i=0; i<SubMod; i++ )
		{
			I2C_Write(a[i]);
			if (I2C_GetAck())
			{
				I2C_Stop();
				return 1;
			}
		}
	}

I2C_Start();
I2C_Write(a[0]+1);
	if ( I2C_GetAck() )
	{
		I2C_Stop();
		return 1;
	}
//接收数据
	for (;;)
	{
		*dat++ = I2C_Read();
		if (--Size==0 )
		{
			I2C_PutAck(1);
			break;
		}
		I2C_PutAck(0);
	}
//接收完毕,停止I2C总线,并返回结果
	I2C_Stop();
	return 0;
}

/*
函数:ZLG7290_ReadReg()
功能:从ZLG7290的某个内部寄存器读出数据
参数:
	RegAddr:ZLG7290的内部寄存器地址
	*dat:保存读出的数据
返回:
	0:正常
	1:访问ZLG7290时出现异常
*/
bit ZLG7290_ReadReg(unsigned char RegAddr, uchar *dat)
{
	bit b;
	b=I2C_Gets(ZLG7290_I2C_ADDR,RegAddr,1,dat,1);
	return b;
}



/*------------------初始化-----------------*/
void init_lcd (void)
{
  wr_lcd (comm,0x30);  /*30---基本指令动作*/   
  wr_lcd (comm,0x01);  /*清屏,地址指针指向00H*/
  wr_lcd (comm,0x06);  /*光标的移动方向*/
  wr_lcd (comm,0x0c);  /*开显示,关游标*/
}
/*---------------显示汉字或字符----------------*/
void chn_disp (uchar code *chn,uchar j,uchar ad)
{
   uchar i=0;
  wr_lcd(comm,0x30);
  if(j==0) wr_lcd(comm,(0x80+ad));
	else wr_lcd(comm,(0x90+ad));
 while((chn[i]!='\0')&&(i<(16-ad)))
 {
  wr_lcd(dat1,chn[i]);
  i++;
  }
  }
/*--------------清DDRAM------------------*/
void clrram (void)
{
  wr_lcd (comm,0x30);
  wr_lcd (comm,0x01);
}
/*---------------------------------------*/
void wr_lcd (uchar dat_comm,uchar content)
{
  chk_busy ();
  if(dat_comm)
   {
    rs=1;   //data
    rw=0;   //write
   }
  else 
   {
    rs=0;   //command
    rw=0;   //write
   }
  P0=content;   //output data or comm
  e=1;
 
  e=0;
}

void chk_busy (void)
{
  P0=0xff;
  rs=0;
  rw=1;
  e =1;
  while(busy==1);
  e =0;
}
/*---------------------------------------*/
void delay (uint us)   //delay time
{
  while(us--);
}

 
/*void delay1 (uint ms)
{
  uint i,j;
  for(i=0;i<ms;i++)
  for(j=0;j<15;j++)
  delay(1);
}
/*******************************************************************
函数:INT0_SVC()
功能:ZLG7290 键盘中断服务程序
说明:中断触发方式选择负边沿触发,因此不必等待中断请求信号恢复为高电平
********************************************************************/
void INT0_SVC() interrupt 0 using 1
{
  flagint0=1;
}

/*void send_byte(uchar buf)
{
	SBUF=buf+'0';
	while(TI==0);TI=0;
 }*/
/*------------------主程序--------------------*/
void main()
{
unsigned char key;
//uchar  *p;
uchar s;
uchar buf[10];
init_lcd();
chn_disp(tab1,0,0);
delay(1000);
EA=0;
IT0=1;
IE0=1;
EX0=1;
SCON=0x50;//串行方式2
TMOD=0x20;
TH1=0xd8;
TL1=0xd8;
EA=1;
   for(;;)
   {
    
     if(flagint0==1)
       { 
		     flagint0=0;
           TR1=1;

         ZLG7290_ReadReg(ZLG7290_Key,&key);
			switch(key)
           {
			 case 5:buf[0]=key+43;wr_lcd(dat1,buf[0]);delay(100);break; //以前指针用的不正确	朱科 
             case 6:buf[1]=key+43;wr_lcd(dat1,buf[1]);delay(100);break;
             case 7:buf[2]=key+43;wr_lcd(dat1,buf[2]);delay(100);break;
             case 8:buf[3]=key+43;wr_lcd(dat1,buf[3]);delay(100);break;
             case 13:buf[4]=key+39;wr_lcd(dat1,buf[4]);delay(100);break;
             case 14:buf[5]=key+39;wr_lcd(dat1,buf[5]);delay(100);break;
             case 15:buf[6]=key+39;wr_lcd(dat1,buf[6]);delay(100);break;
             case 16:buf[7]=key+39;wr_lcd(dat1,buf[7]);delay(100);break;
             case 21:buf[8]=key+35;wr_lcd(dat1,buf[8]);delay(100);break;
             case 22:buf[9]=key+35;wr_lcd(dat1,buf[9]);delay(100);break;
             case 23:s='.';wr_lcd (dat1,s);delay(100);break;
		     case 29:EA=0;break;
		     case 30:init_lcd();chn_disp(tab1,0,0);delay(1000);break;
		     case 31:clrram();break;  //看看这个键值是不是由问题,看资料  朱科
			 default:break;
           }
         }  
 
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -