软件模拟I2C总线操作。

原创 2003年05月27日 11:26:00

     在单片机应用中,I2C(I方C)总线一种简单,双向的二线制同步串行总线,它只需要两根串行线,脉冲线,就可以在总线与连接的器件之间传送信息, 它不外乎有以下几个特点:
a.每个连接到总线上的器件都可以进行唯一的寻址,还可建立起简单的主从关系,主器件既可作为发送器,也可作为接收器.
b.它带竞争电路和仲裁电路,可以接收多个主器件发送的数据,而这些数据不会产混乱.
c.同步脉冲可以允许器件可以通过总线以不同的波特率进行通信.
d.因为只有两根线,连接简单,方便.
     对于MCS51系列来讲,内部并没I2C总线接口,在这种情况下,可以采用软件模拟的方法来写出I2C总线的操作,下面我的程序就在开始处定义哪个引脚作为数据线SDA,哪个引脚作为脉冲线,请看我的程序(C51写的,总共有8个函数来模拟I2C总线):
Common.h File
#pragma  LA DB SB OE CD OT(SPEED,6)
//LA indicate LARGE Compling Mode-All local and global variables are located in external-ram.
//DB indicate DEBUG
//SB indicate SYMBOL
//OE indicate OBJECTEXTEND
//CD indicate CODE  //Generate ASM Code
//OT indicate OPTIMIZATION
#include <stdio.h>
#include <reg51.h>
#include <intrins.h>
#include <stdlib.h>
#pragma REGPARMS
#pragma SAVE
#define BOOL bit
#define BYTE unsigned char
#define UINT unsigned int
#define ULONG unsigned long
#define HIGH 1
#define LOW 0
#define TRUE 1
#define FALSE 0
#define MAXLONGS  2147483647
#define MINLONGS  -2147483648
#define MAXINTS   32767
#define MININTS   -32768
#define MAXLONGU  4294967295
#define MAXINTU   65535
#define BLOCKLOW 0x0000 //The start-address in AT24C64 is 0x0000
#define BLOCKSIZE 0x20 //Each block is 32 bytes
#define BLOCKNUM  0xC8 //At best 200,Only Save the newest 200 records.
#define BLOCKHIGH 0x18FF//The end-address in AT24C64 is 0x18FF
#define OSC       24000000 //Osillcator Frequency
#define BAUDRATE  9600
#define OTV    256-OSC/12/BAUDRATE/32 //character O represents Obtain,character T represents Timer,character V represents Value
//IMPORTANT ANNOUNCEMENT:I use a word 0x1FFC,0x1FFD to save the next block's address and 0x1FFE,0x1FFF to save the block's no.
sbit GUN=0x85;//PIN P05
sbit SCL=0xFF;     //Undefined bit-address,which will be defined in function:DEFI2C
sbit SDA=0xFF;     //Undefined bit-address,which will be defined in function:DEFI2C
sbit SHKL=0xFF;    //Undefined bit-address,which will be defined in function:DEFI2C
sbit SHKH=0xFF;    //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH0=0xFF;     //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH1=0xFF;     //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH2=0xFF;     //Undefined bit-address,which will be defined in function:DEFI2C
extern void DEFI2C(char *name) //To define which pin is SDA and which pin is SCL
extern void I2CInit()   //Initialization For I2C Bus
extern void I2CStart()  //Start I2C Bus
extern void I2CStop();  //Stop  I2C Bus
extern bit  I2CClock(); //return SDA while SCL is HIGH
extern void I2CDelay(); //Delay
extern void I2CAck();  //Answer
extern bit  I2CSend(BYTE I2CData);//Send data with I2C Bus
extern BYTE I2CReceive();  //Receive data

