|
亚瑟王 发表于 2012-10-12 16:33 
亲,总结一下,发个总结吧。谢谢了。
行, 我已经按照自己程序结构做了详细的解析,分享在了心得体会中,标题为“基于S3C2440的24C02的IIC总线操作”,如您有空帮我看看有没有不对的地方。
S3C2440对24C02的IIC总线基本操作
#include"2440addr.h"
#include"iic.h"
#include"uart.h"
int TT;
void Delay(int time) //延时程序(精确)
{
unsigned int val = (50000000>>3)/1000-1;
rTCFG0 &= ~(0xff<<8);
rTCFG0 |= 3<<8; //prescaler = 3+1
rTCFG1 &= ~(0xf<<12);
rTCFG1 |= 0<<12; //mux = 1/2
rTCNTB3 = val;
rTCMPB3 = val>>1; // 50%
rTCON &= ~(0xf<<16);
rTCON |= 0xb<<16; //interval, inv-off, update TCNTB3&TCMPB3, start timer 3
rTCON &= ~(2<<16); //clear manual update bit
while(time--) {
while(rTCNTO3>=val>>1);
while(rTCNTO3<val>>1);}
}
void __irq IicIn(void)
{
rSRCPND |= (BIT_IIC);
rINTPND |= (BIT_IIC);
TT=0;
}
void Test_Iic(void)
{
int i;
unsigned int save_E,save_PE;
static unsigned char A_1='0',A_2='0';
save_E = rGPECON;
save_PE = rGPEUP;
rGPEUP |= 0xc000; //这句代码的意图禁止GPE14和GPE15上拉,可是真有用吗?S3C2440数据手册上明明写着
//This pad is open-drain,There is no Pull-up option
rGPECON |= 0xa0000000; //很多资料均写的0xa00000;我都不知道他们是不是真的在S3C2440
//到底跑过,写出来害我类初学者
pISR_IIC = (unsigned int)IicIn; //装载中断函数
rINTMSK &= ~(BIT_IIC); //使能IIC中断
rIICCON = (1<<7)|(0<<6)|(1<<5)|(0xf); //ACk、接收发送中断的使能,总线发送时钟的设置
rIICADD = 0x10; //给主机分配作为从机时的总线地址,在本试验S3C2440一直作为主机,可设置也可不设置。但是注意了
//如果要写入这个地址,必须首先确认IICSTAT[4]=0,关于读取却可以在任意时刻。
rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
rIICLC = (1<<2)|(1); //总线线路控制寄存器,这个可以不设置。
putc('A');
A_1='U';
for(i=65;i<91;i++) //我想向AT24C02中写入‘a?~‘z'字母,直接使用ASCII码
{A_1=i;
Wr24c02(0xa0,i-65,A_1);}
Wr24c02(0xa0,2,'M');
for(i=0;i<256;i++)
{Rd24c02(0xa0,i,&A_2);
putc(A_2);}
putc('A');
rINTMSK |= BIT_IIC; //禁止中断操作
rGPEUP = save_PE; //恢复IO口
rGPECON = save_E;
}
void Delay_1(int time) //延时程序,为了操作对AT24C02总线时序时滞和硬件反应时间的控制
{
int i,j;
for(j=0;j<time;j++)
for(i=0;i<10;i++);
}
void Wr24c02(unsigned char slvaddr,unsigned char addr,unsigned char data)
{
rIICDS = slvaddr; //将从机器地址发送到接收发送数据寄存器IICDS中
rIICSTAT = 0xf0; //配置为主发送模式,(写)开始信号输出,滞后IICDS中的数据开始发送
TT=1; //中断标记,相信大家都知道它用来干嘛
while(TT) // waitting for interrput 1,第一个ACK后当然要产生中断了。见图1的信号操作过程
Delay_1(10);
rIICDS = addr; //送入写入首地址
Delay_1(1); //为了实现IICSCL上升沿的建立时间
rIICCON = 0xaf; //Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
TT=1;
while(TT) // waitting for interrput 2,第二个ACK后的中断
Delay_1(10);
rIICDS = data; //将数据送到IICDS中
Delay_1(1);
rIICCON = 0xaf; //同上
TT=1;
while(TT) // waitting for interrput 3,第三个ACK后的中断
Delay_1(10);
rIICSTAT = 0xd0; //生成停止信号(写模式下IICSTAT[5]的定义可知)
rIICCON = 0xaf; //恢复操作
//Delay(1);
/*rIICDS = slvaddr;
rIICSTAT = 0xf0;
rIICCON = 0xaf;
TT=1;
while(TT) // waitting for interrput 4
Delay_1(10);
while(!(rIICSTAT&0x01));
rIICSTAT = 0xd0;
rIICCON = 0xaf;*///上诉几行代码是我在参考TQ2440测试程序代码中写的,说是ACK模式下的操作,在这里的简单操作模式中没有也可以。
Delay(10);
}
void Rd24c02(unsigned char slvaddr,unsigned char addr,unsigned char *data)
{
unsigned char temp;
rIICDS = slvaddr;//发送从机地址,实现伪写
rIICSTAT = 0xf0; //配置为主发送模式,(写)开始信号输出,滞后IICDS中的数据开始发送
TT=1;
while(TT) // waitting for interrput 1
Delay_1(10);
rIICDS = addr; //将首地址送入rIICDS
Delay_1(1);
rIICCON = 0xaf;//Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
TT=1;
while(TT) // waitting for interrput 2
Delay_1(10);
rIICDS = slvaddr; //发送从机地址,实现真正从机的发送
rIICSTAT = 0xb0; //配置接收模式
rIICCON = 0xaf;//Resumes IIC operation.清除了IIC中断标记,不清除的话,总线将持续挂起,清除后开始传送数据了
TT=1;
while(TT) // waitting for interrput 3
Delay_1(10);
temp =rIICDS; //发送带有读命令的从设备地址后,24C02再返回一个从设备地址信息或从设备内存地址信息作为应答
//所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息。
rIICCON = 0x2f;
TT=1;
while(TT) // waitting for interrput 4
Delay_1(10);
*data = rIICDS;
rIICSTAT = 0x90;
rIICCON = 0xaf;
Delay(10);
}
这段程序费了我一周时间,由于本人是初学者有点难度,相信这些代码对其他初学者IIC总线的学习有所帮助。
|
|