S3C2440 I2C实现

发布者:PeacefulSoul最新更新时间:2016-12-31 来源: eefocus关键字: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:显示结果



关键字:S3C2440  I2C 引用地址:S3C2440 I2C实现

上一篇:ARM中断区别-LPC2142与S3C2440的区别
下一篇:S3C2440FCLK、HCLK、PCLK的配置

推荐阅读最新更新时间:2024-03-16 15:28

基于MSP430F5系列的硬件I2C的使用分享
0.前言 对于大多数单片机来说,I2C成了一个老大难问题。从51时代开始,软件模拟I2C成了主流,甚至到ARMCortex M3大行其道的今天,软件模拟I2C依然是使用最广的方法。虽然软件模拟可以解决所有的问题,但是总感觉没有充分发挥MCU内部的硬件资源。查阅了所有关于MSP430F5系列的图书,没有关于硬件I2C的应用代码,自己通过调试摸索,把经验总结之后和大家分享,希望大家喜欢。同时,I2C的使用可以分为等待法和中断法,从理解的角度来说等待法思路清晰易于上手,从功耗的角度出发,中断法可以灵活的进入低功耗模式,但是不易理解。本文先从等待法入手。 MSP430F5系列的硬件I2C使用大致会有以下问题: 【I2C地址设定】一般情
[单片机]
基于MSP430F5系列的硬件<font color='red'>I2C</font>的使用分享
ARM-Linux s3c2440 之UART分析(五)
从上面四篇介绍文章中,已经清楚了串口设备与串口驱动实现的各层次关系流程。是一种从上而下的关系,从第二篇的层次流程图中可以看出。之前说过串口设备是一种platform device,下面看看串口作为platform device的实现细节。 串口的硬件平台实现smdk2440_map_io()初始化入口: static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iodesc,ARRAY_SIZE(smdk2440_iodesc)); s3c24xx_init_clocks(12000000); s3c24xx_
[单片机]
使用J-Link烧写一U-boot的烧写+裸板程序烧写(JZ2440-S3C2440)
一、使用J-Link 烧写NOR Flash 注意:J-Link 只支持NOR Flash,不支持NAND Flash。 1、安装J-link 驱动(在Windows 下) 在JZ2440 开发板JLINK 使用手册(JZ2440开发板JLINK使用手册jlink安装驱动程序目录)中,驱动名为:Setup_JLinkARM_V436e.exe。 双击即可进行安装,安装完成后,桌面上显示两个图标J-Flash和J-Link: 2、使用JLINK 烧写Uboot 到NOR Flash (1)开发板设置为NOR (将NAND/NOR 开关打到NOR一侧)启动,接好J-Link 后,最后启动上电。 (2)启动上电。打开J-Flas
[单片机]
使用J-Link烧写一U-boot的烧写+裸板程序烧写(JZ2440-S3C2440)
s3c2440(2410) USB HOST不稳定的原因及解决方法
今天tpu拿出一块2440板子调试,发现尽管采取了种种措施,USBHOST总是会偶尔不工作.把UCLK通过CLKOUT0引出,用示波器查看,发现不工作的时候,UCLK根本就没有稳定下来.于是仔细思考,影响USB的有这几个地方: 外部晶振16.9344Mhz LOCKTIME寄存器的UPLL LOCKTIME UPLLCON CLKSLOW寄存器的UPLL开关 接下来逐个排除: 晶振是MPLL和UPLL公用,从来没听说过MPLL不稳定的. 怀疑LOCKTIME太大(0xffff),但改小了没有效果. 在UCLK不稳定的时候,重复设置UPLLCON是没有用的. 在UCLK不稳定的时候,开关UPLL,有效果!在UCLK
[单片机]
C51---12 AT24C02 (I2C总线)
存储器介绍 存储器简化模型 AT24C02 引脚以及电路 内部结构框图 I2C总线❗ I2C总线介绍 I2C电路规范 I2C时序❗ I2C数据帧❗ AT24C02数据帧❗ AT24C02数据存储 功能 按键1 使数字+1 按键2 使数字-1 按键3 将数字写入AT24C02 按键4 读出AT24C02刚刚写入的数据 代码 main.c #include REGX52.H #include LCD1602.h #include Key.h #include AT24C02.h #include Delay.h unsigned char KeyNum; unsign
[单片机]
C51---12 AT24C02 (<font color='red'>I2C</font>总线)
S3C2440 触摸屏touch screen驱动程序(十七)
1、先来回忆之前第12节分析的输入子系统(请点击这里) 其中输入子系统层次如下图所示: 其中事件处理层的函数是通过input_register_handler()函数注册到input_handler_list链表中 搜索input_register_handler注册函数,就可以看到都是事件处理层里的函数: 所以最终如下图所示: 右边的驱动事件处理,内核是已经写好了的,所以我们的触摸屏只需要写具体的驱动设备,然后内核会与触摸屏驱动tsdev.c自动连接。 2、本节需要用到的结构体成员如下: struct input_dev { void *private; const char *
[单片机]
<font color='red'>S3C2440</font> 触摸屏touch screen驱动程序(十七)
I2C读写心得(AT24C02篇)
困扰我几的程序终于搞定了,前几天我对AT24C02一直读不准确,找了N长时间的程序都没有头绪,后来在板哥的指点下,一下子明白了,原因很简单,我在AT24C02_read()最后没有加延时, 主要还是对时序没有控制好呀,用板哥的一句话是我们对器件的了解还不很熟,我现在也感到,一定要先了解了器件的特性,我们才能游刃有余把握住每一个容易疏忽的细节,在这里,板哥确实教会了我好多东西,在我刚学单片机时,他就对我说时序很重要,现在终于是看到了. 好了不罗嗦了,最后得出一点,最好在每个读写结束时加个延时,如果对时间要求不是很重要的话,加的长一点无所谓,如果要求比较高的话,那先加长延时,然后慢慢的减. #include reg51.h #i
[单片机]
NiosII的I2C控制IP及其在成像系统中的应用
  IP的硬件结构及寄存器   1.1 IP硬件结构   IP内部结构如图1所示。主要由波特率时钟寄存器、寄存器组控制器、并行I/O接口、I2C可编程接口、I2C接口引擎5个模块组成。   波特率时钟产生器用来产生I2C IP工作的基本时钟频率;寄存器组控制器用来对寄存器进行设置,设置数据通过并行I/O接口传送到该模块中;并行I/O接口模块用来处理可编程接口模块传送过来的命令;I2C可编程接口模块用来设置IP各个寄存器的地址;I2C接口引擎模块执行I2C总线上数据的传输。   1.2  寄存器结构   I2C控制IP主要由6个寄存器构成,如表1所列。通过对寄存器的读写可以方便地控制I2C总线数据的传输,从而
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved