mini2440开发板提供的测试代码过于复杂,让人很难理解,而且有些错误,如GPE14-15不能设置上拉电阻,可是代码里却设置了,虽然无关紧要。为了方便学习,我在闲暇之时我研究了一下。IIC的原理是比较简单的,可是在实际编程中却遇到很多困难。不知道哪里出了错误,有些逻辑上认为正确的,但在硬件上却不能实现。如下两行代码:
rGPECON &= ~(0x0f<<28);
rGPECON |= (0x0a<<28);
我们来看程序编写过程:
s3c2440的IIC七位地址时的数据接收和发送格式:
灰色的是从设备发送的。
IIC的具体时序:
由此可知SCL为高位时SDA从高位跃迁到低位时表示开始、SCL为高位时SDA从低位跃迁到高位时表示结束。我们可以设置IICSTAT寄存器来发送开始或结束信号。在第九个时钟时主设备或从设备拉低SDA,表示应答ACK。应答后产出中断,此时可以将数据写入IICDS或读出,然后清除中断标志位IICCON[4]恢复操作。具体的操作参考芯片手册或源代码。
mini2440的IIC接口连接一个EEPROM即AT24C08A,我选择页写和连续读来测试IIC接口。具体时序如下:
其中页写的时许很明确。但是连读读的时序前面不太明确,在数据手册中我们可以得知连续读是当前地址读和随机读的一种,所以前面的时序我采取随机读时许,即组合起来。要是还不太清楚请看源代码。随机读时序如下:
AT24C08A接法在硬件电路图中可知如下:
查数据手册可以其地址为0xa0或0xa1。最低位为读写标志。在s3c2440中根据IIC模式自动选择,所以地址我们只需填写0xa0即可。
值得注意的是EEPROM读写速度不是很快,所以每次读写一个字节都要加一定延时,这点十分关键。这往往是程序读写失败的原因。当然我们也需要设置好SCL的频率。在IICCON里设置这里不多说。
在接收模式下最后一个字节数据不发送ACK这点也需要注意。
测试代码中我们采用将数据写入EEPROM中然后读取出来输出到串口来检验,程序可以采用中断或轮询,代码如下:
mian.c部分
#define GLOBAL_CLK 1
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h"
typedef unsigned char uchar;
typedef unsigned int uint;
extern void AT24C08_wirte(uchar waddr, uchar *dat, int num);
extern void AT24C08_read(uchar waddr, uchar *rev, int num);
extern void IIC_init(void);
extern void delay(int time);
uchar dat[]={"0123456789abcdef"};
uchar rev[50]={0};
void Main(void)
{
rGPBCON=(1<<0);//关闭蜂鸣器
rGPBDAT=0x00;
IIC_init();
AT24C08_wirte(0x00, dat, 16);
Uart_Printf("\n\n");
AT24C08_read(0x00, rev, 10);
Uart_Printf("\n%s\n",rev);
}
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h"
typedef unsigned char uchar;
typedef unsigned int uint;
void __irq IIC_INT(void);
int flag=1;//中断标志
void delay(int time)
{
int i,j,k;
for(i=0;i<100;++i)
for(k=0;k<100;++k)
for(j=0;j
我们通过代码在结合芯片手册可以直观的了解IIC接口的读写。代码中有很多注释方便大家阅读。
程序运行结果:
将0123456789abcdef写入EEPROM,然后读出0123456789。
源代码地址:http://download.csdn.net/detail/a16839678/6010041