1      硬件特性

1.1 概述

I2C总线是由Philips公司开发的两线式串行总线,这两根线为时钟线(SCL)和双向数据线(SDA)。由于I2C总线仅需要两根线,因此在电路板上占用的空间更少,带来的问题是带宽较窄。I2C在标准模式下传输速率最高100Kb/s,在快速模式下最高可达400kb/s。属于半双工。

在嵌入式系统中,I2C应用非常广泛,大多数微控制器中集成了I2C总线,一般用于和RTC,EEPROM,智能电池电路,传感器,LCD以及其他类似设备之间的通信。

1.2 I2C总线传输时序

1.3 I2C总线的信号状态

1、  空闲状态:SDA和SCL都是高电平;

2、  开始条件(S):SCL为高电平时,SDA由高电平向低电平跳变,开始传输数据;

3、  结束条件(P):SCL为高电平时,SDA由低电平向高电平跳变,结束传输数据;

4、  数据有效:在SCL的高电平期间,SDA保持稳定,数据有效。SDA的改变只能发生在SCL的低电平期间;

5、  ACK信号:数据传输的过程中,接收器件每接收一个字节数据要产生一个ACK信号,向发送器件发出特定的低电平脉冲,表示已经收到数据。

1.4 从设备地址


I2C总线从设备使用7位地址,最后一个为读写控制位。下图是eeprom的原理图,我们可以计算出它的地址为0x50。

1.5 I2C读写方式

多字节写的时序

多字节读的时序

具体可参考datasheet

附:ok6410裸机I2C代码。

 #define INTPND (*(volatile unsigned long*)0x4a000010)
