I2C存储器读写实验C源程序 #include <regx52.h> #include <stdio.h> #define uchar unsigned char #define uint unsigned int uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//各数字的数码管段码(共阴) //==============I2C, Define============================================== sbit scl=P2^7; sbit sda=P2^6; bit flag;//应答位 //=========================延时,I2C时序用 void delay(void)//延时子程序 { uchar i; for(i=0;i<6;i++); ; } //=========================I2C模拟时序部分 void I_start(void)//发送I2C总线起始条件子程序 { sda=1; scl=1; delay(); sda=0; delay(); scl=0; } void I_stop(void) //I2C总线停止条件子程序 { sda=0; scl=1; delay(); sda=1; delay(); } bit ACK_check(void) //应答位检查子程序 { bit flag; sda=1;//ready for receiving ACK scl=1; //start receiving ack delay(); if(sda==0) flag=0; else flag=1; scl=0; return(flag);//return ACK or NACK } void I_send(uchar I_data) //字节数据发送子程序,每发送一字节后要调用一次ACK_check子程序 { uchar i; for(i=0;i<8;i++) { sda=(bit)(I_data&0x80);//高位在先 I_data=I_data<<1; scl=1; delay(); scl=0; } } void ACK_send(void) //发送应答位子程序 { sda=0;//发送ACK scl=1; delay(); scl=0; } void NACK_send(void) //发送应答位子程序 { sda=1;//发送NACK scl=1; delay(); scl=0; } uchar I_receive(void) //字节数据接收子程序,每取一字节要发送一个应答/非应答信号 { uchar i; uchar I_data=0; sda=1; for(i=0;i<8;i++) { scl=1; delay(); I_data*=2;//等同于I_data=I_data<<1; if(sda==1) I_data++; scl=0; } return(I_data); } //N字节数据发送子程序 //slave:器件寻址命令字 //subaddr:器件内部子地址 //num:欲发送字节数 //p_date:发送缓冲区首地址 void I_Nsend(uchar slave,uchar subaddr,uchar num,uchar *p_data) { uchar i; bit flag; //发送器件寻址命令字 I_start(); I_send(slave); flag=ACK_check(); if(flag==1) { printf(%s,Send Slave NACK); return; } //发送器件内部子地址 I_send(subaddr); flag=ACK_check(); if(flag==1) { printf(%s,Send Subaddr NACK); return; } //发送数据 for(i=0;i<num;i++) { I_send(*p_data); flag=ACK_check(); if(flag==1) { printf(%s,Send Date NACK); return; } p_data++; } I_stop(); } //N字节数据接收子程序 //slave:器件寻址命令字 //num:欲接收字节数 void I_Nreceive(uchar slave,uchar num,uchar *p_data) //欲指定读取地址则需要先调用发送程序发送subaddr { uchar i; bit flag; //发送器件寻址命令字 I_start(); I_send(slave); flag=ACK_check(); if(flag==1) { printf(%s,Send Slave NACK); return; } //接收数据=============== for(i=num;i>0;i--) { *p_data=I_receive(); if(i>1) { ACK_send(); p_data++; } else NACK_send(); } I_stop(); } //============================================================================ //延时 void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i<120;i++); } //显示 void Display_Result(void) { P2=0xfe; P0=0x77;//A DelayMS(300); P2=0xfd; P0=0x39;//显示小数点,分割分和秒 DelayMS(300); P2=0xfb; P0=0x73; DelayMS(300); } //主程序 void main() { uchar i; uchar p_send[16];//定义发送缓冲区 uchar p_read[16];//接收缓冲区 uchar slave;//器件寻址命令字 uchar subaddr;//器件内部子地址 uchar num;//发送或接收字节数 for(i=0;i<16;i++) p_send[i]=i; slave=0xa0;//24C01C地址字,写操作 subaddr=0x30;//目标地址 num=16;//字节数 I_Nsend(slave,subaddr,num,p_send);//写操作 DelayMS(20); slave=0xa1;//24C01C地址字,读操作 I_Nreceive(slave,num,p_read);//读操作 while(1) { Display_Result(); } } |