/*****************************************************
* 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
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
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- 【Qinheng Trial】549+ Light up a lamp first
- Gated Clock.rar
- Battery explosion problem
- What is the difference between a thermocouple and a RTD?
- EEWORLD University Hall----Live playback: Bidirectional CLLLC resonance, dual active bridge (DAB) reference design
- Online Upgrade Method of DSP Application Program Based on Serial Communication
- If you are interested in AI, which technology do you focus on?
- [EVAL-M3-TS6-665PN] Interpretation again
- What is output impedance? What is impedance matching?
- [Unboxing and document display of the ACM32F070 capacitive touch development board]