S3C2440 I2C实现


1:I2C原理

总线的构成及信号类型 I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。CPU发出的控制信号分为地址码和控制量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量决定该调整的类别(如对比度、亮度等)及需要调整的量。这样,各控制电路虽然挂在同一条总线上,却彼此独立,互不相关。 I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。应答信号:接收数据的从控器在接收到8bit数据后,向发送数据的主控器发出特定的低电平脉冲,表示已收到数据。CPU向从控器发出一个信号后,等待从控器发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,判断为受控单元出现故障。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

2:I2C实验代码

/*
---------------------------------------------------------------
文件名称:I2C.c
说    明:I2C协议 读写AT24C08
作    者:温子祺
创建时间:2010-08-17
测试结果:[OK]
注意事项:

(1)24C02数据速率I2C总线的数据传送速率在标准工作方式下为100kbit/s,
   在快速方式下,最高传送速率可达400kbit/s。
(2)当前S3C2440各频率如下:FCLK 405MHz
                         HCLK 135MHz
                         PCLK 67.5MHz
(3)当前I2C协议在三星提供的源代码进行修改,并提升代码的容错能力
   如I2C进行读写时,都有进行超时处理。
---------------------------------------------------------------
*/
#include "S3C244x.h"
#include "Global.h"
#include "IIC.h"
/*
1:rIICON                  IIC总线控制寄存器
2:rIICSTAT                IIC总线控制状态寄存器
3:rIICADD                 IIC总线地址寄存器
4:rIICDS                   IIC总线发送接收数据移位寄存器
5:rIICLC                  IIC总线多主设备线路控制寄存器
*/

/*
====================================================

I2C基本函数接口

====================================================
*/
static volatile UINT8  g_ucI2CDataBuf[256];           //I2C发送数据缓冲区
static volatile UINT32 g_unI2CCurDataCount;           //I2C当前数据计数
static volatile UINT32 g_unI2CCurStatus;           //I2C当前状态
static volatile UINT32 g_unI2CCurDataOffset;       //I2C当前发送数据偏移量
static          UINT32 g_unI2CCurMode;               //I2C当前模式
static          UINT32 g_unIICCONSave;               //临时保存rIICCON寄存器值

static void __irq I2CISR(void)    ;                   //I2C中断服务函数

static BOOL  I2CWriteByte(UINT32 unSlaveAddress,UINT32 ucWriteAddress,UINT8 *pucWriteByte);
static BOOL  I2CReadByte (UINT32 unSlaveAddress,UINT32 ucReadAddress ,UINT8 *pucReadByte);

/******************************************************
*文件名称:I2CWriteByte
*输    入:unSlaveAddress 从机地址
          unWriteAddress 写地址
          pucWriteByte   写字节
*输    出:TRUE/FALSE
*功能说明:I2C 写单个字节
*注意事项:
主机发送起始信号后,发送一个寻址字节,收到应答后紧跟着的就是数据传输,
数据传输一般由主机产生的停止位终止。但是,如果主机仍希望在总线上通讯,
它可以产生重复起始信号和寻址另一个从机,而不是首先产生一个停止信号。
在这种传输中,可能有不同的读/写格式。
*******************************************************/
static BOOL I2CWriteByte(UINT32 unSlaveAddress,
                         UINT32 unWriteAddress,
                         UINT8 *pucWriteByte)
{
    BOOL    bRt=TRUE;
    UINT32  unTimeouts;

g_unI2CCurMode      = WRDATA;                      //当前I2C模式:写
    g_unI2CCurDataOffset= 0;                          //I2C数据缓冲区偏移量为0
    g_ucI2CDataBuf[0]   = (UINT8)unWriteAddress;      //写地址
    g_ucI2CDataBuf[1]   = *pucWriteByte;              //写数据
    g_unI2CCurDataCount = 2;                          //当前数据计数值(即地址+数据=2字节)
   
    rIICDS   = unSlaveAddress;                        //0xa0(高四位默认是1010,低四位为xxxx)
    rIICSTAT = 0xf0;                                  //主机发送启动
 
    unTimeouts=1000;

while(g_unI2CCurDataCount!=-1 && unTimeouts--)
    {
          DelayNus(1);
    }

if(!unTimeouts)
    {
       bRt=FALSE;

goto end;
    }

g_unI2CCurMode = POLLACK;

while(1)
    {
        rIICDS           = unSlaveAddress;
        g_unI2CCurStatus = 0x100;
        rIICSTAT         = 0xf0;              //主机发送启动
          
        rIICCON=g_unIICCONSave;                  //恢复I2C运行

unTimeouts=1000;

while(g_unI2CCurStatus==0x100 && unTimeouts--)
        {
              DelayNus(1);
        }

if(!unTimeouts)
        {
            bRt=FALSE;

goto end;
        }

if(!(g_unI2CCurStatus&0x1))
        {
             break;                           //接收到应答(ACK)信号
        }
           
    }

end:
    rIICSTAT = 0xd0;                         //停止主机发送状态Stop MasTx condition
    rIICCON  = g_unIICCONSave;               //恢复I2C运行
    DelayNus(10);                            //等待直到停止条件是有效的

return bRt;
}

/******************************************************
*文件名称:I2CReadByte
*输    入:unSlaveAddress 从机地址
          unReadAddress  读地址
          pucReadByte    读字节
*输    出:TRUE/FALSE
*功能说明:I2C 读单个字节
*注意事项:
  主机发送完寻址字节后,主机立即读取从机中的数据。
  当寻址字节的"R/W"位为1时,在从机产生应答信号后,
  主机发送器变成主机接收器,从机接收器变成从机发送器。
  之后,数据由从机发送,主机接收,每个应答由主机产生,
  时钟信号CLK仍由主机产生。若主机要终止本次传输,则发送
  一个非应答信号,接着主机产生停止信号
*******************************************************/
static BOOL I2CReadByte(UINT32 unSlaveAddress,
                        UINT32 unReadAddress,
                        UINT8 *pucReadByte)
{
    BOOL   bRt=TRUE;
    UINT32 unTimeouts;

g_unI2CCurMode      = SETRDADDR;
    g_unI2CCurDataOffset= 0;
    g_ucI2CDataBuf[0]   = (UINT8)unReadAddress;
    g_unI2CCurDataCount = 1;

rIICDS   = unSlaveAddress;
    rIICSTAT = 0xf0;                               //主机发送启动

unTimeouts=1000;

while(g_unI2CCurDataCount!=-1 && unTimeouts--)
    {
          DelayNus(1);
    }

if(!unTimeouts)
    {
       bRt=FALSE;

goto end;
    }

g_unI2CCurMode              = RDDATA;
    g_unI2CCurDataOffset        = 0;
    g_unI2CCurDataCount         = 1;
   
    rIICDS        = unSlaveAddress;
    rIICSTAT      = 0xb0;                         //主机接收启动
    rIICCON       = g_unIICCONSave;               //恢复I2C运行
     
    unTimeouts=1000;

while(g_unI2CCurDataCount!=-1 && unTimeouts--)
    {
          DelayNus(1);
    }

if(!unTimeouts)
    {
       bRt=FALSE;

goto end;
    }

*pucReadByte= g_ucI2CDataBuf[1];

end:

return bRt;
}

/******************************************************
*文件名称:I2CWriteNBytes
*输    入:unSlaveAddress 从机地址
          unWriteAddress 写地址
          pucWriteByte   写字节
          unNumOfBytes   写字节数
*输    出:TRUE/FALSE
*功能说明:I2C 写多个字节
*******************************************************/
BOOL I2CWriteNBytes(UINT32 unSlaveAddress,
                    UINT32 unWriteAddress,
                    UINT8 *pucWriteBytes,
                    UINT32 unNumOfBytes)
{
     UINT32 unSpareOfBytes=unNumOfBytes;

while(unSpareOfBytes--)
     {
            if(!I2CWriteByte( unSlaveAddress,
                             unWriteAddress,
                             pucWriteBytes))
           {
          
                  I2CMSG("I2C[ERROR]:fail to write data fail at address %d /
                                  success to write %d bytes /r/n",
                                  unWriteAddress,(unNumOfBytes-unSpareOfBytes));

return  FALSE;

}

unWriteAddress++;
           pucWriteBytes++;

}

return TRUE;
}
/******************************************************
*文件名称:I2CReadNBytes
*输    入:unSlaveAddress 从机地址
          unReadAddress  读地址
          unNumOfBytes  
*输    出:TRUE/FALSE
*功能说明:I2C 读多个字节
*******************************************************/
BOOL I2CReadNBytes(UINT32 unSlaveAddress,
                   UINT32 unReadAddress,
                   UINT8 *pucReadByte,
                   UINT32 unNumOfBytes)

