实验工具:rvds2.2
实验系统:windows 7
1 硬件特性
1.1 概述
I2C总线是由Philips公司开发的两线式串行总线,这两根线为时钟线(SCL)和双向数据线(SDA)。由于I2C总线仅需要两根线,因此在电路板上占用的空间更少,带来的问题是带宽较窄。I2C在标准模式下传输速率最高100Kb/s,在快速模式下最高可达400kb/s。属于半双工。
在嵌入式系统中,I2C应用非常广泛,大多数微控制器中集成了I2C总线,一般用于和RTC,EEPROM,智能电池电路,传感器,LCD以及其他类似设备之间的通信。
1.2 I2C总线传输时序

1.3 I2C总线的信号状态
1、 空闲状态:SDA和SCL都是高电平;
2、 开始条件(S):SCL为高电平时,SDA由高电平向低电平跳变,开始传输数据;
3、 结束条件(P):SCL为高电平时,SDA由低电平向高电平跳变,结束传输数据;
4、 数据有效:在SCL的高电平期间,SDA保持稳定,数据有效。SDA的改变只能发生在SCL的低电平期间;
5、 ACK信号:数据传输的过程中,接收器件每接收一个字节数据要产生一个ACK信号,向发送器件发出特定的低电平脉冲,表示已经收到数据。
2 ok6410 i2c实验
首先我们在这里不得不说一下飞凌的ok6410实在是不怎么样,竟然没有i2c-eepROM,所以我们只能通过示波器检测外接的user IO中i2c的SCL和SDA的信号来达到实验的目的。
下面是三星官方的IIC0 Interface原理图,在此贴出来给大家一个参考。

2.1 实验的具体思路,完成向eeprom写入数据,读出数据。
思路如下:

