S3C2440A 的IIC 总线接口有4 种工作模式:
– 主机发送模式
– 主机接收模式
– 从机发送模式
– 从机接收模式
这里把S3C2440A单做主机,AT24C08单做从机,讲解主机发送模式,主机接收模式
I2C总线的数据传输协议如下:
(1)、主器件发出开始信号
(2)、主器件发出第一个字节,用来选通相应的从器件。其中前7位为地址码,第8位为方向位(R/W)。方向位为“0”表示发送,方向位为“1”表示接受。
(3)、从机产生应答信号,进入下一个传送周期,如果从器件没有给出应答信号,此时主器件产生一个结束信号使得传送结束,传送数据无效。
(4)、接下来主、从器件正式进行数据的传送,这时在I2C总线上每次传送的数据字节数不限,但每一个字节必须为8位(传送的时候先送高位,再送低位)。当一个字节传送完毕时,再发送一个应答位(第9位),如上一条所述,这样每次传送一个字节都需要9个时钟脉冲。
每一次传送之后都要进行应答,除非到了最后一个数据
当主器件传送一个字节后,在第9个SCL时钟内置高SDA线,而从器件的响应信号将SDA拉低,从而给出一个应答位。
当使用24WC08 时最多可连接2 个器件且仅使用地址管脚A2 A0 A1 管脚未用可以连接到
Vss(地) 或悬空如果只有一个24WC08 被总线寻址A2 管脚可悬空或连接到Vss
- #include "2440addr.h"
-
#include "uart.h"
-
#include "def.h"
-
#include "IIC.h"
-
-
-
extern void Delay(int time);
-
//全局变量
-
static U8 _iicData[IICBUFSIZE];
-
static volatile int _iicDataCount;
-
static volatile int _iicStatus;
-
static volatile int _iicMode;
-
static int _iicPt; //指针
-
-
-
void __irq IicInt(void)
-
{
-
U32 iicSt,i;
-
-
rSRCPND = BIT_IIC; //Clear pending bit
-
rINTPND = BIT_IIC;
-
//iicSt = rIICSTAT;
-
-
//if(iicSt & 0x8){} //When bus arbitration is failed.
-
//if(iicSt & 0x4){} //When a slave address is matched with IICADD
-
//if(iicSt & 0x2){} //When a slave address is 0000000b
-
//if(iicSt & 0x1){} //When ACK isn't received
-
-
switch(_iicMode)
-
{
-
//case POLLACK:
-
// _iicStatus = iicSt;
-
// break;
-
-
case RDDATA:
-
if((_iicDataCount--)==0)
-
{
-
_iicData[_iicPt++] = rIICDS;
-
-
rIICSTAT = 0x90; //Stop MasRx condition
-
rIICCON = 0xaf; //Resumes IIC operation.
-
Delay(1); //Wait until stop condtion is in effect.
-
//Too long time...
-
//The pending bit will not be set after issuing stop condition.
-
break;
-
}
-
_iicData[_iicPt++] = rIICDS; //The last data has to be read with no ack.
-
-
if((_iicDataCount)==0)
-
rIICCON = 0x2f; //Resumes IIC operation with NOACK.
-
else
-
rIICCON = 0xaf; //Resumes IIC operation with ACK
-
break;
-
-
case WRDATA:
-
if((_iicDataCount--)==0)
-
{
-
rIICSTAT = 0xd0; //Stop MasTx condition
-
rIICCON = 0xaf; //Resumes IIC operation.
-
Delay(1); //Wait until stop condtion is in effect.
-
//The pending bit will not be set after issuing stop condition.
-
break;
-
}
-
rIICDS = _iicData[_iicPt++]; //_iicData[0] has dummy.地址,不是我们要的数据
-
for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
-
-
rIICCON = 0xaf; //resumes IIC operation.
-
break;
-
-
case SETRDADDR:
-
// Uart_Printf("[ S%d ]",_iicDataCount);
-
if((_iicDataCount--)==0)
-
break; //IIC operation is stopped because of IICCON[4]
-
rIICDS = _iicData[_iicPt++]; //扔到IICDATA数据线上,串行传输
-
for(i=0;i<10;i++); //For setup time until rising edge of IICSCL
-
rIICCON = 0xaf; //Resumes IIC operation.
-
break;
-
-
default:
-
break;
-
}
-
}
-
-
-
-
-
-
void Wr24C080(U32 slvAddr,U32 addr,U8 data)
-
{
-
_iicMode = WRDATA;
-
_iicPt = 0;
-
_iicData[0] = (U8)addr;
-
_iicData[1] = data;
-
_iicDataCount = 2;
-
-
rIICDS = slvAddr; //0xa0
-
rIICSTAT = 0xf0; //MasTx,Start
-
//Clearing the pending bit isn't needed because the pending bit has been cleared.
-
-
while(_iicDataCount!=-1); //等待应答信号
-
-
_iicMode = POLLACK;
-
-
while(1)
-
{
-
rIICDS = slvAddr;
-
_iicStatus = 0x100;
-
rIICSTAT = 0xf0; //MasTx,Start
-
rIICCON = 0xaf; //Resumes IIC operation.
-
-
//while(_iicStatus==0x100);//等待中断,这里无实质意义,
-
//只是为了看状态寄存器的值改变否?用个1ms的延时代替也可
-
Delay(1);
-
-
if(!(_iicStatus&0x1))
-
break; //When ACK is received
-
}
-
rIICSTAT = 0xd0; //Stop MasTx condition
-
rIICCON = 0xaf; //Resumes IIC operation.
-
Delay(1); //Wait until stop condtion is in effect.
-
//Write is completed.
-
}
-
-
-
-
void Rd24C080(U32 slvAddr,U32 addr,U8 *data)
-
{
-
_iicMode = SETRDADDR;
-
_iicPt = 0;
-
_iicData[0] = (U8)addr;
-
_iicDataCount = 1;
-
-
rIICDS = slvAddr;
-
rIICSTAT = 0xf0; //MasTx,Start
-
//Clearing the pending bit isn't needed because the pending bit has been cleared.
-
while(_iicDataCount!=-1); //等待中断
-
-
_iicMode = RDDATA;
-
_iicPt = 0;
-
_iicDataCount = 1;
-
-
rIICDS = slvAddr;
-
rIICSTAT = 0xb0; //MasRx,Start
-
rIICCON = 0xaf; //Resumes IIC operation.
-
while(_iicDataCount!=-1);
-
-
*data = _iicData[1];//数据总是放在这个元素里面
-
}
-
-
-
-
-
-
void Test_Iic(void)
-
{
-
unsigned int i,j;
-
static U8 data[256];
-
-
Uart_Printf("\nIIC Test(Interrupt) using AT24C02\n");
-
-
-
rGPEUP |= 0xc000; //Pull-up disable
-
rGPECON |= 0xa00000; //GPE15:IICSDA , GPE14:IICSCL
-
-
pISR_IIC = (unsigned)IicInt; //中断处理函数的并联,要用到MMU,因为烧到SDRAM的话,中断向量不再0x00000000那里
-
rINTMSK &= ~(BIT_IIC); //开启中断
-
-
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
-
// If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz
-
rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
-
-
//rIICADD = 0x10; //2440 slave address = [7:1],2440做从机的地址
-
rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
-
//rIICLC = (1<<2)|(1); // Filter enable, 15 clocks SDA output delay added by junon
-
-
Uart_Printf("Write test data into AT24C08\n");
-
-
for(i=0;i<256;i++) //第一个参数:AT24C08地址,第二个参数:AT24C08内部地址,第三个参数,数据
-
Wr24C080(0xa0,(U8)i,i);//0xa0,0xa1无所谓,因为2440有主从机收发4种模式
-
-
for(i=0;i<256;i++)
-
data[i] = 0;
-
-
Uart_Printf("Read test data from AT24C08\n");
-
-
for(i=0;i<256;i++)
-
Rd24C080(0xa0,(U8)i,&(data[i])); //0xa0,0xa1无所谓,因为2440有主从机收发4种模式
-
-
//Line changed 0 ~ f
-
for(i=0;i<16;i++)
-
{
-
for(j=0;j<16;j++)
-
Uart_Printf("%2x ",data[i*16+j]);
-
Uart_Printf("\n");
-
}
-
rINTMSK |= BIT_IIC; //关闭中断
-
}
说明:
1:注意那几个全局变量的值,很灵活,程序不好懂
2:发送,接受都是用到中断,尤其是应答信号,烧到SDRAM中的话,要在mian中初始化MMU,,因为烧到 SDRAM的话,中断向量已经改变了
3:操作时序按,2440芯片手册的主机收发模式操作,细细体会,出差的话很难调试的,尤其某些地方需要延时,试了好几个程序,都没成功,最终参看模板中的这个~_~
阅读(2486) | 评论(0) | 转发(0) |