Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40801
  • 博文数量: 18
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-05 10:27
文章分类
文章存档

2011年(1)

2009年(1)

2008年(16)

我的朋友

分类:

2008-11-03 17:09:22

最近做了一个 V2 上的 FM tuner 模块(实际上我只是代码搬运工,原code 大部分搬自jim 的case),使用到了 I2C 协议,总结一下与大家 share。
一. 技术性能:
    工作速率有100K和400K两种;
    支持多机通讯;
    支持多主控模块,但同一时刻只允许有一个主控;     
    由数据线SDA和时钟SCL构成的串行总线;
    每个电路和模块都有唯一的地址;                   
    每个器件可以使用独立电源

二. 基本工作原理:
    以启动信号START来掌管总线,以停止信号STOP来释放总线;
    每次通讯以START开始,以STOP结束;
    启动信号START后紧接着发送一个地址字节,其中7位为被控器件的地址码,一位为读/写控制位R/W,R. /W位为0表示由主控向被控器件写数据,R/W为1表示由主控向被控器件读数据;
    当被控器件检测到收到的地址与自己的地址相同时,在第9个时钟期间反馈应答信号;
    每个数据字节在传送时都是高位(MSB)在前;

写通讯过程:
    1. 主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
    2. 发送一个地址字节(包括7位地址码和一位R/W);
    3. 当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
    4. 主控收到ACK后开始发送第一个数据字节;
    5. 被控器收到数据字节后发送一个ACK表示继续传送数据,发送NACK表示传送数据结束;
    6. 主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;

读通讯过程:
    1. 主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
    2. 发送一个地址字节(包括7位地址码和一位R/W);
    3. 当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
    4. 主控收到ACK后释放数据总线,开始接收第一个数据字节;
    5. 主控收到数据后发送ACK表示继续传送数据,发送NACK表示传送数据结束;
    6. 主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;

四. 总线信号时序分析
    1. 总线空闲状态
    SDA和SCL两条信号线都处于高电平,即总线上所有的器件都释放总线,两条信号线各自的上拉电阻把电平拉高;
    2. 启动信号START
    时钟信号SCL保持高电平,数据信号SDA的电平被拉低(即负跳变)。启动信号必须是跳变信号,而且在建立该信号前必修保证总线处于空闲状态;
    3. 停止信号STOP
    时钟信号SCL保持高电平,数据线被释放,使得SDA返回高电平(即正跳变),停止信号也必须是跳变信号。
    4. 数据传送
    SCL线呈现高电平期间,SDA线上的电平必须保持稳定,低电平表示0(此时的线电压为地电压),高电平表示1(此时的电压由元器件的VDD决定)。只有在SCL线为低电平期间,SDA上的电平允许变化。
    5. 应答信号ACK
    I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个ACK(把数据总线的电平拉低)来表示数据成功接收。
    6. 无应答信号NACK
    在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
    a. 一般表示接收器未成功接收数据字节;
    b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。

五. 寻址约定
    地址的分配方法有两种:
    1. 含CPU的智能器件,地址由软件初始化时定义,但不能与其它的器件有冲突;
    2. 不含CPU的非智能器件,由厂家在器件内部固化,不可改变。

    高7位为地址码,其分为两部分:
    1. 高4位属于固定地址不可改变,由厂家固化的统一地址;
    2. 低三位为引脚设定地址,可以由外部引脚来设定(并非所有器件都可以设定);
 
 
 
上面是主要的协议,下面结合我们的代码做简要的分析:
1、I2C 总线很简单,只有一根 CLK 一根 DATA,不过虽然这么简单,我还是因为没有设对 CLK 而白忙活了很久:现有的 V2 里面,没有用的 IIC 的模块,所以默认是没有打开的。在IIC.c 里面找到了
IIC_Initialize()  函数,
里面有个 IIC_SetClockRate(CLK_100K);
其中 #define CLK_100K  (100*1024)
这样就将 clk 设置好了。参考其他的 case 的sourcecode,发现其实只要在 config.h 里面加个
#define SMTK_RTC_IIC_ENBLE 就可以在程序的某个位置地方调用到上面的 IIC  Initialize程序了,具体位置自己搜索啦~~!
PS:
  • 示波器是个好东西,它帮我找到了问题的根源
  • GDB 的调试,本身就有部分的 bug 还没完善,再加上我们的程序其实有对 thread 的support那段沒porting,所以 Debug 的时候也经常遇到一些怪怪的问题,所以最好的方式还是用 printf message!

设置好 CLK,就开始按部就班的来 send data 跟 write data 了。过程没什么好讲的,其实就是按照协议,对相应的 IIC 寄存器做一些操作。也就是通过类似这样的方式

    AHB_WriteRegister(REG_I2C_DATA, (MMP_UINT16)slaveAddr);
    AHB_WriteRegister(REG_I2C_CONTROL,
                        REG_BIT_INTR_TRIG | REG_BIT_CONTL_TRANSFER_BYTE | REG_BIT_CONTL_CLK_ENABLE |
                        REG_BIT_CONTL_I2C_ENABLE | REG_BIT_CONTL_START);

对 IIC 相关几个寄存器赋值。因为 FM TUNER 的模块已经连在 IIC 总线上面,所以他们会收到这些数据,然后判断地址是否匹配,然后就接着一下步的动作...

 

 
 
 
 
阅读(845) | 评论(0) | 转发(0) |
0

上一篇:Video部分学习

下一篇:UI修改之Brightness Menu

给主人留下些什么吧!~~