当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > 2C 原理及应用(下)
2C 原理及应用(下)
时间:2016-12-14作者:华清远见

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

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)