·I2C总线的一些特征:

1、 只要求两条总线,一条串行数据线(SDA),一条串行时钟线(SCL)

2、 两个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机系统软件设定的地址;主机可以作为主机发送器或主机接收器

3、 它是一个真正的多主机总线,如果两个或更多个主机同时初始化数据传输,可以通过冲突检测和总裁防止数据被破坏

4、 串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s

5、 片上的滤波器可以滤去总线数据线上的毛刺波,保证数据完整

6、 连接到相同总线上的IC数量只收到总线的最大电容400pF限制

·I2C总线术语定义:

1、 发送器:发送数据到总线的器件。

2、 接收器:从总线接收数据的器件。

3、 主机:初始化发送、产生时钟信号和终止发送的器件。

4、 从机:被主机寻址的器件。

5、 多主机:同时有多于一个主机尝试控制总线,但不破坏报文。

6、 仲裁:是一个在有多个主机同时尝试控制总线,但只允许其中一个控制总线并使报文不被破坏的过程。

7、 同步:两个或多个器件同步时钟信号的过程。

/* */

·主机发出的总线时钟信号只有在以下的情况下才能被改变:慢速的从机器件控制时钟线并延长时钟信号(时钟线被拉低延长),或者在发生仲裁时被另一个主机改变。

·I2C总线支持任何IC生产过程(NMOS、CMOS、双极性)。

·两线——串行数据(SDA)和串行时钟(SCL)线在连接到总线的器件间传递信息。

·每个器件都有一个唯一的地址识别,而且都可以作为一个发送器或接收器。

·除了发送器和接收器外,器件在执行数据传输时也可以被看作是主机或从机。

·主机是初始化总线的数据传输并产生允许传输的时钟信号的器件。任何被寻址的器件都认为是从机。

·在I2C总线上产生时钟信号通常是主机器件的责任;在总线上传输数据时,每个主机产生自己的时钟信号。

·SDA和SCL都是双向线路,都通过一个电流源或上拉电阻连接到正的电源电压。当总线空闲时,这两条线路都是高电平。

·连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与功能。(????)

·SDA线上的数据必须在时钟的高电平周期保持稳定。数据线的高或低电平状态只有在SCL线的时钟信号是低电平时才能改变:

·起始条件:在SCL线是高电平时,SDA线从高电平向低电平切换。

·停止条件:当SCL线是高电平时,SDA线由低电平向高电平切换。

·起始和停止条件一般由主机产生。总线在起始条件后被认为处于忙的状态。在停止条件的某段时间后,总线被认为再次处于空闲状态。

传输数据:

·字节格式:发送到SDA线上的每个字节必须为8位。每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。

·如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL保持低电平迫使主机进入等待状态。当从机准备好接收下一个数据字节并释放时钟线SCL后,数据传输继续。

·数据传输必须带响应。相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间,发送器释放SDA线(高)。

·在响应的时钟脉冲期间,接收器必须将SDA线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。

·当从机不能响应从机地址时(例如它正在执行一些实时函数不能接收或发送),从机必须是数据线保持高电平。主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。

·如果从机-接收器响应了从机地址但是在传输了一段时间后不能接收更多数据字节,主机必须再一次终止传输。这种情况用从机在第一个字节后没有产生响应来表示。从机使数据线保持高电平,主机产生一个停止或重复起始条件。

·如果传输中有主机接收器,它必须通过在从机不产生时钟的组后一个字节不产生一个响应,向从机-发送器通知数据结束,从机-发送器必须释放数据线,允许主机产生一个停止或重复起始条件。

【IO模拟IIC源码】

 #include "base.h"
