函数定义:gpio_iic.h:#ifndef__IIC_GPIO__#define__IIC_GPIO__voiddelay();/*设置scl引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。*/intset_scl(intvalue);/*得到scl引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。*/intget_scl();/*设置sda引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。*/intset_sda(intvalue);/*得到sda引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。*/intget_sda();/*重新发送iicstart位,这个是在传送数据过程中使用。*/voidiic_restart();/*发送iicstart位,这里假设总线空闲,此时SDL与SCL都为高电平。*/voidiic_start();/*发送stop位,这里假设scl此时为低电平。*/voidiic_stop();/*发送一个bit0,这里假设scl此时为低电平,sda电平不定。*/voidsend_bit0();/*发送一个bit1,这里假设scl此时为低电平,sda电平不定。*/voidsend_bit1();/*接收一个bit位,返回值只能是0或1。*/intreceive_bit();/*发送ACK,实际上是发送一个bit0.*/voidsend_ack();/*接收ACK。*/intreceive_ack();/*接收一个字节。*/charreceive_byte();/*接收一个buf,返回值总是为0,它不能保证从器件一定能收到ACK,也不能保证从器件正在工作。*/intreceive_buf(char*buf,intbuf_size);/*发送一个字节,返回ACK的值,发送时,没有收到ACK会重试n次,这是常。*/intsend_byte(chardata_byte);/*发送一个buf,返回值是成功发送,收到ACK的字节数量。*/intsend_buf(char*buf,intbuf_size);#endifgpio_iic.c:#includegpio_iic.h//#define__80C52__#define__MINI2440__#ifdef__MINI2440__#includelinux/gpio.h#includelinux/delay.h#includemach/regs-gpio.h#endif#ifdef__80C52__#includereg52.hsbitSCL=P1^0;sbitSDA=P1^1;#endifvoiddelay(){#ifdef__MINI2440__udelay(1);#endif#ifdef__80C52__inti=0;for(i=0;i10000;i++);#endif}/*设置scl引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。*/intset_scl(intvalue){#ifdef__MINI2440__//s3c2410_gpio_cfgpin(S3C2410_GPE(15),S3C2410_GPE15_IICSDA);//s3c2410_gpio_cfgpin(S3C2410_GPE(14),S3C2410_GPE14_IICSCL);s3c2410_gpio_cfgpin(S3C2410_GPE(14),S3C2410_GPIO_OUTPUT);switch(value){case0:s3c2410_gpio_setpin(S3C2410_GPE(14),0);//IICSCLbreak;case1:s3c2410_gpio_setpin(S3C2410_GPE(14),1);//IICSCLbreak;default:break;}#endif#ifdef__80C52__if(0==value)SCL=0;elseif(1==value)SCL=1;#endifreturn0;}/*得到scl引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。*/intget_scl(){#ifdef__MINI2440__s3c2410_gpio_cfgpin(S3C2410_GPE(14),S3C2410_GPIO_INPUT);returns3c2410_gpio_getpin(S3C2410_GPE(14))0?1:0;#endif#ifdef__80C52__returnSCL;#endif}/*设置sda引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。*/intset_sda(intvalue){#ifdef__MINI2440__s3c2410_gpio_cfgpin(S3C2410_GPE(15),S3C2410_GPIO_OUTPUT);switch(value){case0:s3c2410_gpio_setpin(S3C2410_GPE(15),0);//IICSDAbreak;case1:s3c2410_gpio_setpin(S3C2410_GPE(15),1);//IICSDAbreak;default:break;}#endif#ifdef__80C52__if(0==value)SDA=0;elseif(1==value)SDA=1;#endifreturn0;}/*得到sda引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。*/intget_sda(){#ifdef__MINI2440__intsda_pin=0;s3c2410_gpio_cfgpin(S3C2410_GPE(15),S3C2410_GPIO_INPUT);sda_pin=s3c2410_gpio_getpin(S3C2410_GPE(15))0?1:0;returnsda_pin;#endif#ifdef__80C52__returnSDA;#endif}/*重新发送iicstart位,这个是在传送数据过程中使用。*/voidiic_restart(){set_scl(0);delay();set_sda(1);delay();set_scl(1);delay();set_sda(0);delay();set_scl(0);delay();}/*发送iicstart位,这里假设总线空闲,此时SDL与SCL都为高电平。*/voidiic_start(){set_sda(0);delay();set_scl(0);delay();}/*发送stop位,这里假设scl此时为低电平。*/voidiic_stop(){set_sda(0);delay();set_scl(1);delay();set_sda(1);delay();}/*发送一个bit0,这里假设scl此时为低电平,sda电平不定。*/voidsend_bit0(){set_sda(0);delay();set_scl(1);delay();set_scl(0);delay();}/*发送一个bit1,这里假设scl此时为低电平,sda电平不定。*/voidsend_bit1(){set_sda(1);delay();set_scl(1);delay();set_scl(0);delay();}/*接收一个bit位,返回值只能是0或1。*/intreceive_bit(){intvalue=-1;set_sda(1);delay();set_scl(0);delay();set_scl(1);delay();value=get_sda();set_scl(0);returnvalue;}/*发送ACK,实际上是发送一个bit0.*/voidsend_ack(){send_bit0();}/*接收ACK。*/intreceive_ack(){intack=1;set_sda(1);delay();set_scl(1);delay();ack=get_sda();delay();set_scl(0);returnack;}/*接收一个字节。*/charreceive_byte(){inti=0;intrecv_data=0;for(i=0;i8;i++){recv_data=recv_data|receive_bit();if(7==i)break;recv_data=1;}send_ack();returnrecv_data;}/*接收一个buf,返回值总是为0,它不能保证从器件一定能收到ACK,也不能保证从器件正在工作。*/intreceive_buf(char*buf,intbuf_size){inti=0;for(i=0;ibuf_size;i++){buf[i]=receive_byte();}returnbuf_size;}/*发送一个字节,返回ACK的值,发送时,没有收到ACK会重试n次,这是常。*/intsend_byte(chardata_byte){intretry_count=8;//重试次数。inti=0;intack=1;charsend_data=0;send_data=data_byte;do{for(i=0;i8;i++){if(0x80&send_data)send_bit1();elsesend_bit0();send_data=1;}ack=receive_ack();if(0==ack)break;send_data=data_byte;retry_count--;}while(retry_count=0);returnack;}/*发送一个buf,返回值是成功发送,收到ACK的字节数量。*/intsend_buf(char*buf,intbuf_size){inti=0;intcount=0;for(i=0;ibuf_size;i++){if(0!=send_byte(buf[i]))break;count++;}returncount;}下面是可以用来读写at24c02的测试代码,在mini2440板和Protues仿真测试通过,staticvoidm24c02_send(intaddr,char*buf,intbuf_size){intcount=0;intrev=-1;iic_start();rev=send_byte(0xa0);rev=send_byte((addr0)&0xff);count=send_buf(buf,buf_size);iic_stop();}staticvoidm24c02_recv(intaddr,char*buf,intbuf_size){iic_start();send_byte(0xa0);send_byte((addr0)&0xff);iic_restart();send_byte(0xa1);receive_buf(buf,buf_size);iic_stop();}