S3C2440 I2C Implementation

Publisher:PeacefulSoulLatest update time:2016-12-31 Source: eefocusKeywords:S3C2440  I2C Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

/*****************************************************

 * Description: S3C2440 I2C implementation

 *****************************************************/


1:I2C Principle

    The bus structure and signal type The I2C bus is a serial bus composed of data line SDA and clock SCL, which can send and receive data. Bidirectional transmission is carried out between the CPU and the controlled IC, and between ICs, with a maximum transmission rate of 100kbps. Various controlled circuits are connected in parallel on this bus, but just like a telephone, they can only work when their respective numbers are dialed, so each circuit and module has a unique address. In the process of information transmission, each module circuit connected in parallel on the I2C bus is both a master controller (or a controlled device) and a transmitter (or a receiver), depending on the function it is to complete. The control signal sent by the CPU is divided into two parts: the address code and the control amount. The address code is used to select the address, that is, to connect the circuit to be controlled and determine the type of control; the control amount determines the type of adjustment (such as contrast, brightness, etc.) and the amount to be adjusted. In this way, although each control circuit is hung on the same bus, it is independent of each other and unrelated. There are three types of signals in the I2C bus during data transmission, which are: start signal, end signal and response signal. Start signal: When SCL is at a high level, SDA jumps from a high level to a low level to start transmitting data. End signal: When SCL is at a high level, SDA jumps from a low level to a high level to end data transmission. Response signal: After receiving 8 bits of data, the slave controller that receives data sends a specific low-level pulse to the master controller that sends data, indicating that the data has been received. After the CPU sends a signal to the slave controller, it waits for the slave controller to send a response signal. After receiving the response signal, the CPU determines whether to continue transmitting the signal based on the actual situation. If no response signal is received, it is determined that the controlled unit has a fault. Among these signals, the start signal is required, and the end signal and response signal can be omitted.


2: I2C Experiment Code

/*
---------------------------------------------------------------
File name: I2C.c
Description: I2C protocol read and write AT24C08
Author: Wen Ziqi
Creation time: 2010-08-17
Test result: [OK]
Notes:

(1) 24C02 data rate The data transfer rate of the I2C bus is 100kbit/s in standard working mode, and
  the maximum transfer rate can reach 400kbit/s in fast mode.
(2) The current frequencies of S3C2440 are as follows: FCLK 405MHz
                        HCLK 135MHz
                        PCLK 67.5MHz
(3) The current I2C protocol is modified from the source code provided by Samsung, and the fault tolerance of the code is improved
  . For example, when I2C is read and written, timeout processing is performed.
---------------------------------------------------
*/
#include "S3C244x.h"
#include "Global.h"
#include "IIC.h"
/*
1:rIICON IIC bus control register
2:rIICSTAT IIC bus control status register
3:rIICADD IIC bus address register
4:rIICDS IIC bus transmit and receive data shift register
5:rIICLC IIC bus multi-master line control register
*/

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

                   I2C basic function interface

======================================================
*/
static volatile UINT8 g_ucI2CDataBuf[256]; //I2C send data buffer
static volatile UINT32 g_unI2CCurDataCount; //I2C current data count
static volatile UINT32 g_unI2CCurStatus; //I2C current status
static volatile UINT32 g_unI2CCurDataOffset; //I2C current send data offset
static UINT32 g_unI2CCurMode; //I2C current mode
static UINT32 g_unIICCONSave; //Temporarily save rIICCON register value

static void __irq I2CISR(void); //I2C interrupt service function

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


/**********************************************************
*File name: I2CWriteByte
*Input: unSlaveAddress Slave address
         unWriteAddress Write address
         pucWriteByte Write byte
*Output: TRUE/FALSE
*Function description: I2C writes a single byte
*Note:
After the host sends the start signal, it sends an addressing byte, and the data transmission is followed by the response.
The data transmission is generally terminated by the stop bit generated by the host. However, if the host still wants to communicate on the bus,
it can generate a repeated start signal and address another slave instead of generating a stop signal first.
In this transmission, there may be different read/write formats.
**********************************************************/
static BOOL I2CWriteByte(UINT32 unSlaveAddress,
                        UINT32 unWriteAddress,
                        UINT8 *pucWriteByte)
{
   BOOL bRt=TRUE;
   UINT32 unTimeouts;

   g_unI2CCurMode = WRDATA; //Current I2C mode: write
   g_unI2CCurDataOffset= 0; //I2C data buffer offset is 0
   g_ucI2CDataBuf[0] = (UINT8)unWriteAddress; //Write address
   g_ucI2CDataBuf[1] = *pucWriteByte; //Write data
   g_unI2CCurDataCount = 2; //Current data count value (i.e. address + data = 2 bytes)
   
   rIICDS = unSlaveAddress; //0xa0 (the upper four bits default to 1010, the lower four bits are xxxx)
   rIICSTAT = 0xf0; //Host sends start
 
   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; //Master sends start
         
       rIICCON = g_unIICCONSave; //Resume I2C operation

        unTimeouts = 1000;

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

       if (! unTimeouts)
       {
           bRt = FALSE;

           goto end;
       }

         
       if (! (g_unI2CCurStatus & 0x1))
       {
            break; //Receive the response (ACK) signal
       }
           
   }

end:
   rIICSTAT = 0xd0; //Stop the host to send status Stop MasTx condition
   rIICCON = g_unIICCONSave; //Resume I2C operation
   DelayNus (10); //Wait until the stop condition is valid

   return bRt;
}