#include "simI2C.h" #define MAX_PORT_INDEX 4
#define MIN_PORT_INDEX 0
#define MAX_PIN_INDEX 31
#define MIN_PIN_INDEX 0
#define I2C_INTVAL 15 // ~=30KHz #define DIR_MODE_IN 0
#define DIR_MODE_OUT 1 #define CLK_DELAY_RETRY 10000 #define log /*
set the io dir
*/
static int i2c_SetIODir(int iPin, int iMode)
{
int port, subno; port = (iPin >> ) & 0xff;
subno = (iPin & 0xff);
if(port < MIN_PORT_INDEX || port > MAX_PORT_INDEX)
return I2C_ERR_INVALID_PARAM;
if(subno < MIN_PIN_INDEX|| subno > MAX_PIN_INDEX)
return I2C_ERR_INVALID_PARAM; gpio_set_pin_type(port, subno, iMode);
return I2C_OK;
} /*
set the io level
*/
static int i2c_SetIO(int iPin, int iLevel)
{
int port, subno; port = (iPin >> ) & 0xff;
subno = (iPin & 0xff);
if(port < MIN_PORT_INDEX || port > MAX_PORT_INDEX)
return I2C_ERR_INVALID_PARAM;
if(subno < MIN_PIN_INDEX|| subno > MAX_PIN_INDEX)
return I2C_ERR_INVALID_PARAM; gpio_set_pin_val(port, subno, iLevel);
return I2C_OK;
} /*
get the io level
*/
static int i2c_GetIO(int iPin)
{
int port, subno; port = (iPin >> ) & 0xff;
subno = (iPin & 0xff);
if(port < MIN_PORT_INDEX || port > MAX_PORT_INDEX)
return I2C_ERR_INVALID_PARAM;
if(subno < MIN_PIN_INDEX|| subno > MAX_PIN_INDEX)
return I2C_ERR_INVALID_PARAM; return gpio_get_pin_val(port, subno);
} static void i2c_Intval(void)
{
DelayUs(I2C_INTVAL);
} static void i2c_start (T_SimI2CHdl *pHdl)
{
int m;
int clk; pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSDA, );
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
// TODO:
pHdl->pfSetIO(pHdl->iSDA, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSDA, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
} static void i2c_stop (T_SimI2CHdl *pHdl)
{
int m;
int clk; pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_OUT);
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSDA, );
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSDA, );
i2c_Intval();
//log("out");
} static void i2c_ack (T_SimI2CHdl *pHdl)
{
int m;
int clk; pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_OUT);
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
i2c_Intval();
// i2c_Intval();
pHdl->pfSetIO(pHdl->iSDA, );
// i2c_Intval();
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
//log("out");
} static void i2c_nack (T_SimI2CHdl *pHdl)
{
int m;
int clk; pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_OUT);
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
i2c_Intval();
// i2c_Intval();
pHdl->pfSetIO(pHdl->iSDA, );
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
//log("out"); } /*
the receiver acknowlage the ack?
1 yes, 0 no
*/
static int i2c_isack (T_SimI2CHdl *pHdl)
{
int val = ;
int m;
int clk; // pHdl->pfSetIO(pHdl->iSDA, 0); //Joshua _a
pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_IN);
// i2c_Intval();
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
val = pHdl->pfGetIO(pHdl->iSDA);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval(); return val==? : ;
} static int i2c_ReadByte(T_SimI2CHdl *pHdl, char *ch)
{
int i;
int temp = ;
int m;
int clk; //pHdl->pfSetIO(pHdl->iSDA, 1); //Joshua _a
pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_IN);
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
//pHdl->pfSetIO(pHdl->iSDA, 1);
i2c_Intval(); for (i=; i<; i++)
{
temp <<= ;
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
temp |= pHdl->pfGetIO(pHdl->iSDA);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
}
*ch = (char)(temp&0xff);
//log("ReadByte = %02X", temp);
return ;
} static int i2c_WriteByte(T_SimI2CHdl *pHdl, char ch)
{
int i;
char temp = ch;
int m;
int clk; pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_OUT);
//pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT); for (i=; i<; i++)
{
if ((temp << i) & 0x80)
{
pHdl->pfSetIO(pHdl->iSDA, );
}
else
{
pHdl->pfSetIO(pHdl->iSDA, );
}
do {
pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_IN);
pHdl->pfSetIO(pHdl->iSCL, );
if(pHdl->pfGetIO(pHdl->iSCL) == )
continue ;
else
break;
}while(); pHdl->pfSetDIR(pHdl->iSCL, DIR_MODE_OUT);
pHdl->pfSetIO(pHdl->iSCL, );
i2c_Intval();
pHdl->pfSetIO(pHdl->iSCL, );
if (i >= )
pHdl->pfSetDIR(pHdl->iSDA, DIR_MODE_IN);
i2c_Intval();
}
} /*********************************************************
Name :
imI2CInit
Descritpion :
initialize the I2C handle
input: output:
pHdl - the handle pointer;
return:
= 0 - success
< 0 - failed
Joshua Guo. @ 2012-06-27
**********************************************************/
int SimI2CInit(T_SimI2CHdl *pHdl, int iSDA, int iSCL)
{
int sda_port, sda_subno;
int scl_port, scl_subno; sda_port = (iSDA >> ) & 0xff;
sda_subno = (iSDA & 0xff);
scl_port = (iSCL >> ) & 0xff;
scl_subno = (iSCL & 0xff); if(pHdl == NULL
|| sda_port < MIN_PORT_INDEX || sda_port > MAX_PORT_INDEX
|| sda_subno < MIN_PIN_INDEX || sda_subno > MAX_PIN_INDEX
|| scl_port < MIN_PORT_INDEX || scl_port > MAX_PORT_INDEX
|| scl_subno < MIN_PIN_INDEX || scl_subno > MAX_PIN_INDEX)
return I2C_ERR_INVALID_PARAM; pHdl->iSDA = iSDA;
pHdl->iSCL = iSCL;
pHdl->iRetry = ;
pHdl->pfGetIO = i2c_GetIO;
pHdl->pfSetIO = i2c_SetIO;
pHdl->pfSetDIR = i2c_SetIODir; return ;
} int SimI2CSetRetry(T_SimI2CHdl *pHdl, int iRetry)
{
if (pHdl == NULL || iRetry < )
{
return I2C_ERR_INVALID_PARAM;
}
pHdl->iRetry = iRetry;
return ;
} /*
read data from the simulator I2C bus return:
< 0 read failed, return the error No.
>=0 data length Joshua Guo. @ 2012-06-27
*/
//int SimI2CReadDataFromAddr(T_SimI2CHdl *pHdl, char slave, char addr, char *buf, int iLen)
int SimI2CReadDataFromAddr(T_SimI2CHdl *pHdl,
unsigned char slave, unsigned char addr, unsigned char *buf, unsigned char iLen)
{
int i;
int iRetry1 = ;
int iRetry2 = ;
// if (pHdl == NULL || buf == NULL || iLen < 0)
if (pHdl == NULL || buf == NULL)
{
log("I2C_ERR_INVALID_PARAM");
return I2C_ERR_INVALID_PARAM;
}
if (iLen == )
{
log("iLen = 0");
return ;
}
/*
* Read Data From the Device
* +---+-------+---+------------+---+---+---+-------+---+
* | S | SLA+W | A | MemAddress | A | P | S | SLA+R | A | ...
* +---+-------+---+------------+---+---+---+-------+---+
* +-------+----+-------+----+-----+-------+-----+---+
* | Data1 | mA | Data2 | mA | ... | DATAn | /mA | P |
* +-------+----+-------+----+-----+-------+-----+---+
* S - Start Condition
* P - Stop Condition
* SLA+W - Slave Address plus Wirte Bit
* SLA+R - Slave Address plus Read Bit
* MemAddress - Targe memory address within device
* mA - Host Acknowledge Bit
* A - Slave Acknowledge Bit
*/
/*
i2c_nack(pHdl);
i2c_ack(pHdl);
i2c_stop(pHdl);
*/
retry1:
//start
i2c_start(pHdl);
//slave with the R/W as 0
i2c_WriteByte(pHdl, slave);
if (i2c_isack(pHdl) == ) //not acknowlage the ACK
{
i2c_stop(pHdl);
if(iRetry1++ >= pHdl->iRetry)
{
log("I2C_ERR_READ_FAILED 1");
return I2C_ERR_READ_FAILED;
}
goto retry1;
} //addr byte
i2c_WriteByte(pHdl, addr);
if (i2c_isack(pHdl) == ) //not acknowlage the ACK
{
i2c_stop(pHdl);
log("I2C_ERR_READ_FAILED 2");
return I2C_ERR_READ_FAILED;
}
retry2:
//start
i2c_start(pHdl);
//slave byte with R/W as 1
i2c_WriteByte(pHdl, (slave|0x01));
if (i2c_isack(pHdl) == ) //not acknowlage the ACK
{
i2c_stop(pHdl);
if(iRetry2++ >= pHdl->iRetry)
{
log("I2C_ERR_READ_FAILED 3");
return I2C_ERR_READ_FAILED;
}
goto retry2;
} //real read
for(i=; i<iLen; i++)
{
i2c_ReadByte(pHdl, buf+i);
if (i == (iLen-)) //the last byte will acknowlage the NACK
{
//log("if");
i2c_nack(pHdl);
}
else
{
//log("else");
i2c_ack(pHdl);
}
} //log("stop");
//stop
i2c_stop(pHdl);
//logHex(buf, iLen, "Read<%d> = ", iLen);
return iLen;
} /*
Write data to the simulator I2C bus return:
< 0 write failed, return the error No.
>=0 data length Joshua Guo. @ 2012-06-27
*/
//int SimI2CWriteDataToAddr(T_SimI2CHdl *pHdl, char slave, char addr, char *buf, int iLen)
int SimI2CWriteDataToAddr(T_SimI2CHdl *pHdl,
unsigned char slave, unsigned char addr, unsigned char *buf, unsigned char iLen)
{
int i;
int iRetry = ;
//if (pHdl == NULL || buf == NULL || iLen < 0)
if (pHdl == NULL || buf == NULL)
{
log("I2C_ERR_INVALID_PARAM");
return I2C_ERR_INVALID_PARAM;
}
if (iLen == )
{
log("iLen = 0");
return ;
} /*
* Write Data to the Device
* +---+-------+---+------------+---+------+---+---+
* | S | SLA+W | A | MemAddress | A | Data | A | P |
* +---+-------+---+------------+---+------+---+---+
* S - Start Condition
* SLA+W - Slave Address plus write bit
* MemAddress - Targe memory address within device
* Data - Data to be written
* A - Slave Acknowledge Bit
* P - Stop Condition
*/
retry:
//start
i2c_start(pHdl);
//slave
i2c_WriteByte(pHdl, slave);
if (i2c_isack(pHdl) == )
{
i2c_stop(pHdl);
if(iRetry++ >= pHdl->iRetry)
{
log("I2C_ERR_WRITE_FAILED 1");
return I2C_ERR_WRITE_FAILED;
}
goto retry;
} //addr
i2c_WriteByte(pHdl, addr);
if (i2c_isack(pHdl) == ) //not acknowlage the ACK
{
i2c_stop(pHdl);
log("I2C_ERR_WRITE_FAILED 2");
return I2C_ERR_WRITE_FAILED;
} for (i=; i<iLen; i++)
{
i2c_WriteByte(pHdl, buf[i]);
if (i2c_isack(pHdl) == ) //not acknowlage the ACK
{
i2c_stop(pHdl);
log("I2C_ERR_WRITE_FAILED 3");
return I2C_ERR_WRITE_FAILED;
}
}
i2c_stop(pHdl);
//log("return iLen = %d", iLen);
return iLen;
} // TODO: test

