使用中断的方式读写ZLG7290,写操作还可以,读操作不成功,小弟认为是I2C中断程序的问题,请帮忙一起分析下,谢谢了!!!<br />文件7290test.c<br />#include<reg935.h><br />#include<900I2C.h><br /><br />#define CSI24WC02 0xA0 /* i2c 定义器件地址 */<br />#define ZLG7290 0x70<br /><br />extern uint8 xdata I2C_sla; <br />extern uint8 xdata I2C_suba; <br />extern uint8 xdata I2C_suba_num; <br />extern uint8 xdata *I2C_buf; <br />extern uint8 xdata I2C_num; <br />extern uint8 xdata I2C_end; <br />extern uint8 xdata I2C_suba_en; <br /><br />uint8 xdata ReceiveBuffer=0;<br />uint8 xdata DisplayByte[16]={0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,0xF6,0x6E,0x20,0x70,0x0E,0x1C,0x3A,0xCE,0xE6,0x0A};<br />uint8 xdata DisplayByteFull[15]={0x70,0x03,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff};<br />uint8 xdata DisplayByte6[6]={0xEE,0x3E,0x9C,0x7A,0x9E,0x8E};<br />uint8 xdata DispatchTimer=0;<br /><br />bit TimerTick=0;<br />bit RequireSend=0;<br />bit ReceivedByte=0;<br />/****************************************************************************/<br />/****************************************************************************/<br />void InitializeSystem(void)<br />{<br /> P1M1=0xbc; //10111100B <br /> P1M2=0x4c; //01001100B <br /><br /> SCON=0xd0; //UART model 3,enable receive<br /> SSTAT=0x20; //UART individual interrupt<br /> BRGCON=0x00; //stop baud generate<br /> BRGR1=0x02; //9.6k<br /> BRGR0=0xF0; <br /> BRGCON=0x03; //run baud generate <br /><br /> I2CInit();<br /><br /> WDCON=0xe0; //关闭看门狗 <br /> RTCL=0xbf; //RTC low restore register,7.373MHz,0.15 second<br /> RTCH=0x21; //RTC high restore register<br /> RTCCON=0x63; //RTC use CCLK,enable RTC interrupt and RTC<br /><br /> IEN0=0xd0; //开CPU中断,UART,RTC,I2C,<br /> IEN1=0x41; <br />}<br />/****************************************************************************/<br />/****************************************************************************/<br />void main()<br />{<br /> uint8 i=0;<br /> uint8 j=0;<br /> uint8 TickTimes=0;<br /> uint8 DisplayUnit[2]={0x70,0x03};<br /> uint8 GetKeys[4]={0x11};<br /> InitializeSystem(); <br /><br /> while(1)<br /> {<br /> if(TimerTick==1)<br /> {<br /> TimerTick=0; <br /><br /> if(TickTimes<12)TickTimes++;<br /> else TickTimes=0;<br /><br /> if(TickTimes==2)<br /> {<br /> SBUF=GetKeys[0];<br /> DisplayByte6[5]=DisplayByte6[0];<br /> for(i=0;i<5;i++)DisplayByte6=DisplayByte6[i+1];<br /> I2C_WriteNByte(ZLG7290,ONE_BYTE_SUBA,0x10,DisplayByte6,4); //send data display<br /> }<br /> if(TickTimes==3)SBUF=GetKeys[1];<br /> if(TickTimes==4)SBUF=GetKeys[3];<br /> if(TickTimes==5)SBUF=GetKeys[3];<br /> if(TickTimes==6)<br /> {<br /> I2C_WriteNByte(ZLG7290,ONE_BYTE_SUBA,0x07,DisplayByteFull,2); //send data display<br /> if(j<4)j++;<br /> else j=0;<br /> DisplayByteFull[1]=1<<j;<br /> }<br /> //if(TickTimes==8)I2C_ReadNByte(ZLG7290,ONE_BYTE_SUBA,0x00,GetKeys,4); //这条指令老不成功<br /> }<br /> }<br />} <br />/****************************************************************************/<br />/****************************************************************************/<br />void int2() interrupt 10 //RTC 中断入口<br />{<br /> TimerTick=1;<br /> RTCCON=0x63; //clear interrupt <br />}<br />/****************************************************************************/<br />/****************************************************************************/<br />void int3() interrupt 4 //UART RI 中断入口<br />{ <br /> ReceiveBuffer=SBUF;<br /> ReceivedByte=1;<br /> RI=0;<br />}<br />/****************************************************************************/<br />/****************************************************************************/<br />void int4() interrupt 13 //UART TI 中断入口<br />{ <br /> TI=0;<br /> RequireSend=0; //release right of send<br />}<br />/****************************************************************************/<br />/***************************end of file**************************************/<br /><br /><br />文件900I2C.C<br />#include<900I2C.h><br />#include<reg935.h><br /><br />/* 定义用于和I2C中断传递信息的全局变量 */<br />volatile uint8 xdata I2C_sla; /* I2C器件从地址 */<br />volatile uint8 xdata I2C_suba; /* I2C器件内部子地址 */<br />volatile uint8 xdata I2C_suba_num; /* I2C子地址字节数 */<br />volatile uint8 xdata *I2C_buf; /* 数据缓冲区指针 */<br />volatile uint8 xdata I2C_num; /* 要读取/写入的数据个数 */<br />volatile uint8 xdata I2C_end=1; /* I2C总线结束标志:结束总线是置1 */<br />volatile uint8 xdata I2C_suba_en; /* 子地址控制。<br /> 0--子地址已经处理或者不需要子地址<br /> 1--读取操作<br /> 2--写操作 */<br /><br />/*******************************************************************************************************<br />* Function name:I2CInit()<br />*******************************************************************************************************/<br />void I2CInit(void)<br />{ <br /> I2SCLH=I2SCLL=15; //setting clock 7.373MHz/(15+15)/2=123KHz<br />}<br />/********************************************************************************************************<br />** 函数名称:ISendByte()<br />** 函数功能:向无子地址器件发送1字节数据。<br />** 入口参数:sla 器件地址<br />** dat 要发送的数据<br />********************************************************************************************************/<br />void ISendByte(uint8 sla, uint8 dat)<br />{ /* 参数设置 */<br /> I2C_sla = sla; // 写操作的器件地址<br /> I2C_buf = &dat; // 待发送的数据<br /> I2C_num = 1; // 发送1字节数据<br /> I2C_suba_en = 0; // 无子地址<br /> I2C_end = 0;<br /> <br /> I2CON=I2CON&0xd3; //清零SI STA AA位<br /> I2CON=I2CON|0x60; // 设置为主机,并启动总线<br />}<br />/********************************************************************************************************<br />** 函数名称:IRcvByte()<br />** 函数功能:向无子地址器件读取1字节数据。<br />** 入口参数:sla 器件地址<br />** dat 接收数据的变量指针<br />********************************************************************************************************/<br />void IRcvByte(uint8 sla, uint8 *dat)<br />{ /* 参数设置 */<br /> I2C_sla = sla+1; // 读操作的器件地址<br /> I2C_buf = dat;<br /> I2C_num = 1;<br /> I2C_suba_en = 0; // 无子地址<br /> I2C_end = 0;<br /><br /> I2CON=I2CON&0xd3; //清零SI STA AA位 <br /> I2CON=I2CON|0x60; // 设置为主机,并启动总线<br />}<br />/********************************************************************************************************<br />** 函数名称 :I2C_ReadNByte()<br />** 函数功能 :从有子地址器件任意地址开始读取N字节数据<br />** 入口参数 : sla 器件从地址<br />** suba_type 子地址结构 1-单字节地址 2-8+X结构 2-双字节地址<br />** suba 器件子地址<br />** s 数据接收缓冲区指针<br />** num 读取的个数<br />*******************************************************************************************************/<br />void I2C_ReadNByte (uint8 sla, uint8 suba_type, uint8 suba, uint8 *s, uint8 num)<br />{<br /> if (num > 0) /* 判断num个数的合法性 */<br /> { /* 参数设置 */<br /> if (suba_type == 1)<br /> { /* 子地址为单字节 */<br /> I2C_sla = sla + 1; /* 读器件的从地址,R=1 */<br /> I2C_suba = suba; /* 器件子地址 */<br /> I2C_suba_num = 1; /* 器件子地址为1字节 */<br /> }<br /> if (suba_type == 2)<br /> { /* 子地址为2字节 */<br /> I2C_sla = sla + 1; /* 读器件的从地址,R=1 */<br /> I2C_suba = suba; /* 器件子地址 */<br /> I2C_suba_num = 2; /* 器件子地址为2字节 */<br /> }<br /> if (suba_type == 3)<br /> { /* 子地址结构为8+X*/<br /> I2C_sla = sla + ((suba >> 7 )& 0x0e) + 1; /* 读器件的从地址,R=1 */<br /> I2C_suba = suba & 0x0ff; /* 器件子地址 */<br /> I2C_suba_num = 1; /* 器件子地址为8+x */<br /> }<br /> I2C_buf = s; /* 数据接收缓冲区指针 */<br /> I2C_num = num; /* 要读取的个数 */<br /> I2C_suba_en = 1; /* 有子地址读 */<br /> I2C_end = 0;<br /><br /> I2CON=I2CON&0xd3; //清零SI STA AA位 <br /> I2CON=I2CON|0x60; // 设置为主机,并启动总线<br /> }<br />}<br /><br />/********************************************************************************************************<br />** 函数名称 :I2C_WriteNByte()<br />** 函数功能 :向有子地址器件写入N字节数据<br />** 入口参数 : sla 器件从地址<br />** suba_type 子地址结构 1-单字节地址 3-8+X结构 2-双字节地址<br />** suba 器件内部物理地址<br />** *s 将要写入的数据的指针<br />** num 将要写入的数据的个数<br />********************************************************************************************************/<br />void I2C_WriteNByte(uint8 sla, uint8 suba_type, uint8 suba, uint8 *s, uint8 num)<br />{ <br /> if (num > 0)/* 如果读取的个数为0,则返回错误 */<br /> { /* 设置参数 */ <br /> if (suba_type == 1)<br /> { /* 子地址为单字节 */<br /> I2C_sla = sla; /* 读器件的从地址 */<br /> I2C_suba = suba; /* 器件子地址 */<br /> I2C_suba_num = 1; /* 器件子地址为1字节 */<br /> }<br /> if (suba_type == 2)<br /> { /* 子地址为2字节 */<br /> I2C_sla = sla; /* 读器件的从地址 */<br /> I2C_suba = suba; /* 器件子地址 */<br /> I2C_suba_num = 2; /* 器件子地址为2字节 */<br /> }<br /> if (suba_type == 3)<br /> { /* 子地址结构为8+X */<br /> I2C_sla = sla + ((suba >> 7 )& 0x0e); /* 读器件的从地址 */<br /> I2C_suba = suba & 0x0ff; /* 器件子地址 */<br /> I2C_suba_num = 1; /* 器件子地址为8+X */<br /> }<br /><br /> I2C_buf = s; /* 数据 */<br /> I2C_num = num; /* 数据个数 */<br /> I2C_suba_en = 2; /* 有子地址,写操作 */<br /> I2C_end = 0;<br /><br /> I2CON=I2CON&0xd3; //清零SI STA AA位 <br /> I2CON=I2CON|0x60; // 设置为主机,并启动总线<br /> }<br />}<br /><br />/********************************************************************************************************<br />** 函数名称 :I2CInterrupt ()<br />** 函数名次 :硬件I2C中断服务程序。 <br />********************************************************************************************************/<br />void I2CInterrupt() interrupt 6 //IIC 中断入口<br />{ <br /> switch (I2STAT & 0xF8)<br /> { /* 根据状态码进行相应的处理 */<br /> case 0x08: /* 已发送起始条件 */ /* 主发送和主接收都有 */<br /> /* 装入SLA+W或者SLA+R */<br /> if(I2C_suba_en == 1)/* SLA+R */ /* 指定子地址读 */<br /> { I2DAT = I2C_sla & 0xFE; /* 先写入地址 */<br /> }<br /> else /* SLA+W */<br /> { I2DAT = I2C_sla; /* 否则直接发送从机地址 */<br /> }<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> break;<br /> <br /> case 0x10: /*已发送重复起始条件 */ /* 主发送和主接收都有 */<br /> /* 装入SLA+W或者SLA+R */<br /> I2DAT = I2C_sla; /* 重起总线后,重发从地址 */<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> break;<br /><br /> case 0x18:<br /> case 0x28: /* 已发送I2DAT中的数据,已接收ACK */<br /> if (I2C_suba_en == 0)<br /> {<br /> if (I2C_num > 0)<br /> { I2DAT = *I2C_buf++;<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_num--;<br /> }<br /> else /* 没有数据发送了 */<br /> { /* 停止总线 */<br /> I2CON=I2CON|0x10; //stop bus,set on bit STO <br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_end = 1; /* 总线已经停止 */<br /> }<br /> }<br /> <br /> if(I2C_suba_en == 1) /* 若是指定地址读,则重新启动总线 */<br /> { <br /> if (I2C_suba_num == 2)<br /> { I2DAT = ((I2C_suba >> 8) & 0xff);<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_suba_num--;<br /> break; <br /> } <br /> <br /> if(I2C_suba_num == 1)<br /> { I2DAT = (I2C_suba & 0xff);<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_suba_num--;<br /> break; <br /> }<br /> <br /> if (I2C_suba_num == 0)<br /> { <br /> I2CON=I2CON|0x20; //start BUS,set on bit STA<br /> I2CON=I2CON&0xf7; //清零SI位<br /> I2C_suba_en = 0; /* 子地址己处理 */<br /> break;<br /> }<br /> }<br /> <br /> if (I2C_suba_en == 2)/* 指定子地址写,子地址尚未指定,则发送子地址 */<br /> {<br /> if (I2C_suba_num > 0)<br /> { if (I2C_suba_num == 2)<br /> { I2DAT = ((I2C_suba >> 8) & 0xff);<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_suba_num--;<br /> break;<br /> }<br /> if (I2C_suba_num == 1)<br /> { I2DAT = (I2C_suba & 0xff);<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_suba_num--;<br /> I2C_suba_en = 0;<br /> break;<br /> }<br /> }<br /> }<br /> break;<br /> <br /> case 0x40: /* 已发送SLA+R,已接收ACK */<br /> if (I2C_num <= 1) /* 如果是最后一个字节 */ <br /> { <br /> I2CON=I2CON&0xfb; //clear AA<br /> }<br /> else<br /> { <br /> I2CON=I2CON|0x04; //set AA<br /> }<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> break;<br /><br /> case 0x20: /* 已发送SLA+W,已接收非应答 */<br /> case 0x30: /* 已发送I2DAT中的数据,已接收非应答 */<br /> case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */<br /> case 0x48: /* 已发送SLA+R,已接收非应答 */<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_end = 0xFF; <br /> break; <br /> <br /> case 0x50: /* 已接收数据字节,已返回ACK */<br /> *I2C_buf++ = I2DAT;<br /> I2C_num--;<br /> if (I2C_num == 1)/* 接收最后一个字节 */<br /> { <br /> I2CON=I2CON&0xd3; //清零SI AA STA位<br /> }<br /> else<br /> { <br /> I2CON=I2CON|0x04; //set AA<br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> }<br /> break;<br /> <br /> case 0x58: /* 已接收数据字节,已返回非应答 */<br /> *I2C_buf++ = I2DAT; /* 读取最后一字节数据 */<br /> I2CON=I2CON|0x10; //stop bus,set on bit STO <br /> I2CON=I2CON&0xd7; //清零SI STA位<br /> I2C_end = 1; <br /> break;<br /> <br /> default:<br /> break;<br /> }<br />}<br /><br /><br />
|