/**********************************************************
*File name: I2CReadByte
*Input: unSlaveAddress Slave address
         unReadAddress Read address
         pucReadByte Read byte
*Output: TRUE/FALSE
*Function description: I2C read single byte
*Note:
 After the host sends the address byte, the host immediately reads the data in the slave.
 When the "R/W" bit of the address byte is 1, after the slave generates a response signal,
 the host transmitter becomes the host receiver, and the slave receiver becomes the slave transmitter.
 After that, the data is sent by the slave and received by the host. Each response is generated by the host, and
 the clock signal CLK is still generated by the host. If the host wants to terminate this transmission, it sends
 a non-acknowledge signal, and then the host generates a stop signal
**********************************************************/
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; //Host sends start  

   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; //Host reception starts
   rIICCON = g_unIICCONSave; //Resume I2C operation
     
   unTimeouts=1000;

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

   if(!unTimeouts)
   {
      bRt=FALSE;

      goto end;
   }

   *pucReadByte= g_ucI2CDataBuf[1];

end:

    return bRt;
}

/************************************************** ********
*File name: I2CWriteNBytes
*Input: unSlaveAddress slave address
         unWriteAddress write address
         pucWriteByte write byte
         unNumOfBytes write byte number
*Output: TRUE/FALSE
*Function description: I2C write multiple bytes
** ************************************************** ***/
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;
}
/******* ***********************************************
*file name :I2CReadNBytes
*Input: unSlaveAddress Slave address
         unReadAddress Read address
         unNumOfBytes  
*Output: TRUE/FALSE
*Function description: I2C read multiple bytes
************************ **********************************/
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;
}
/*
================================================== ==

                   Interrupt service function

================================================ =======
*/
/**************************************** **************
*File name: I2CISR
*Input: None  
*Output: None
*Function description: I2C interrupt service function
****************** ****************************************/
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; //Stop I2C receiving status
              rIICCON = g_unIICCONSave; //Resume I2C operation
              DelayNus(1 ); //Wait until the stop condition is valid
                                                         
                                                               //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 slave address setting
   rIICSTAT = 0x10; //I2C bus data output enable (Rx/Tx)
   rIICLC =(1<<2)|(1); //Filter enable, SDA data delay output
   
   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: Display the results



Keywords:S3C2440  I2C Reference address:S3C2440 I2C Implementation

Previous article:ARM interrupt difference - the difference between LPC2142 and S3C2440
Next article:S3C2440FCLK, HCLK, PCLK configuration

Recommended ReadingLatest update time:2024-11-16 12:56

PWM timer for ARM (S3C2440)
Refer to Chapter 10 "PWM Timer" in the S3C2440 data sheet Overview The S3C2440A has five 16-bit timers. Timers 0, 1, 2, and 3 have pulse width modulation (PWM) functions. Timer 4 is an internal timer without output pins. Timer 0 also contains a dead zone generator for high current drive. S3C2440 has two 8-bit pres
[Microcontroller]
PWM timer for ARM (S3C2440)
S3C2440 - DMA transfer (taking character transfer as an example)
1. Advantages of using DMA and request sources supported by DMA 1. The advantage of DMA is that it does not require CPU intervention during data transmission, which can greatly improve the CPU's working efficiency. 2. DMA is very important in large-capacity data transmission, such as image data transmission, SD ca
[Microcontroller]
Single chip microcomputer simulation I2C bus and 24C02 reading and writing examples
Microcontroller simulates I2C bus and 24C02 (I2C EEP ROM ) reading and writing examples (c source code) /* When using the 51 series microcontroller, it is sometimes necessary to simulate the I2C bus. */ /* Here is an example (reading and writing the serial EEPROM chip at2402) */ /*********************************
[Microcontroller]
I2C reading and writing program for PIC microcontroller
TITLE " TWO WIRE/I2C BUS INTERFACE WITH PIC16C5x " ; LIST P=16C54 ; ;***************************************************************************** ;**  Two wire/I2C Bus READ/WRITE Sample Routines of Microchip's ;**  24Cxx / 85Cxx serial CMOS EEPROM interfacing to a  ;**  PIC16C54 8-bit CMOS single chip microcomputer ;
[Microcontroller]
s3c2440GPIO programming
1.GPIO Introduction:    GPIO (general purpose input/output port) is relative to the chip. If there are GPIO pins on the corresponding chip, the changes of the pins (i.e. the changes of the high and low levels of the pins) can be obtained by reading these pins. s3c2440 belongs to ARM920T, with a total of 130 GPIOs,
[Microcontroller]
S3C2440 Development Board Bare Metal Program Series 06—LCD Controller
1 Overview S3C2440 has very strong support for LCD, both in breadth and depth. Here we will only learn one mode and then practice various modes later when we have the energy. This article discusses several aspects including display mode, display timing, hardware connection, and controller register settings. 2.
[Microcontroller]
S3C2440 Development Board Bare Metal Program Series 06—LCD Controller
Touch screen driver development example on S3C2440
1. Development Environment Host: VMWare--Fedora 9 Development board: Mini2440--64MB Nand, Kernel:2.6.30.4 Compiler: arm-linux-gcc-4.3.2 2. Prerequisite Knowledge 1. Linux Input Subsystem:    In Linux, the input subsystem is composed of the input subsystem device driver layer, the input subsystem core layer (Input
[Microcontroller]
Touch screen driver development example on S3C2440
I2C bus ferroelectric memory FM31256 with RTC
  FM31256 is a new generation of multifunctional system monitoring and non-volatile ferroelectric memory chip launched by Ramtron. Compared with other non-volatile memories, it has the following advantages: fast read/write speed, no write waiting time; low power consumption, static current less than 1 mA, write current
[Microcontroller]
I2C bus ferroelectric memory FM31256 with RTC
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号