I2C总线以及GPIO模拟I2C的更多相关文章

  1. S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

    目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看 ...

  2. STM32F207 两路ADC连续转换及GPIO模拟I2C给MT9V024初始化参数

    1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯 ...

  3. gpio模拟i2c驱动

    前段时间做项目,需要gpio模拟i2c通信,最后参考了一些资料,然后编写了一个程序.现在发出来,以免以后忘记,也为一些需要的朋友提供参考.不喜勿喷哈. /* 说明:该程序是基于atmel公司的sama ...

  4. 【转载】GPIO模拟i2c通信

    I2C总线的通信过程(见图4-8)主要包含三个主要阶段:起始阶段.数据传输阶段和终止阶段. 1. 起始阶段 在I2C总线不工作的情况下,SDA(数据线)和SCL(时钟线)上的信号均为高电平.如果此时主 ...

  5. 51单片机 | 基于I2C总线的秒表模拟应用

    ———————————————————————————————————————————— 参考地址: http://blog.csdn.net/junyeer/article/details/4648 ...

  6. I2C总线和S5PV210的I2C总线控制器

    一.什么是I2C通信协议? 1.物理接口:SCL + SDA (1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道. (2)SDA(serial ...

  7. gpio模拟I2C,驱动pcf8574T

    一.pcf8574T介绍 查看pcf8574T的数据手册, A表示读或写,当A为1的时候表示读,当A为0的时候表示写.现把地址控制线,即A2.A1.A0全部接地,可以得到读控制指令为0x41,写控制指 ...

  8. I2C总线协议的软件模拟实现方法

    I2C总线协议的软件模拟实现方法 在上一篇博客中已经讲过I2C总线通信协议,本文讲述I2C总线协议的软件模拟实现方法. 1. 简述 所谓的I2C总线协议的软件模拟实现方法,就是用软件控制GPIO的输入 ...

  9. C51单片机模拟I2C总线驱动程序设计

    /********************************** I2C总线驱动 ******************************** 模块名:I2C总线驱动 型号:I2C 功能描述 ...

随机推荐

  1. IOS中position:fixed弹出框中的input出现光标错位的问题

    解决方案是 在弹框出现的时候给body添加fixed <style type="text/css"> body{ position: fixed; width: 100 ...

  2. py requests.get

    import osimport requestsimport jsonfrom Util import Propertiesprint('########[公务员自助列表]############## ...

  3. ci框架url去掉index.php

    去掉index.php: 1.修改配置文件, $config['index_page'] = ' '; 设置空 2.修改Apache,搜索 htaccess  将 AllowOverride None ...

  4. HTTP上传数据 :表单,二进制数据(multipart/form-data application/octet-stream boundary)

    使用WinINet 一个较简单的例子:上传头像 void CBackstageManager::UpdateAvatarThreadProc(LPVOID params) { stForThread* ...

  5. CSS3 的box-shadow进阶之 - 动画篇 - 制作辐射动画

    本篇文章是上一篇讲box-shadow基础知识的延伸,建议先花几分钟阅读那篇文章,点击阅读,再来看这篇. 除了box-shadow属性知识外,制作动画,还需要对CSS3的animation, @key ...

  6. unity中让摄像机移动到鼠标点击的位置和鼠标控制平移视角

    private Vector3 targetVector3; private float movespeed=0.5f; private bool IsOver = true; private Gam ...

  7. Oauth2.0:Access Token 与 Refresh Token

    access token 是客户端访问资源服务器的令牌.拥有这个令牌代表着得到用户的授权.然而,这个授权应该是临时的,有一定有效期.这是因为,access token 在使用的过程中可能会泄露.给 a ...

  8. HUSTOJ配置文件

    转载:http://blog.csdn.net/zhblue/article/details/7366194 经常有用户询问如何开发一些功能,实际上这些功能都已经有,或者部分实现了,只需要修改配置文件 ...

  9. html随笔CSS(*^__^*)

    控制文本显示字数,超过规定的文本长度  x显示... white-space:nowrap;        //规定不能换行 overflow:hidden; text-overflow:ellips ...

  10. 1040 有几个PAT

    字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T):第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T). 现 ...