源代码是由几个部分拼凑起来,其中一个重要的部分就是单片机对24LC02进行I2C总线读写,这部分是从一个例子中得到,但是原来的例子中有错误,原班不动地照抄到你自己的程序中去,就会发现单片机根本无法对24LC02读写。经过纠正,可以仿真通过了。纠正的地方我已经做了记号,也就是“!!!!!!!!!!!!”。 //24C02读写的C程序 //晶振对24C02影响特别大,排版要避开。 //试验证实必须接上拉电阻 //I2C 24LC02 C读写例程(PIC16F73单片机) /******************************************************************* 一、程序说明: 1, 24LC02器件地址是1010000R/W. 2, 数组写入24LC02采取页写方式. 3, 数组code从24LC02读出时采取自由读方式. 4, 采用4.00M晶体。 (后来改成20M,所以延时参数有所调整。) 5,采用软件I2C。 二、硬件连接: 1, SDA------->15 pin.(当然你可以任意选择脚位) 2, SCL------->14 Pin.(当然你可以任意选择脚位) *******************************************************************/ void start_i2c(); void stop_i2c(); void send_byte(uchar c); uchar receive_byte(); void I_send_str(uchar sla,uchar suba,uchar *s,uchar no); void delay_250ms(); void i2c_error (); /******************************************************************* 起动总线函数 函数原型: void start_i2c(); Function: start on the I2C bus *******************************************************************/ void start_i2c() { SDA=1; //发送启始条件的数据信号 nop(); SCL=1; nop();nop();nop();nop();nop(); //24LC02要求建立时间大于4.7uS SDA=0; //发送起始信号 nop();nop();nop();nop();nop(); SCL=0; //钳住I2C总线,准备发送数据或接收数据 nop();nop(); } /******************************************************************* 停止总线函数 函数原型: void stop_i2c(); Function: stop the I2C bus *******************************************************************/ void stop_i2c() { SDA=0; //发送结束条件的数据信号 nop(); SCL=1; nop();nop();nop();nop();nop(); SDA=1; nop();nop();nop();nop(); } /*================================================================= 字节数据传送函数 函数原型: void send_byte(uchar c); Function: 将数据C发送出去,可以是地址,也可以是数据,发完后等待回应,并对此状态 位进行操作(不应答或非应答都使ack=0 ),发送数据正常,ack=1;ack=0 表示被控器无应答或损坏。 ==================================================================*/ void send_byte(uchar c) { uchar bit_count; for (bit_count=0;bit_count<8;bit_count++) { if ((c<<bit_count)&0x80) {SDA=1;} else {SDA=0;} nop(); SCL=1; nop();nop();nop();nop();nop(); SCL=0; } nop();nop(); SDA=1; TRISC4=1; //SDA改成输入口!!!!!!!!!!!!!!!!!!!!!!!!! nop();nop(); SCL=1; nop();nop();nop(); if (SDA==1) ack=0; else ack=1; //用ASK=1为有应答信号 SCL=0; nop(); TRISC4=0; //SDA改成输出口!!!!!!!!!!!!!!!! nop();nop(); } /*================================================================== 字节数据接收函数 函数原型: uchar receive_byte(); FUNCTION: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数。 ===================================================================*/ uchar receive_byte() { uchar retc,bit_count; retc=0; SDA=1; TRISC4=1; //SDA改成输入口!!!!!!!!! for (bit_count=0;bit_count<8;bit_count++) { nop(); SCL=0; nop();nop();nop();nop();nop(); SCL=1; nop();nop(); retc=retc<<1; if (RC4==1) retc=retc+1; nop();nop(); } SCL=0; nop();nop(); TRISC4=0; //SDA改成输出口!!!!!!!!!!!!!!!!!! return (retc); } /*================================================================ 向有子地址器件发送多字节数据函数 函数原型: bit I_send_str(uchar sla,uchar suba,uchar *s,uchar no); Function: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果 返回1表示操作成功,否则操作有误。 =================================================================*/ void I_send_str(uchar sla,uchar suba,uchar *s,uchar no) { uchar i; start_i2c(); send_byte(sla); if (ack==0) i2c_error(); send_byte(suba); if (ack==0) i2c_error(); for (i=0;i<no;i++) { send_byte(*s); if (ack==0) i2c_error(); s++; } stop_i2c(); // return(1); }
/***************************************************************** 延时函数 函数原型: void delay_250ms(); FUNCTION: 延明250ms *****************************************************************/ void delay_250ms() { unsigned int d=24999; while (--d); } /***************************************************************** 总线错误函数 函数原型: void i2c_error(); *****************************************************************/ void i2c_error () { uchar i; for (i=0;i<8;i++) { delay_250ms(); delay_250ms(); }
} |