📄 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 + -