GPIO模拟I2C-1

发布者:和谐相伴最新更新时间:2024-07-25 来源: cnblogs关键字:GPIO  模拟I2C  波形 手机看文章 扫描二维码
随时随地手机看文章

GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。


这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以不用计较的;通常情况下I2C开始之前和I2C结束之后,两者都是高电平,而在正常工作时两者不受控制的情况下都是默认低电平


(1)基础宏定义


#define GPIO_SCL             S3C2410_GPF3

#define GPIO_SDA             S3C2410_GPF0

#define GPIO_SDA_OUTP   S3C2410_GPF0_OUTP  //设定SDA输出

#define GPIO_SDA_INP      S3C2410_GPF0_INP     //设定SDA输入

#define GPIO_SCL_OUTP   S3C2410_GPF3_OUTP  //设定SCL输出


void I2C_SCL_OUTP( void )

{

      s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);

}


void I2C_SCL_Output(u8 value)

{

      if(value)

      {                                               

            s3c2410_gpio_setpin(GPIO_SCL,value); 

      }

      else

      {

            s3c2410_gpio_setpin(GPIO_SCL,value ); 

      }

}


void I2C_SDA_Mode(u8 v_mode)   //SDA输出方向

{

       if(v_mode)

       {                                               

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP);  

       }

       else

       {

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP);  

       }

}


void I2C_SDA_Output(u8 value)

{

       if(value)

       {                                               

               s3c2410_gpio_setpin(GPIO_SDA,value); 

       }

       else

       {

                s3c2410_gpio_setpin(GPIO_SDA,value ); 

       }

}


u8 I2C_SDA_Read(void)    //SDA读数据

{

       return s3c2410_gpio_getpin(GPIO_SDA); 

}


(2)基础段


void I2C_Init(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);      //默认拉高

}


void I2C_Wait(void)

{

      u16 i;

      for(i=0;i<200;i++);

}


void I2C_Start(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(0);

}

void I2C_Stop(void)

{

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(1);

}

(3)读写单个字节的段


u8 I2C_Send_Byte(u8 bytedata)

{

      u8 i,ack;

      I2C_SDA_Mode(1);  //SDA输出

      I2C_SCL_OUTP();


      for (i = 0; i < 8; i++) 

      {

              if (bytedata & 0x80)

              {

                     I2C_SDA_Output(1);

              }

              else

              {

                    I2C_SDA_Output(0);

              }

              bytedata <<= 1;

            

              I2C_SCL_Output(1);

              udelay(3);

              I2C_SCL_Output(0);

              udelay(1);

       }    

  

        I2C_SDA_Output(1);  //release

        udelay(3);

       

        I2C_SDA_Mode(0);  //设定SDA输入

        I2C_SCL_Output(1);  

        udelay(3);

        ack = I2C_SDA_Read();   //读应答

        I2C_SDA_Mode(1);

        I2C_SCL_Output(0);

        udelay(3);

      

        return ack;  

}


u8 I2C_Receive_Byte(void) 

{

       u8 i;

       u8 bytedata = 0x00;

       u8 temp;

 

       I2C_SDA_Mode(0);

       for ( i = 0; i < 8; i++)

       {

             I2C_SCL_Output(1);

             udelay(3);


             bytedata <<= 1;

             temp = I2C_SDA_Read();

             printk('reda SDA'value is:%dn',temp);

 

             if (temp)

                   bytedata |= 0x01;

             printk('  bytedata is:%xn',bytedata);

             I2C_SCL_Output(0);

             udelay(1);

       }

       I2C_SDA_Mode(1);

       return bytedata;

}


(4)读写单个字节的I2C应用函数


u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata)

{  

       u8 ack;

       printk('device_ID is:%xn',device_ID);

       printk('address is:%xn',address);

       printk('date is:%xn',bytedata);

       I2C_Start(); 

       ack=I2C_Send_Byte(device_ID);

       printk('ack is:%dn',ack);

       if(ack)


             I2C_Stop();

       I2C_Send_Byte(address);

       I2C_Send_Byte(bytedata);

       I2C_Stop();

       I2C_Wait();

       return 0;

}


u8 I2C_Byte_Read(u8 device_ID,u8 address)

{  

       u8 bytedata;


       I2C_Start();

       I2C_Send_Byte(device_ID);

       I2C_Send_Byte(address);

       I2C_Start();

       I2C_Send_Byte(device_ID+1);

       bytedata = I2C_Receive_Byte();  //读单个字节,不需要再发应答

       I2C_Stop();   

       return bytedata;

}


(5)类似可以完成读写多个字节的函数,暂不补充。


关键字:GPIO  模拟I2C  波形 引用地址:GPIO模拟I2C-1

上一篇:有关i2c的问题总结
下一篇:linux gpio模拟i2c

推荐阅读最新更新时间:2026-03-25 15:07

