在tq2440和mini2440上都连接着EEPROM 它们作用也不过測试I2C总线能否用。

当中在mini2440上EEPROM型号是 AT24C08,在tq2440上这个型号是 AT24C02A。

它们之间容量不同。地址线也不一样。

S3C2440A RISC 微处理器能够支持一个多主控 IIC 总线串行接口。一条串行数据线(SDA)和一条专用时钟线(SCL) 连接到 IIC 总线的总线主控和外设之间。SDA 和 SCL 线都为双向的。都连接到GPE14(SCL)  GPE15(SDA)。

为了控制多主控 IIC 总线操作,必须写入值到下面寄存器中:

– 多主控 IIC 总线控制寄存器,IICCON

– 多主控 IIC 总线控制/状态寄存器,IICSTAT

– 多主控 IIC 总线 Tx/Rx 数据移位寄存器,IICDS

– 多主控 IIC 总线地址寄存器,IICADD

因为我们仅仅把s3c2440当做主设备来用,而且系统的IIC总线上仅仅有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD无需配置。

S3C2440A 的 IIC 总线接口有 4 种工作模式:

– 主机发送模式

– 主机接收模式

– 从机发送模式

– 从机接收模式

起始和停止条件

   当 IIC 总线接口不活动时,其通常在从机模式。

换句话说,该接口在从 SDA 线上检測到起始条件之前应该处于从机模式(当 SCL 时钟信号为高时的一个高到低 SDA 的变化可

以启动一个起始条件)。当接口状态被改为主机模式时,能够起始发送数据到 SDA 上而且产生 SCL 信号。

起始条件能够传输 1 字节串行数据到 SDA 线上,而停止条件能够结束

数据的传输。

停止条件是在当 SCL 为高时的 SDA 线低到高的变化。起始和停止条件总由主机产生。当产生了一个起始条件时 IIC 总线变为忙。停止条件将使得 IIC 总线空暇。

当主机发起一个起始条件时,其应该送出一个从机地址来通知从设备。

地址字段的 1 字节由 7 位地址和 1 位传输方向标志(表现为读或写)组成。

假设位[8]为 0,其表示一个写操

作(发送操作);假设位[8]为 1,其表示一个数据读取的请求(接收操作)。

主机将通过发送一个停止条件来完毕传输操作。假设主机希望持续发送数据到总线上,其应该在同一个从地址产生再一个起始条件。这样就能够运行各种格式的读写操作。

注意到在 起始 和 停止 条件之间还有若干个SCL时钟。 用来发送数据。

传输数据格式

    放置到 SDA 线上的每一个字节应该以 8 位为长度。

每次传输字节能够无限制的发送。起始条件随后的第一个字节应该包括地址字段。当 IIC 总线工作在主机模式时能够由主机

发送该地址字段。

每一个字节都应该尾随一个应答(ACK)位。

总是最先发送串行数据和地址的 MSB。

上图勘误   这里图例应该反过来  ---  灰色框表示从从机到主机,看来翻译文档的人还不够细心呢。

上面提到了4中工作模式,在这里我们仅仅把s3c2440当做IIC总线的主设备来使用。因此仅仅介绍前两种操作模式。

首先看下主设备发送流程图:

首先配置IIC模式,然后把从设备地址写入 接收发送数据移位寄存器IICDS  中。再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号。如

果想要继续发送数据。那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后。再次等待应答信号。假设不想再发送数据了,那么

把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后。即完毕了一次主设备的发送。

代码例如以下:

//AT24C02A页写,当sizeofdate为1时。是字节写
//输入參数依次为设备内存地址、IIC数据缓存数组和要写入的数据个数
void __attribute__((optimize("O0"))) wr24c02a(UINT8 wordAddr,UINT8 *buffer,UINT32 sizeofdate )
{
int i;
i2cflag =1; //应答标志 rIICDS = devAddr;
rIICSTAT = 0xf0; //主设备发送模式
rIICCON &= ~0x10; //清中断标志 while(i2cflag == 1) //等待从设备应答,
OSTimeDly(2); //一旦进入IIC中断,就可以跳出该死循环 i2cflag = 1; rIICDS = wordAddr; //写入从设备内存地址
rIICCON &= ~0x10; while(i2cflag)
OSTimeDly(2); //连续写入数据
for(i=0;i<sizeofdate;i++)
{
i2cflag = 1;
rIICDS = *(buffer+i);
rIICCON &= ~0x10;
while(i2cflag)
OSTimeDly(2);
} rIICSTAT = 0xd0; //发出stop命令,结束该次通讯
rIICCON = 0xe0; //为下次IIC通讯做准备 OSTimeDly(100);
}