#define SRCPND (*(volatile unsigned long*)0x4a000000)
#define INTMSK (*(volatile unsigned long*)0x4a000008)
#define GPECON (*(volatile unsigned long*)0x56000040)
#define GPEUP (*(volatile unsigned long*)0x56000048) #define IICCON (*(volatile unsigned char*)0x54000000)
#define IICSTAT (*(volatile unsigned char*)0x54000004)
#define IICDS (*(volatile unsigned char*)0x5400000C) #define SLAVE_WRITE_ADD 0xa0 /* 写入数据时;方向位(第0位)为0 */
#define SLAVE_READ_ADD 0xa1 /* 读取数据时;方向位(第0位)为1 */ void delay(int i)
{
int j = ;
while (i--)
{
for (j=;j<;j++)
{
;
}
}
} void i2c_init()
{
//1.a 初始化中断
INTPND |= (<<);
SRCPND |= (<<);
INTMSK &= ~(<<); IICCON |= (<<); //1.b 设置scl时钟
IICCON &= ~(<<);
IICCON &= ~(0xf<<);
IICCON |= (0x5<<); //2. 设置IICSTAT
IICCON |= (<<); //3.设置引脚功能
GPECON |= (0x2<<)|(0x2<<);
GPEUP |= (0x3<<); //4.允许产生ACK
IICCON |= (<<);
} void write_byte(unsigned char xchar, unsigned char daddr)
{
/* 写入数据时,每发送一个数据收到一个ACK就产生一次中断
* 写入下次发送的数据之后要清除中断 */ //1. 设置处理器为主设备+发送模式
IICSTAT |= (<<); //2. 将从设备的地址写入到IICDS寄存器
IICDS = SLAVE_WRITE_ADD; //清除中断
IICCON &= ~(<<); //3. 写入0xF0写入IICSTAT M/T Start
IICSTAT = 0xF0; //4. 等待ACK的产生
while ((IICCON & (<<)) == )
delay(); //5.1写入字节的地址到IICDS寄存器
IICDS = daddr; //5.2清除中断
IICCON &= ~(<<); //5.3等待ACK的产生
while ((IICCON & (<<)) == )
delay(); //6. 将要传输的字节数据写入IICDS寄存器
IICDS = xchar; //7. 清除中断
IICCON &= ~(<<); //8. 等待ACk的产生
while ((IICCON & (<<)) == )
delay(); //9. 写入0xD0到IICSTAT
IICSTAT = 0xD0; //10. 清除中断
IICCON &= ~(<<); delay();
} void read_data(unsigned char *buf, unsigned char daddr, int length) /* 结合eeprom手册 */
{
/* 每接收一个数据产生一个中断 */ int j =;
unsigned char unusedata; //1. 设置处理器为主设备+发送模式
IICSTAT |= (<<); //2. 将从设备的地址写入到IICDS寄存器
IICDS = SLAVE_WRITE_ADD; //清除中断
IICCON &= ~(<<); //3. 写入0xF0写入IICSTAT M/T-Start
IICSTAT = 0xF0; //4. 等待ACK的产生
while ((IICCON & (<<)) == )
delay(); //5.1写入eeprom内部地址
IICDS = daddr; //5.2清除中断
IICCON &= ~(<<); //5.3等待ACK的产生
while ((IICCON & (<<)) == )
delay(); /**************eeprom代码**************/
/**************************************/
/***************i2c代码****************/ //设置为主设备接收模式
IICSTAT &= ~(<<);
IICSTAT |= (<<); //2.写入从设备地址到IICDS /* 从设备地址成功发送之后产生中断,故要清除中断 */
IICDS = SLAVE_READ_ADD;
//清除中断
IICCON &= ~(<<); //3.写入0xB0到IICSTAT开始接收,每接收道一个数据就产生一个中断
IICSTAT = 0xb0; //等待中断
while ((IICCON & (<<)) == )
delay(); #if 0
/***写入设备内部地址***/
IICDS = daddr;
IICCON &= ~( << );
while((IICCON & ( << )) == )
{
delay();
}
#endif //***丢掉收到的第1个字节 第一个数据无效 丢弃!
unusedata = IICDS;
IICCON &= ~(<<);
while ((IICCON & (<<)) == )
delay(); for(j=;j<length;j++)
{
if(j == (length - ))
{
IICCON &= ~(<<);
} //5.1 从IICDS里取出数据
buf[j]=IICDS; //5.2 清除中断
IICCON &= ~(<<); //4.等待中断
while ((IICCON & (<<)) == )
delay();
} //写入0x90到IICSTAT
IICSTAT = 0x90; // 清除中断
IICCON &= ~(<<);
} void i2c_test()
{
int i=;
unsigned char sbuf[]={};
unsigned char dbuf[]={}; i2c_init(); for(i=;i<;i++)
{
sbuf[i] = i+;
dbuf[i] = ;
} printf("dbuf befor I2C read:\r\n");
for(i =; i<;i++)
{
if(i%==)
printf("\r\n"); /* */ printf("%d\t",dbuf[i]); /*t-空格 */
} for(i=;i<;i++)
write_byte(sbuf[i],i); printf("i2c reading, plese wait!\n\r"); read_data(dbuf,,); printf("dbuf after I2C read:\r\n"); for(i =; i<;i++)
{
if(i%==)
printf("\r\n"); printf("%d\t",dbuf[i]);
}
}