2.2试验中相关函数分析:
a、首先是i2c_init()完成gpio,i2c频率和slaveaddr的初始化。
void i2c_init()
{
u32 uSelClkSrc;
u32 uClkValue;
u32 ufreq=400000;
//UART_Printf("\n*** IIC0 Setting Frequency: %d Hz\n",ufreq);
INTC_SetVectAddr(NUM_IIC,Isr_myIIC);
INTC_Enable(NUM_IIC);
GPIO_SetFunctionEach(eGPIO_B,eGPIO_5,2);
GPIO_SetFunctionEach(eGPIO_B,eGPIO_6,2);
GPIO_SetPullUpDownEach(eGPIO_B,eGPIO_5,2);
GPIO_SetPullUpDownEach(eGPIO_B,eGPIO_6,2);
if ((((g_PCLK>>4)/ufreq)-1)>0xf)
{
uSelClkSrc = 1;
uClkValue = ((g_PCLK>>9)/ufreq) -1; // PCLK/512/freq
UART_Printf("*** PCLK= %.2fMHz, SelClkSrc= %d (IICCLK=PCLK/512) ,ClkDivideValue= %d\n",(float)g_PCLK/1.0e6,uSelClkSrc,uClkValue);
UART_Printf("*** IICCLK= %d Hz, IICSCL (Tx clock)= %d Hz\n",(g_PCLK/512),((g_PCLK/512)/(uClkValue+1)));
}
else
{
uSelClkSrc = 0;
uClkValue = ((g_PCLK>>4)/ufreq) -1; // PCLK/16/freq
UART_Printf("*** PCLK= %.2fMHz, SelClkSrc= %d (IICCLK=PCLK/16) ,ClkDivideValue= %d\n",(float)g_PCLK/1.0e6,uSelClkSrc,uClkValue);
UART_Printf("*** IICCLK= %d Hz, IICSCL (Tx clock)= %d Hz\n",(g_PCLK/16),((g_PCLK/16)/(uClkValue+1)));
}
//Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
Outp32(rIICCON0,(uSelClkSrc<<6) | (1<<5) | (uClkValue&0xf));
Outp32(rIICADD0,0xc0); // Slave address = [7:1]
Outp32(rIICSTAT0,0x10); // IIC bus data output enable(Rx/Tx)
Outp32(rIICLC0,0x4); // SDA Filter Enable,delayed 0clks
}b、我们在这里使用中断来完成i2c数据的传输工作,所以下面我们要看看中断函数。
void __irq Isr_myIIC( void)
{
unsigned int iicSt,i;
u32 uTemp0 = 0;
u8 cCnt;
g_cIIC_STAT0 = Inp32(rIICSTAT0);
UART_Printf("\r\n##### i2c_int #####\r\n");
switch (mask)
{
case MasterRX:
if (g_uIIC_PT>0)
g_PcIIC_BUFFER[g_uIIC_PT-1] = Inp32(rIICDS0);
UART_Printf("*** MasterRX is %x\n", g_PcIIC_BUFFER[g_uIIC_PT-1]);
g_uIIC_PT++;
if (g_uIIC_PT==g_uIIC_DATALEN)
{
uTemp0 = Inp32(rIICCON0);
uTemp0 |= (1<<7); // Enable Ack generation
Outp32(rIICCON0,uTemp0); //
}
else if (g_uIIC_PT > g_uIIC_DATALEN)
{
// Added by SOP on 04/11/2008 -----
uTemp0 = Inp32(rIICCON0);
uTemp0 &= ~(1<<7); // Disable Ack generation
Outp32(rIICCON0,uTemp0); //
//----------------------------------
Outp32(rIICSTAT0,0x90); // Stop Master Rx condition
}
uTemp0 = Inp32(rIICCON0);
uTemp0 &= ~(1<<4); // Clear pending bit to resume
Outp32(rIICCON0,uTemp0);
Delay(100);
break;
case MasterTX:
if (g_uIIC_PT<g_uIIC_DATALEN)
{
Outp32(rIICDS0,g_PcIIC_BUFFER[g_uIIC_PT]);
UART_Printf("*** MasterTX is %x\n", g_PcIIC_BUFFER[g_uIIC_PT]);
}
else
{
// Added by SOP on 04/11/2008 -----
uTemp0 = Inp32(rIICCON0);
uTemp0 &= ~(1<<7);
uTemp0 &= ~(1<<4); // Disable Ack generation
Outp32(rIICCON0,uTemp0); //
//----------------------------------
Outp32(rIICSTAT0,0xd0); // Stop Master Tx condition, ACK flag clear
g_uIIC_PT++; // Added For Test by SOP on 2008/05/27
Delay(1000);
break;
}
g_uIIC_PT++;
uTemp0 = Inp32(rIICCON0);
uTemp0 &= ~(1<<4); // Clear pending bit to resume
Outp32(rIICCON0,uTemp0);
Delay(100); // wait until Stop Condition is in effect, Need to here Delay(1)
//UART_Printf("*** Ended IIC ISR MasterTX (rIICCON0 =>0x28 or a8): 0x%02x\n", uTemp0); // For Debugging
// Outp32(rIICSTAT0,0xf0); // Master Tx Start.
break;
default:
break;
}
g_cIIC_STAT0 &=0xf;
INTC_ClearVectAddr();
}
c、接下来便是读写数据
/*
* 主机发送
* slvAddr : 从机地址,buf : 数据存放的缓冲区,len : 数据长度
*/
void i2c_write(volatile unsigned int slvAddr, unsigned char *buf,volatile int len)
{
u32 uTmp1;
g_uIIC_PT=0;
g_uIIC_DATALEN=len;
g_PcIIC_BUFFER=buf;
mask=MasterTX;
uTmp1 = Inp32(rIICSTAT0);
while((uTmp1&(1<<5)) || (uTmp1&(1<<3))) // Wait until IIC bus is free or Arbitration successful.
{
uTmp1 = Inp32(rIICSTAT0);
}
/* 等待直至数据传输完毕 */
uTmp1 = Inp32(rIICCON0);
uTmp1 |= (1<<7); // ACK Enable
Outp32(rIICCON0,uTmp1); // Ack generation Enable
Outp32(rIICDS0,slvAddr);
Outp32(rIICSTAT0,0xf0);
// while (g_tS3C24xx_I2C.DataCount != -1);
while(g_uIIC_PT<=g_uIIC_DATALEN);
}到此I2c功能基本实现。
参考代码:三星官方提供的6410_Test裸机工程项目。
本文介绍了OK6410进行I2C实验的详细过程,包括I2C总线的硬件特性、传输时序和信号状态。由于开发板缺少内置EEPROM,实验通过示波器检测外接IO的SCL和SDA信号。实验思路涉及初始化设置、中断函数和读写数据操作,参考了三星官方的6410_Test项目。
1073

被折叠的 条评论
为什么被折叠?