上面有2点地方须要说明。1点是刚開始的初始化 rIICCON  一定要在 rIICSTAT 后面赋值。

第2点是因为这是在多任务环境下执行的,while后面跟的OSTimeDly有延迟,也就是说假设OSTimeDly(2)延迟10ms,而在1ms的时候中断发生了。这里

仍然要延迟10ms才干继续运行,能够考虑用信号量替代。这样一旦发生中断,从中断出来之后就会马上继续运行。

然后就是主设备接收流程图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWHNjS2VybmVs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

首先配置 IIC 模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xB0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号。假设想要接收数据,那么在应答信号后。读取寄存器IICDS,清除中断标志;假设不想接收数据了,那么就向寄存器IICSTAT写入0x90。清除中断标志并等待停止条件后,即完毕了一次主设备的接收。

//AT24C02A的序列读,当sizeofdate为1时,是随机读
//输入參数依次为设备内存地址、IIC数据缓存数组和要读取的数据个数
void rd24c02a(UINT8 wordAddr,UINT8 *buffer,UINT32 sizeofdate )
{
int i;
unsigned char temp; i2cflag =1;
rIICDS = devAddr; // rIICCON &= ~0x10; //清中断标志
rIICSTAT = 0xf0; //主设备发送模式 while(i2cflag)
OSTimeDly(2); i2cflag = 1; rIICDS = wordAddr;
rIICCON &= ~0x10;
while(i2cflag)
OSTimeDly(2); i2cflag = 1;
rIICDS = devAddr; //
rIICCON &= ~0x10;
rIICSTAT = 0xb0; //主设备接收模式
while (i2cflag)
OSTimeDly(2); i2cflag = 1;
temp = rIICDS; //读取从设备地址
rIICCON &= ~0x10;
while(i2cflag)
OSTimeDly(2); //连续读
for(i=0;i<sizeofdate;i++)
{
i2cflag = 1;
if(i==sizeofdate-1) //假设是最后一个数据
rIICCON &= ~0x80; //不再响应
*(buffer+i) = rIICDS;
rIICCON &= ~0x10;
while(i2cflag)
OSTimeDly(2);
} rIICSTAT = 0x90; //结束该次通讯
rIICCON = 0xe0; // OSTimeDly(100);
}

s3c2440的 IIC 时钟源为PCLK。当系统的 PCLK 为50MHz。而从设备最高须要100kHz时,须要配置IICCON寄存器   例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWHNjS2VybmVs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

系统初始化时候配置iic寄存器例如以下:

void init_i2c(void)
{
rGPEUP |= 0xc000; //Pull-up disable
rGPECON |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL rINTMSK &= ~(1<<27); /// enable i2c
rIICCON = 0xe0; //设置IIC时钟频率,使能应答信号,并开启中断
rIICSTAT = 0x10;
pIRQ_IIC = (UINT32)i2c_isr;
}

在 i2c_isr 里面也不过把 i2cflag 赋值为0:

void i2c_isr(void)
{
i2cflag = 0;
}

详细的代码能够从我的github上clone。

參考:

博文    http://blog.csdn.net/zhaocj/article/details/5477152

s3c2440文档

atmel_at24c02a Datasheet

最新文章

  1. Node.js之NPM工具使用
  2. PowerDesigner自增列问题
  3. form上传文件以及跨域异步上传
  4. c# UpdateLayeredWindow异形窗口
  5. String课后作业
  6. js格式化日期,获取当月的第一天,与最后一天.
  7. Java API —— BigDecimal类
  8. SQL SERVER中的逻辑读,预读和物理读
  9. 读写应用程序数据-NSUserDefault、对象归档(NSKeyedArchiver)、文件操作
  10. 网络流(费用流)CodeForces 321B:Ciel and Duel
  11. MFC socket网络通讯核心代码
  12. Android中常用的颜色
  13. Bug Tracker
  14. Bootstrap Table急速完美搭建后台管理系统
  15. 使用ControllerAdvice注意事项,Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]
  16. 痞子衡嵌入式:微控制器CPU性能测试基准(EEMBC-CoreMark)
  17. git 常用命令,上传,下载,更新线上代码
  18. TZOJ 2569 Wooden Fence(凸包求周长)
  19. Android Studio 学习(一)
  20. servlet获取多个同名参数

热门文章

  1. 探索Android调用系统的分享功能
  2. CGContext含义
  3. java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
  4. 基于macOS+VMware的GNS3内VM上公网
  5. UWP tips (与wp8.1的不同)
  6. Failed reading log event, reconnecting to retry
  7. poj 2828 Buy Tickets【线段树 单点更新】
  8. 第一次接触Arduino
  9. protocol 和delegate(协议和代理)的区别
  10. Xcode 下“ did not have any applicable content ”分析及解决