{
     UINT32 unSpareOfBytes=unNumOfBytes;

while(unSpareOfBytes--)
     {
            if(!I2CReadByte(  unSlaveAddress,
                             unReadAddress,
                             pucReadByte))
           {
          
                  I2CMSG("I2C[ERROR]:fail to read data fail at address %d /
                                  success to read %d bytes /r/n",
                                  unReadAddress,(unNumOfBytes-unSpareOfBytes));

return  FALSE;

}

unReadAddress++;
           pucReadByte++;

}

return TRUE;
}
/*
====================================================

中断服务函数

====================================================
*/
/******************************************************
*文件名称:I2CISR
*输    入:无  
*输    出:无
*功能说明:I2C 中断服务函数
*******************************************************/
void __irq I2CISR(void)
{
    UINT32 unI2CStatus;

unI2CStatus   = rIICSTAT;
   
    if(unI2CStatus & 0x8){}           //When bus arbitration is failed.
    if(unI2CStatus & 0x4){}           //When a slave address is matched with IICADD
    if(unI2CStatus & 0x2){}           //When a slave address is 0000000b
    if(unI2CStatus & 0x1){}           //When ACK isn't received

switch(g_unI2CCurMode)
    {
       case POLLACK:
            g_unI2CCurStatus = unI2CStatus;
            break;

case RDDATA:

if((g_unI2CCurDataCount--)==0)
           {
               g_ucI2CDataBuf[g_unI2CCurDataOffset++] = rIICDS;
           
               rIICSTAT = 0x90;                                 //停止I2C接收状态
               rIICCON  = g_unIICCONSave;                       //恢复I2C运行
               DelayNus(1);                                     //等待直到停止条件是有效的
                                                          
                                                                //The pending bit will not be set after issuing stop condition.
               break;   
           }     
           g_ucI2CDataBuf[g_unI2CCurDataOffset++] = rIICDS;     //The last data has to be read with no ack.

if((g_unI2CCurDataCount)==0)
               rIICCON = 0x2f;                                  //Resumes IIC operation with NOACK. 
           else
               rIICCON = g_unIICCONSave;                        //Resumes IIC operation with ACK
               break;

case WRDATA:

rIICDS = g_ucI2CDataBuf[g_unI2CCurDataOffset++];    //g_ucI2CDataBuf[0] has dummy.
            DelayNus(10);                                       //for setup time until rising edge of IICSCL
             
            rIICCON = g_unIICCONSave;                           //恢复I2C运行

if((g_unI2CCurDataCount--)==0)
            {
                rIICSTAT = 0xd0;                                //Stop MasTx condition
                rIICCON  = g_unIICCONSave;                      //恢复I2C运行
                DelayNus(10);                                   //Wait until stop condtion is in effect.
                                                                //The pending bit will not be set after issuing stop condition.
            }

break;

case SETRDADDR:

if((g_unI2CCurDataCount--)==0)
            {
                break;
            }
                                                                //IIC operation is stopped because of IICCON[4]   
            rIICDS = g_ucI2CDataBuf[g_unI2CCurDataOffset++];
            DelayNus(10);                                       //For setup time until rising edge of IICSCL
            rIICCON = g_unIICCONSave;                           //恢复I2C运行
            break;

default:
            break;     
    }

rSRCPND = BIT_IIC;                                         //Clear pending bit
    rINTPND = BIT_IIC;
}
/*
====================================================

测试代码

====================================================
*/
/******************************************************
*文件名称:I2CTest
*输    入:无  
*输    出:无
*功能说明:I2C 测试代码
*******************************************************/
void I2CTest(void)
{
    UINT32 i;
    UINT8  buf[256];

I2CMSG("/nIIC Test(Interrupt) using AT24C02/n");

rGPEUP  |= 0xc000;                  //Pull-up disable
    rGPECON |= 0xa00000;                //GPE15:IICSDA , GPE14:IICSCL
    rCLKCON    |= 1<<16;
    pISR_IIC = (UINT32)I2CISR;
    rINTMSK &= ~(BIT_IIC);

/*
   IIC时序太重要了,要认真设置好发送时钟和接收数据时钟
   当前PCLK = 405/6 = 67.5MHz

IICCLK=67.5/16= 4.22MHz

Tx Clock = 4.22/11=0.384MHz
   
*/

g_unIICCONSave=rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xa);

rIICADD  = 0x10;                    //S3C2440 从机地址设置
    rIICSTAT = 0x10;                    //I2C总线数据输出使能(Rx/Tx)
    rIICLC   =(1<<2)|(1);                  //滤波器使能,SDA数据延时输出
   
    I2CMSG("Write test data into AT24C02/n");

for(i=0;i<256;i++)
    {
        buf[i]=i;
    }

I2CWriteNBytes(0xA0,0,buf,256);
          
    for(i=0;i<256;i++)
        buf[i] = 0;

