6. S5PC100下的I2C控制器介绍
S5PC100处理器支持多主机I2C串行总线接口,并且它支持主机发送模式、主机接收模式、从机发送模式和从机接收模式4种模式,图4所示为I2C总线的概括图。

图4 I2C总线的概括图
7. I2C总线控制寄存器详解
表1为I2C总线控制寄存器描述。
表1 I2C总线控制寄存器
| I2CCON | 位 | 描 述 | 复 位 值 |
| 应答产生 | [7] | IIC应答产生使能位 0 = 禁止 1 = 使能 |
0 |
| Tx时钟源选择 | [6] | IIC传输时钟预分值选择位 0 = I2CCLK = fPCLK /16 1= I2CCLK = fPCLK /512 |
0 |
| Tx/Rx中断 | [5] | I C-Bus Tx/Rx 中断控制位 0 = 禁止 1 = 使能 |
0 |
| 传输时钟值 | [3:0] | IIC总线时钟预分值 Tx clock = I2CCLK/(I2CCON[3:0]+1) |
未定义 |
表2为I2C状态寄存器描述。
表2 I2C状态寄存器
| I2CSTAT | 位 | 描 述 | 复 位 值 |
| 模式选择 | [7:6] | IIC总线主/从Tx/Rx模式选择位 00=从机接收模式 01=从机发送模式 10=主机接收模式 11=主机发送模式 |
00 |
| 忙信号状态位 | [5] | IIC 总线忙信号状态位 读:0=准备 &nbsnbsp; 1=忙 写:产生开启信号 |
0 |
| 串行输出 | [4] | IIC总线数据输出使能/禁止位 0=禁止Rx/Tx 1=使能Rx/Tx |
0 |
| Ar位定量状态标志 | [3] | 0=定量成功 1=失效 |
0 |
| 从地址状态标志 | [2] | 0=当开启/停止条件侦测到时清除 1=接收到的从地址匹配I2CADD的地址值 |
0 |
| 地址0状态标志 | [1] | 0=当开启/停止条件侦测到时清除 1=接收从地址值为00000000b |
0 |
| 后的接收位状态标志 | [0] | 0=为0 1=为1 |
0 |
表3为I2C数据发送/接收移位寄存器描述。
表3 I2C数据发送/接收移位寄存器
| I2CDS | 位 | 描 述 | 复 位 值 |
| 保留位 | [31:8] | 保留位,没有使用 | 未定义 |
| 数据移位 | [7:0] | 8位数据移位寄存器 如果串行输出使能,则I2CDS将变为可写。并且 I2CDS任何时刻都是可读的,不管当前I2CSTAT的设置 |
未定义 |
8. 电路原理分析
结合上面已经提到的I2C理论基础,将以一个例子来进行实际讲解,用I2C来操作LM75温度传感器。
图5所示为LM75的原理图。

图5 LM75原理图
可以看到SDA/SCL被接到了S5PC100的IIC控制器上,并且接了一个外部中断,该中断可作为从机应答信号。
下面简单介绍一下LM75的操作时序,其操作时序的第一部分如图6所示。

图6 LM75操作时序第一部分
如图6所示显示了LM75操作时序的第一阶段,可以看到,如果要获取数据,需要先配置一下模式,并且LM75的从机地址为0x90,发送地址后要做的就是配置工作模式,LM75芯片提供了以下4种模式。
(1)温度(只读模式)。
(2)配置(读/写)。
(3)T(HYST读/写)。
(4)T(OS读/写)。
这里选择第一个即可,也就是发送0x0,接着有如图7所示的时序。

图7 时序第二部分
接下来再次发送从机地址,选择LM75芯片后,即可等待芯片回送数据,这时芯片会发送给主机端两次数据,第一次是主要值,第二次是小数部分,小能精确到0.5。要注意的是每一次都要进行应答,才能保证数据的有效性。
9. 代码实现
1.寄存器定义
/*IIC寄存器结构体定义*/
/*
*I2C0 REGISTERS
*/
typedef struct {
unsigned int I2CCON0 ;
unsigned int I2CSTAT0 ;
unsigned int I2CADD0 ;
unsigned int I2CDS0 ;
unsigned int I2CLC0 ;
}i2c0;
#define I2C0 (* (volatile i2c0 *)0xEC100000 )
/*设置GPIO*/
void cfg_gpio(void)
{
GPD.GPDCON=(GPD.GPDCON&(~((0X0f<<12)|(0x0f<<16))))+((2<<12) | (2<<16)) ;
}
/*写入LM75要读取的地址,然后读出2字节的温度数据*/
int set_pointer_and_read_2byte(int mode)
{
I2C0.I2CDS0 = 0x90; /*LM75 SLAVE ADDRESS 第0位为0 代表接下来是要写入数据*/
I2C0.I2CCON0 = 0xe0; /*ENABLE ACK BIT, PRESCALER:512 ,RX/TX INTERRUPT ENABLE ,*/
I2C0.I2CSTAT0 =0xf0; /*Master Trans mode ,START ,ENABLE RX/TX ,*/
while(!(I2C0.I2CCON0&(1<<4))); /*The end of the waiting to be sent */
I2C0.I2CDS0 = mode; // READ TEMPERATURE ONLY
I2C0.I2CCON0 &= ~(1<<4); /* Clear pending condition & Resume the operation */
while(!(I2C0.I2CCON0&(1<<4))); /*The end of the waiting to be sent */
// 以上是主机发送一个从机地址和一个从机的命令
I2C0.I2CDS0 = 0x91; /*Again to send LM75 salve address 第0位为1 代表接下来是要读出数据*/
I2C0.I2CSTAT0 =0xb0; /*Master receive mode ,START ,ENABLE RX/TX ,*/
I2C0.I2CCON0 &= ~(1<<4); /* Clear pending condition & Resume the operation */
while(!(I2C0.I2CCON0&(1<<4))); /*The end of the waiting to be sent */
I2C0.I2CCON0 &= ~(1<<4); /* Clear pending condition & Resume the operation */
while(!(I2C0.I2CCON0&(1<<4))); /*The end of the waiting to read */
high = I2C0.I2CDS0; /*read temperature of low 8 bit */
I2C0.I2CCON0 &= ~((1<<7)|(1<<4));
/* Clear pending condition & Resume the operation & no ack*/
while(!(I2C0.I2CCON0&(1<<4))); /*The end of the waiting to read */
low = I2C0.I2CDS0; /*read temperature of low 2 bit */
I2C0.I2CSTAT0 &= ~(1<<5); /*STOP signal generation,free bus */
I2C0.I2CCON0 &= ~(1<<4); /*clean interrup pending bit */
return ((high << 8) | low);
}
int main()
{
volatile int delay;
int low, high, temp, config, i;
uart0_init();
cfg_gpio();
/*循环打印采集的数据*/
while (1){
read_data_one(); // 配置模式
temp = read_data_two(); // 开始连续两次读数据
high = temp >> 8;
low = temp & 0xff;
printf("TEMP is : %d.%d\n", high, (((low>>7)==0) ? 0 : 5));
}
return 0;
}
2.实验调试过程与结果
编译生成的.elf文件,连接硬件。并连接好FS_JTAG仿真器套件。将程序编译后获得.elf文件,将该文件通过仿真器下载并运行在目标板上,终端打印信息如图8所示。
TEMP is :22.5
TEMP is :22.5
TEMP is :23.0
TEMP is :23.0
TEMP is :23.0
TEMP is :23.5
TEMP is :23.5
TEMP is :23.5
TEMP is :23.5
TEMP is :23.5
TEMP is :23.5