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