S3C2440 I2C实现

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值