linux之I2C裸机驱动解析(转)的更多相关文章

  1. linux下i2c的驱动架构分析和应用

    i2c在linux下的代码在/driver/i2c下面,总体代码如下所示: i2c-core.c 这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口.    i2c-dev.c  实现 ...

  2. Linux kernel 之 uart 驱动解析

    uart 是一种非常之常见的总线,比如DEBUG信息输出,小数据量数据传输,485,以及蓝牙的控制,GPS,很多都是通过uart 进行数据传输并进行控制. 在Linux kernel 内部,uart ...

  3. I2C裸机驱动程序设计

    ① I2C(Inter-Integrated Circuit)总线是由飞利浦公司开发的两线式串行总线,用于连接微控制器及其外围设备 ② I2C总线有两根双向信号线 (1)SDA:Serial Data ...

  4. [国嵌攻略][153][I2C裸机驱动设计]

    eeprom简介 eeprom电可擦除可编程只读存储器,是一种类似于flash的固态存储器,但是与flash相比又存在一些区别: 1.eeprom可以按位擦写,而flash只能大片擦除. 2.eepr ...

  5. Linux I2C设备驱动编写(一)

    在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I2C driver 某个I2C设备的设备驱动,可以以driver理解. I2C client 某个I2C ...

  6. 【转】Linux I2C设备驱动编写(一)

    原文网址:http://www.cnblogs.com/biglucky/p/4059576.html 在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I ...

  7. 【驱动】linux下I2C驱动架构全面分析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  8. TQ2440学习笔记——Linux上I2C驱动的两种实现方法(1)

    作者:彭东林 邮箱:pengdonglin137@163.com 内核版本:Linux-3.14 u-boot版本:U-Boot 2015.04 硬件:TQ2440 (NorFlash:2M   Na ...

  9. linux下I2C驱动架构全面分析【转】

    本文转载自:http://blog.csdn.net/wangpengqi/article/details/17711165 I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一 ...

随机推荐

  1. How to Modify Public Network Information including VIP in Oracle Clusterware (文档 ID 276434.1)

    APPLIES TO: Oracle Database - Enterprise Edition - Version 11.2.0.3 to 12.1.0.2 [Release 11.2 to 12. ...

  2. Redis集群搭建&访问

    集群搭建步骤 1.创建多个节点: 2.为每个节点指派槽,并将多个节点连接起来,组成一个集群: 3.当集群数据库的16384个槽都有节点在处理时,集群进入上线状态: 要求:搭建一个包含6个节点的Redi ...

  3. 翻译:Knockout 快速上手 - 2: 安装 knockoutJS

    只需要五个简单的步骤,就可以做好使用 Knockout 开发的准备! 第一步 我们需要什么? 最低限度,为了完成后面的教程,你需要如下的准备 Web 浏览器 文本编辑器 你的电脑上大约 2M 的磁盘空 ...

  4. VS2010 和VS2012 的程序在XP上运行的方法

    问题表象: VS2012编译的程序不能再XP下运行 解决办法: 1.工程设置的方法 在vs2012里,右键 属性->配置属性-常规->平台工具集->选个VS2008什么的就ok了~ ...

  5. Android 中获取 debug 测试 SHA1 和 release SHA1 证书指纹数据的方法

    百度地图开发的时候要申请KEY,需要提供SHA1证书指纹数据 Eclipse eclipse中直接查看:windows -> preferance -> android -> bui ...

  6. python-appium练习编写脚本时遇到问题

    遇到问题: 1.安卓4.2及以下系统无法识别resource-id属性 只能用text属性识别 2.输入中文无法识别 脚本最顶部增加#coding=utf-8 3.对象无法识别resource-id属 ...

  7. 菜鸟学四轴控制器之3:数字积分法DDA实现直线插补

    上一篇的逐点比较法显然是无法画一条有倾角的直线的.因为X轴和Y轴永远都不同步,也就是像打台球一样,你打一个,我打一个,如果我进了球,我再接着打一个. 也就是说,如果直线为45度,也是没有办法画出来的, ...

  8. nginx 代理配置文件实例

    安装NGINX前要先安装PCRE正则表达式库: ./configure --prefix=/usr/local/pcre 出现以下错误  (一般./configure即可, 笔者这里是直接./conf ...

  9. JS常用的设计模式(16)—— 享元模式

    享元模式主要用来减少程序所需的对象个数. 有一个例子, 我们这边的前端同学几乎人手一本<JavaScript权威指南>. 从省钱的角度讲, 大约三本就够了. 放在部门的书柜里, 谁需要看的 ...

  10. leetcode 101

    101. Symmetric Tree Given a binary tree, check whether it is a mirror of itself (ie, symmetric aroun ...