STM8S003的GPIO模拟I2C切换输入输出的解决办法
刚开始学STM8,很多东西刚了解,正在做一个温湿度显示小板,就是使用I2C驱动SHT20传感器,并显示到数码管,数码管用的四位一体共阴数码管,STM8管脚有限,添加了一片TM1650做驱动,不过SHT20和TM1650都是用的I2C接口,由于对STM8硬件I2C还不了解,先打算用软件模拟,这就涉及到需要对GPIO做输入输出切换处理来检测ACK响应,刚开始,直接操作DDR寄存器,但是出现从输出切换到输入就会出现单片机死机,不解,查资料,得到一个解决办法,在输出状态时,可以不用切换到输入,我使用管脚D4,D5这两个管脚,这两个管脚比较特殊,就是真正开漏,在管脚描述为T,其它描述为HS(高吸收电流)。 解决办法,将IO设置为开漏输出
[单片机]
基于STM32F103的GPIO模拟I2C操作AT24C02S-ST E2prom调试日志
基于STM32F103的GPIO模拟I2C操作E2prom芯片AT24C02S-ST: 1、硬件环境初始化:Stm32管脚配置,管脚操作 typedef struct _PIN_CFG { GPIO_TypeDef *Port; uint16_t Pin; } PIN_CFG; typedef struct _E2PROM_CFG { PIN_CFG SCL; PIN_CFG SDA; } E2PROM_CFG; E2PROM_CFG E2prom_Cfg; //初始化 void E2prom_Chip_Init(void) { GPIO_InitTypeDef GPIO_InitSt
[单片机]
基于STM32F103的<font color='red'>GPIO</font><font color='red'>模拟</font><font color='red'>I2C</font>操作AT24C02S-ST E2prom调试日志
单片机模拟I2C总线及24C02读写实例
单片机模拟I2C总线及24C02(I2C EEP ROM )读写实例(c源代码) /* 51系列单片机在使用时,有时需要模拟I2C总线, */ /* 这里举出一个实例(读写串行EEPROM 芯片 at2402) */ /************************************************************************/ /* Name:AT24C02存储器的读写程序,用到I2C总线,含相对独立的I2C总线读写函数 */ /* Language: C 51单片机 编程 语言 */ /* Platf or m: Win98, Intel Celeron 433 Processor,伟
[单片机]
如何使用C语言实现51单片机模拟I2C总线
电路原理图 EEPROM为ATMEL公司的AT24C01A。单片机为ATMEL公司的AT89C51。 软件说明 C语言为Franklin C V3.2。将源程序另存为testi2c.c,用命令 C51 testi2c.c L51 TESTI2C.OBJ OHS51 TESTI2C 编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。 3.源程序 #include 《reg51.h》 #include 《intrins.h》 #define uchar unsigned char #define uint unsigned int #define AddWr 0xa0 /*器件地址选择及写标志*/ #d
[单片机]
如何使用C语言实现51单片机<font color='red'>模拟</font><font color='red'>I2C</font>总线
STM32F4之模拟I2C通信协议的实现
一,何为IIC? I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。 它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。 IIC是半双工通信方式。 二,IIC通信的6种状态 1.空闲状态 2.开始信号 3.停止信号 4.应答信号 5.数据的有效性 6.数据传输 三.用代码实现I2C协议的模拟 1.空闲状态:当SDA以及SCL两条总线都处于高电平状态时,处于空闲状态 void IIC_in
[单片机]
STM32F4之<font color='red'>模拟</font><font color='red'>I2C</font>通信协议的实现
stm32与AT24C02的I2C通信总结(模拟时序)
从51的时候就学习了I2C通信协议,但51的功能就那些,内部没有集成I2C模块,所以只能通过模拟I2C通信的时序来和EEPROM进行通信,stm32内部集成了I2C通信的片上外设,但由于内部I2C外设复杂和不稳定行,所以用的人不是很多,而基本上使用I2C的通信都是通过模拟时序的方式来实现的 首先I2C是同步半双工的通信方式,需要两条线即可,SCL时钟线,同步时钟由主机产生,SDA数据线用来发送接收数据,任何时候只能一台主机发送数据。 在编程的时候碰到了很多问题,其中一项就是等待从机的应答程序 开始的时候编写如下 void iic_wait_ack() 错误 voi
[单片机]
stm32与AT24C02的<font color='red'>I2C</font>通信总结(<font color='red'>模拟</font>时序)
计算模拟I2C的传输速率
在编写I2C器件的驱动时,经常会看到手册中提及该器件的最高传输速率,如: 而在配置寄存器实现I2C中也是需要配置I2C的传输速率,如: 但模拟I2C的速率该如何计算? 首先一般I2C速率的单位是kbit/s,I2C传输速率的定义:每秒传输的比特位数。 先把代码贴出来(这里的代码在之前的日志中贴出来过): #define I2C_DELAY() I2CSysCtlDelay(30) //! I2C速率约为237Kb/s(若为40,则速率约为178Kb/s) /* * @brief SysCtlDelay * @param ulCount 延时值,必须大于0 * @retval (3/(120
[单片机]
计算<font color='red'>模拟</font><font color='red'>I2C</font>的传输速率
STM8S 模拟I2C程序
STM8S的硬件I2C还是存在问题,不敢贸然使用. #define SCL PE_ODR_ODR1 #define SDA PE_ODR_ODR2 #define SDAM PE_IDR_IDR2 #define SET_SCL_OUT() {PE_DDR_DDR1=1; PE_CR1_C11 = 1; PE_CR2_C21 = 0;} #define SET_SDA_OUT() {PE_DDR_DDR2=1; PE_CR1_C12 = 1; PE_CR2_C22 = 0;} #define SET_SDA_IN() {PE_DDR_DDR2=0; PE_CR1_C12 = 0; PE_CR2_C22 = 0;} //------
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved