S5PV210 I2C总线
来源:互联网 发布:unity3d 实现拍照功能 编辑:程序博客网 时间:2024/05/02 21:00
I2C(Inter-Integrated Circuit)总线是一种由 Philips 公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C 总线只有两根连接接口(串行数据 SDA 和串行时钟 SCL
线) ,具有使用方便,连接简单,占用空间小,并且支持多主控等优点。因此,在嵌入式系统中,I2C 总线被广泛应用于许多重要外扩设备的连接.
总线上发送数据的器件被称作发送器,接收数据的器件被称作接收器。控制信息交换的器件被称作主器件(CPU) ,受主器件控制的器件则被称作从器件(AT24Cxx 芯片在总
线中作为从器件工作) 。主器件产生串行时钟 SCL,控制总线的访问状态、产生 S 和 P 信号.只有当总线处于空闲状态时才可以启动数据传输,每次数据传输都始于 S 信号,
结束于P 信号,二者之间传输的数据字节没有限制,由总线上的主器件决定,数据以字节(8bit)为单位传输,第 9 位时由接收器产生应答.
I2C 总线的信号类型
② 结束信号(P): SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。
③ 响应信号(ACK):接收设备在接收到 8 位的数据后,在第 9 个时钟周期,拉低 SDA 电平。(注意:谁接收数据,就由谁发出 ACK 信号)
SDA 上传送的数据必须在 SCL 为高电平期间保持稳定,SDA 上的数据只能在SCL 为低电平期间变化
S5PV210 I2C
相关寄存器
多主设备 I2C 总线控制寄存器--I2CCON
多主设备 I2C 总线控制状态寄存器 -- I2CSTAT
多主设备 I2C 总线接收/发送数据移位寄存器 -- I2CDS
多主设备 I2C 总线地址寄存器 -- I2CADD.
当 I2C 总线为空闲时,SDA 和 SCL 总线都应被置为高电平。SDA 从高到低的变化能够初始化一个起始条件。当 SCL 保持稳定在高电平,SDA 从低到高的变化可以初始化一个停止条件,起始和停止条件都是由主设备生成的。 在第一个字节中的一个 7 位地址的值可以决定一个由主设备选择的从设备,其地址在起始条件初始化后被放到总线上。第 8 位决定的是传输方向(读或写),放到 SDA 线上的每个数据字节总共应该是 8 位。在总线传输期间,该字节可以被无限制地发送或接收。数据发送总是先对 MSB,每个字节应该紧跟一个应答位(ACK bit)。
数据传输格式:
开始信号 | 地址(7 位) | 读/写控制信号 | 应答 | 数据(8 位) | 应答 | 停止信号
S5PV210 I2C 读写操作
在接收模式下,如果数据收到后,I2C 总线接口会等待直到 I2C 总线数据移位寄存器被读出。在新的数据被读出寄存器之前,SCL 线将保持低电平,然后再数据被读出后再释
放。S5PV210 应该保持中断来识别当前数据接收是否完成。在CPU 收到中断请求后,它应该从 I2CDS 寄存器读取数据。
如果一个从接收器不能应答从属设备地址的确认, 它应该保持 SDA 线的电平为高。在这种情况下,主设备应该生成一个停止条件并终止数据的传输。如果主设备的接收器也参
与了被终止传输, 它应该通过在从设备收到最后自己后取消 ACK 信号的生成, 给从设备传输操作的最后发信号。 从设备发送器应该释放 SDA 线以允许主设备产生一个停止条件。
#include "i2c.h"#include "lib.h"#include "led.h"#define WRDATA (1)#define RDDATA (2)typedef struct tI2C { unsigned char *pData; /* 数据缓冲区 */ volatile int DataCount; /* 等待传输的数据长度 */ volatile int Status; /* 状态 */ volatile int Mode; /* 模式:读/写 */ volatile int Pt; /* pData中待传输数据的位置 */}t210_I2C, *pt210_I2C;static t210_I2C g_t210_I2C;void i2c_init(void){/* 选择引脚功能:GPD1_0:IIC0_SDA, GPD1_1:IIC0_SCL */GPD1CON |= 0x22;// GPD1CON[7:4] = 0b0010,GPD1CON[3:0] = 0b0010GPD1PUD |= 0x5;// GPD1PUD[3:0] = 0b0101 禁止上拉/* bit[7] = 1, 使能ACK* bit[6] = 0, IICCLK = PCLK/16* bit[5] = 1, 使能中断* bit[3:0] = 0xf, Tx clock = IICCLK/16* PCLK = 66.7MHz, IICCLK = 4.1MHz*/IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); // 0xafIICSTAT = 0x10; // I2C串行输出使能(Rx/Tx)}/* * 主机发送 * slvAddr : 从机地址,buf : 数据存放的缓冲区,len : 数据长度 */void i2c_write(unsigned int slvAddr, unsigned char *buf, int len){ g_t210_I2C.Mode = WRDATA; // 写操作 g_t210_I2C.Pt = 0; // 索引值初始为0 g_t210_I2C.pData = buf; // 保存缓冲区地址 g_t210_I2C.DataCount = len; // 传输长度 IICDS = slvAddr; IICSTAT = 0xf0; // 主机发送,启动,后续的传输工作将在中断服务程序中完成 /* 等待直至数据传输完毕 */ while (g_t210_I2C.DataCount != -1);} /* * 主机接收 * slvAddr : 从机地址,buf : 数据存放的缓冲区,len : 数据长度 */void i2c_read(unsigned int slvAddr, unsigned char *buf, int len){ g_t210_I2C.Mode = RDDATA; // 读操作 g_t210_I2C.Pt = -1; // 索引值初始化为-1,表示第1个中断时不接收数据(地址中断) g_t210_I2C.pData = buf; // 保存缓冲区地址 g_t210_I2C.DataCount = len; // 传输长度 IICDS = slvAddr; IICSTAT = 0xb0; // 主机接收,启动,后续的传输工作将在中断服务程序中完成 /* 等待直至数据传输完毕 */ while (g_t210_I2C.DataCount != 0);}/* 真正的I2C中断服务函数 */void do_i2c_irq(void) {unsigned int i;//用于简单延时switch (g_t210_I2C.Mode){ case WRDATA://写中断{if((g_t210_I2C.DataCount--) == 0){// 下面两行用来恢复I2C操作,发出P信号IICSTAT = 0xd0;// 发出P信号,但由于IICCON[4]仍为1,P信号实际还没有发出IICCON = 0xaf;//当清除IICCON[4]后,P信号才真正发出信号delay(10000); // 等待一段时间以便P信号已经发出break; }IICDS = g_t210_I2C.pData[g_t210_I2C.Pt++];// 将数据写入IICDS后,需要一段时间才能出现在SDA线上for (i = 0; i < 10; i++); IICCON = 0xaf; // 恢复I2C传输,IICCON[4] = 0break;}case RDDATA: //读中断{if (g_t210_I2C.Pt == -1){// 这次中断是发送I2C设备地址后发生的,没有数据// 只接收一个数据时,不要发出ACK信号g_t210_I2C.Pt = 0;if(g_t210_I2C.DataCount == 1)IICCON = 0x2f; // 恢复I2C传输,开始接收数据,接收到数据时不发出ACKelse IICCON = 0xaf; // 恢复I2C传输,开始接收数据,接收到数据时发出ACKbreak;}g_t210_I2C.pData[g_t210_I2C.Pt++] = IICDS;g_t210_I2C.DataCount--;if (g_t210_I2C.DataCount == 0){// 下面两行恢复I2C操作,发出P信号IICSTAT = 0x90;IICCON = 0xaf;delay(10000); // 等待一段时间以便P信号已经发出break; } else{ // 接收最后一个数据时,不要发出ACK信号if(g_t210_I2C.DataCount == 1)IICCON = 0x2f; // 恢复I2C传输,接收到下一数据时无ACKelse IICCON = 0xaf; // 恢复I2C传输,接收到下一数据时发出ACK}break;}default: break; }// 清中断向量VIC0ADDRESS = 0x0;VIC1ADDRESS = 0x0;VIC2ADDRESS = 0x0;VIC3ADDRESS = 0x0;IICCON &= ~(1<<4); //第4位用于中断的标志,当接收或发送数据后一定要对该位,进行清零,以清除中断标志} /* 需要根据AT24Cxx芯片手册的读字节协议 */unsigned char at24cxx_read(unsigned char address){unsigned char val;i2c_write(0xA0, &address, 1);//AT24C02的设备地址为0xa0i2c_read(0xA0, (unsigned char *)&val, 1);return val;}/* 需要根据AT24Cxx芯片手册的写字节协议 */void at24cxx_write(unsigned char address, unsigned char data){unsigned char val[2];val[0] = address;val[1] = data;i2c_write(0xA0, val, 2);}
- S5PV210 I2C总线
- S5PV210 Linux -- IO口模拟I2C总线驱动
- s5pv210 i2c总线驱动s3c2410.c 完全解析1
- s5pv210 i2c总线驱动s3c2410.c 完全解析2
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- i2c总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- I2C总线
- 机房收费系统之窗体遍历
- 给出入栈序列为A,B,C,D,E,可能的出栈序列
- rhadoop
- (采用标准输入输出)在本机测试时用文件重定向,一旦提交到比赛就可以方面删除重定向语句的范例
- 软件测试工具的选择和使用
- S5PV210 I2C总线
- 重谈设计
- 机房收费系统之上下机
- 研发管理学常用定律与思考
- 【BZOJ1500】[NOI2005]维修数列 Splay
- csu oj 1031 Real Numbers(模拟)
- 最长单调递增子序列
- CODE[VS]_3143二叉树的序遍历
- onTouchEvent中 ACTION_MOVE不响应的问题