I2CMSG("Read test data from AT24C02/n");

I2CReadNBytes(0xA0,0,buf,256);

I2CMSG("Read Data Finish/r/n");

for(i=0;i<256;i++)
    {
        I2CMSG("%d ",buf[i]);

}

rINTMSK |= BIT_IIC;

}

3:显示结果


转自:http://www.cnblogs.com/wenziqi/archive/2010/09/03/1817217.html

S3C2440 I2C实现相关推荐

  1. s3c2440 I2C协议

    I2C总线:i2c控制器与设备之间用i2c总线连接,i2c总线有两条,一根是SLC,串行时钟线,不停的发送时钟.另一根是SDA,串行数据线,用来传输数据的.一条I2C总线上可以连接多个设备,是一主多从 ...

  2. S3C2440 I2C总线控制

    概述:话不多说,直接上图 多主机IIC总线控制(IICCON): IIC控制总线状态(IICSTAT): IIC总线地址(IICADD): IIC发送,接收总线寄存器(IICDS) IIC总线控制寄存 ...

  3. Linux的I2C 设备驱动 -- mini2440 上i2c接口触摸屏驱动

    本篇记录在友善之臂 mini2440 平台上挂载I2C接口触摸屏的驱动开发过程. 内核版本linux-2.6.32.2, 平台是ARM9 S3C2440+I2C接口的触摸屏 如上篇 Linux的I2C ...

  4. Linux 设备驱动篇之I2c设备驱动

    ******************************************************************************************** 装载声明:希望 ...

  5. UBOOT I2C读写详解(基于mini2440)

    mini2440 UBOOT I2C支持总结 1. mini2440开发板I2C连接的设备 SDA/SCL对应的引脚:   2. AT24C08地址 查看AT24C08芯片手册 ADDRESS数据段为 ...

  6. Linux设备驱动篇——[I2C设备驱动-1]

    Linux 设备驱动篇之I2c设备驱动 fulinux 一.I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设 ...

  7. Linux设备驱动程序架构分析之I2C架构(基于3.10.1内核)

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 内核版本:3.10.1 I2C体系架构的硬件实体包括两部分: 硬件I2C Adapter:硬件I2C Adapter ...

  8. linux驱动--i2c驱动学习

    转至:http://blog.csdn.net/ghostyu/article/details/8094049 预备知识 在阅读本文最好先熟悉一种i2c设备的驱动程序,并且浏览一下i2c-core.c ...

  9. Linux设备驱动 IIC驱动

    Linux 设备驱动篇之I2c设备驱动 fulinux 一.I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设 ...

最新文章

  1. windows程序设计.第一个windos程序
  2. 三.rocketmq-console
  3. Pycharm快捷键设置(鼠标滚动控制字体大小)
  4. librtmp 源码分析笔记 ReadN
  5. 【数据库课程设计】企业库存管理系统
  6. 零基础用阿里云服务器搭建网站的步骤
  7. npm-Babel转码器
  8. 电脑报错 :file:\boot\bcd 0xc000014c
  9. 国产 Linux 操作系统面临的困境
  10. ODM 对象文档映射
  11. matlab计算wsn覆盖率,WSN覆盖率求解
  12. SAP 中Table的使用(一、显示数据)
  13. MYSQL学习思维导图
  14. 基于LMS自适应滤波器的QPSK信号均衡器matlab仿真
  15. 【我参加NVIDIA Sky Hackathon】感悟篇
  16. mac自带计算器 进制转换
  17. 软件黑盒测试心得与经验
  18. 百公里时速不掉线 芯讯通为商用车驾驶安全保驾护航
  19. 透过率和反射率的关系_玻璃透过率、反射率和吸收率的关系.doc
  20. 电机磁电热多场耦合 matlab,Motor-CAD 基于多物理场的快速电机设计专家_其他专业仿真_工业仿真_产品体系_安世亚太...

热门文章

  1. 【公众号】公众号网页跳转关注微信公众号
  2. h5页面的认识与制作
  3. 三个步骤教你如何通过天猫精灵控制智汀,实现不同生态设备相互联动
  4. 5 打印选课学生名单 (25分)
  5. java对台湾同胞身份证号码验证
  6. python resultful APi
  7. 什么力量推动了互联网的进化
  8. 高级篇之使用ENC编码器实现USBCam摄像头竖屏直播的方法
  9. 安装ros系统出现 404 Not Found [IP: 91.189.91.38 80]
  10. php微信短网址生成,如何把微信文章网址长连接(长网址)转换为短连接(短网址)...