Common.c
void DEFI2C(char *name)
{
    //Todo:add your codes here....
    //Announcement:If you question me why use the function DEFI2C?
    //Well,the function will be used to define which PIN is SCL and which PIN is SDA,especially there are more than 1 I2C
    //equipment in your circuit.In this sitiuation,we write a function for defining I2C Bus named DEFI2C....
}
void I2CStart()
{
   SCL=HIGH;
   I2CDelay();
   SDA=LOW;
   I2CDelay();
   SCL=LOW;
   I2CDelay();
}
void I2CStop()
{
   SDA=LOW;
   I2CDelay();
   SCL=HIGH;
   I2CDelay();
   SDA=HIGH;
   I2CDelay();
   SCL=LOW;
   I2CDelay();
}
void I2CInit()
{
   SCL=LOW;
   I2CStop();
}
bit I2CClock() //return SDA while SCL is HIGH
{
   bit sample;
   SCL=HIGH;
   I2CDelay();
   sample=SDA;
   SCL=LOW;
   I2CDelay();
   return sample;
}
bit I2CSend(BYTE I2CData)
{
   BYTE i;
   for(i=0;i<8;i++)
   {
     SDA=(bit)(((I2CData) & 0x80) / 0x80) ;
     I2CData=I2CData << 1;
     I2CClock();
   }
   SDA=HIGH;
   return (~I2CClock());
}
void I2CAck()
{
   SDA=LOW;
   I2CClock();
   SDA=HIGH;
}
void I2CDelay()
{
   BYTE ll;
   for(ll=0;ll<100;ll++)
   {
      ;
   }
}
BYTE I2CReceive()
{
   BYTE I2CData=0;
   BYTE kk;
   for(kk=0;kk<8;kk++)
   {
      I2CData*=2;
      if(I2CClock())
      {
          I2CData++;
      }
   }
   return I2CData;
}


上面的代码是用软件来模拟I2C总线,在对特定I2C器件进行操作时,一定要和该器件的时序对应起来才可以,本人从事单片机开发不久,上述程序是去年在北京时写的,如有错误还请各位硬件大侠,前辈给予指教.

51单片机模拟I2C总线(我见过最好的,与大家共享)

#include     #include     #include     #define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/     #defi...
  • u010568345
  • u010568345
  • 2014年07月01日 00:35
  • 624

io模拟i2c程序

转来的,觉得不错。可以加深理解I2C,虽然现在的都是硬件I2C. 本程序是在周立功网上的程序的基础上修改的,原例里的ACK时序有点问题 /****************************...
  • dadahacker
  • dadahacker
  • 2010年08月03日 12:14
  • 4852

stm32软件模拟I2C

1 很多人都知道stm32的硬件I2C存在BUG,现在我们通过软件模拟时序的办法来实现I2C。...
  • qq_27312943
  • qq_27312943
  • 2016年11月24日 16:47
  • 2615

普通IO口模拟实现I2C通信及应用解析

根据I2C通信规范(具体可以参考“浅谈I2C总线”),通过普通IO端口模拟可以实现单片机(主设备)与从设备的I2C通信,其中SCL通过IO口延时高低电平变化实现,SDA根据SCL状态变化产生开始信号,...
  • bluewhaletech
  • bluewhaletech
  • 2014年08月20日 14:54
  • 5708

软件模拟I2C

这些天在做一个h.264设备,用的ARM芯片是带I2C接口,但这I2C一来只支持400K,二来没有可调的时序空间,没法支持TVP5150这种有点瑕疵的I2C,至此只好借用两个GPIO口通过软件来模拟i...
  • u013164357
  • u013164357
  • 2014年03月24日 11:47
  • 950

linux gpio模拟i2c的使用/用GPIO模拟I2C总线-2

在drivers/i2c/busses下包含各种I2C总线驱动,如S3C2440的I2C总线驱动i2c-s3c2410.c,使用GPIO模拟I2C总线的驱动i2c-gpio.c,这里只分析i2c-gp...
  • kevinx_xu
  • kevinx_xu
  • 2013年11月25日 13:30
  • 4726

linux gpio模拟i2c的使用/用GPIO模拟I2C总线-1

linux kernel 中的i2c-gpio使用   在linux中,我们可以自己来使用gpio来模拟i2c,但是万能的linux中其实也已经有了i2c的东东了。   现在看看i2c-g...
  • kevinx_xu
  • kevinx_xu
  • 2013年11月25日 12:16
  • 1257

深入理解I2C总线时序的模拟

深入理解I2C总线时序的模拟
  • ce123
  • ce123
  • 2011年10月28日 20:24
  • 6667

I2C总线及单片机模拟I2C总线通信程序编写

1、I2C总线         I2C总线是Inter-IntegratedCircuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ...
  • u011961427
  • u011961427
  • 2017年02月16日 17:14
  • 372

MSP430学习的第一个模拟I2C程序

模拟I2C
  • yhyhdl
  • yhyhdl
  • 2016年09月07日 20:24
  • 1335
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:软件模拟I2C总线操作。
举报原因:
原因补充:

(最多只允许输入30个字)