s3c2440的cpu 在与 eeprom 之间进行通信时有两种方式:第一种,直接通过配置cpu的寄存器;还有一种是通过手工写协议的方式来实现通信:
/**************************************************************
File name : iic.c
Author :
version : V1.0
Date : 2010-8-18
Description : IIC init and test
**************************************************************/
#include "2440addr.h"
#include "iic.h"
#include "UART.h"
#include "timer4.h"
unsigned char *address = (unsigned char)0x30100000; //data address
unsigned char device_address = 0xa0; //EEPROM ID_CODE is 1010 , A2A1A0 = 000 , write or read
//*******************************************************************************************************
//************************************** 通过CPU的模块写协议 ************************************
//*******************************************************************************************************
/*************************************************************
Function name : IIC_Init
Description : init GPE as IIC
Input Arguments : void
Returns : void
othor :
**************************************************************/
void IIC_Init(void)
{
volatile unsigned int number;
number = rGPECON;
number &= ~(((unsigned)3 << 30) | ((unsigned)3 << 28)); // GPECON[31:30] GPECON[29:28]
number |= ((unsigned)2 << 30) | ((unsigned)2 << 28); // IICSDA IICSCL
rGPECON = number; // 10 10
rIICCON = (1 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | 0;
}
/**************************************************************
Function name : IIC_Write_Byte
Description : writ data to EEPROM with IIC
Input Arguments : device_addr, worde_addr and data
Returns : void
othor : Byte Write
**************************************************************/
void IIC_Write_Byte(unsigned char device_addr, unsigned char worde_addr, unsigned char data)
{
//rIICCON = (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | 0;
rIICDS = device_addr; //transmit device_address
rIICSTAT = 0xf0; // Master transmit mode and start transmit
while(!(rIICCON & (1 << 4)));
rIICDS = worde_addr; //transmit worde_address
rIICCON &= ~(1 << 4); //clear interupt pending
while(!(rIICCON & (1 << 4))); //wait interupt
rIICDS = data; //transmit data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4))); //end transmit
rIICSTAT = 0xd0; //stop transmit
rIICCON &= ~(1 << 4);
Delay_1ms(10); //dealy , Twr <= 10ms
}
/*************************************************************
Function name : IIC_Write_Page
Description : writ data to EEPROM with IIC
Input Arguments : device_addr, worde_addr and *data
Returns : void
othor : Page Write
**************************************************************/
void IIC_Write_Page(unsigned char device_addr, unsigned char worde_addr, unsigned char *data)
{
volatile unsigned int i;
rIICDS = device_addr; //transmit device_address
rIICSTAT = 0xf0; // Master transmit mode and start transmit
while(!(rIICCON & (1 << 4)));
rIICDS = worde_addr; //transmit worde_address
rIICCON &= ~(1 << 4); //clear interupt pending
while(!(rIICCON & (1 << 4))); //wait interupt
for(i = 0; i < 8; i++)
{
rIICDS = *data; //transmit data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4))); //end transmit
data++;
}
rIICSTAT = 0xd0; //stop transmit
rIICCON &= ~(1 << 4);
Delay_1ms(10); //dealy , Twr <= 10ms
}
/*********************************************************************
Function name : IIC_Read
Description : read data from EEPROM with IIC
Input Arguments : device_addr, worde_addr, *data and size
Returns : void
othor : Random and Sequential Read(随机连续读取)
**********************************************************************/
void IIC_Read(unsigned char device_addr, unsigned char worde_addr, unsigned char *data, unsigned int size_byte)
{
volatile unsigned int i;
unsigned char *pdata = data;
//rIICCON = (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | 0;
//rIICSTAT = 0xF0;
rIICDS = (device_addr & (~(1 << 0))); // transmit device_address //clear interupt panding
rIICSTAT = 0xF0; //Master transmit mode and start transmit
//while(rIICSTAT & (1 << 0)); //receive a ACK
while(!(rIICCON & (1 << 4))); //make a interupt
rIICDS = worde_addr; //transmit worde_address
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4)));
//rIICCON = (1 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | 0;
rIICDS = (device_addr | (1 << 0)); //transmit device_address
rIICSTAT = 0xB0; //Master recive mode and start transmit
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4))); //receive data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4))); //wait data arrive
for(i = 0; i < size_byte; i++)
{
*pdata = rIICDS; //receive data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4)));
pdata++;
}
rIICSTAT = 0x90; //stop transmit
rIICCON &= ~(1 << 4);
Delay_1ms(10); //dealy Twr ~= 10ms
}
/**************************************************************
Function name : IIC_Read
Description : read data from EEPROM with IIC
Input Arguments : device_addr and *data
Returns : void
othor : Current Address Read(当前地址读)
***************************************************************/
void IIC_Read_Now(unsigned char device_addr, unsigned char *data)
{
//rIICCON = (1 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | 0;
rIICDS = (device_addr | (1 << 0)); //transmit device_address
rIICSTAT = 0xB0; //Master recive mode and start transmit
//rIICCON &= ~(1 << 4); //clear interupt pending
while(!(rIICCON & (1 << 4))); //receive data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4))); //wait data arrive
*data = rIICDS; //receive data
rIICCON &= ~(1 << 4);
while(!(rIICCON & (1 << 4)));
rIICSTAT = 0x90; //stop transmit
rIICCON &= ~(1 << 4);
Delay_1ms(10); //dealy Twr ~= 10ms
}
void Test_IIC(void)
{
unsigned int i;
unsigned char *paddress = address;
unsigned char page_addr = 0;
unsigned char data[8];
IIC_Init();
rIICSTAT = 0x10;
for(i = 0; i < 8; i++)
data[i] = 8;
Uart_Printf("start write data ... /n");
/* for(i = 0; i < 256; i++) //write a Byte data
{
IIC_Write_Byte(device_address,i,8);
}
*/
for(i = 0; i < 32; i++) //write a Page data
IIC_Write_Page(device_address,(i << 3),data);
Uart_Printf("start read data ... /n");
IIC_Read(device_address,(page_addr<<3),paddress,256); //Random and Sequential Read
//IIC_Read_Now(device_address,paddress); //Current Address Read
Uart_Printf("the data is ... /n");
paddress = address;
for(i = 0; i < 256; i++)
{
if(((i % 16) == 0) && (i != 0))
Uart_Printf("/n");
Uart_Printf(" %0x", *paddress);
paddress++;
}
}
//*******************************************************************************************************
//***************************************** 手工写协议 ************************************************
//*******************************************************************************************************
/****************************************************************
Function name : Set_IIC_DAT_Output
Description : switch mode as output
Input Arguments : void
Returns : void
othor :
*****************************************************************/
void Set_IIC_DAT_Output(void)
{
volatile unsigned int number;
number = rGPECON;
number &= ~(((unsigned)3 << 30) | ((unsigned)3 << 28)); // GPE15[31:30] GPE14[29:28]
number |= ((unsigned)1 << 30) | ((unsigned)1 << 28); // IICSDA IICSCL
rGPECON = number; // 01 01
}
/***************************************************************
Function name : Set_IIC_DAT_Input
Description : switch mode as input
Input Arguments : void
Returns : void
othor :
****************************************************************/
void Set_IIC_DAT_Input(void)
{
volatile unsigned int number;
number = rGPECON;
number &= ~(((unsigned)3 << 30) | ((unsigned)3 << 28)); // GPE15[31:30] GPE14[29:28]
number |= ((unsigned)0 << 30) | ((unsigned)1 << 28); // IICSDA IICSCL
rGPECON = number; // 00 01
}
/***************************************************************
Function name : IIC_Start
Description : start IIC
Input Arguments : void
Returns : void
othor :
***************************************************************/
void IIC_Start(void)
{
// start definition : SCL = 1, SDA = 1 --> 0 ===> SCL = 0
SDA_H;
SCL_H;
Delay_1ms(1); //延时 t > 4.7us
SDA_L;
Delay_1ms(1); // t > 4.0us
SCL_L;
}
/**************************************************************
Function name : IIC_Stop
Description : stop IIC
Input Arguments : void
Returns : void
othor :
***************************************************************/
void IIC_Stop(void)
{
// stop definition : SCL = 1, SDA = 0 --> 1
SDA_L;
Delay_1ms(1);
SCL_H;
Delay_1ms(1); //延时 t > 4.7us
SDA_H;
Delay_1ms(1); //t > 4.7us
}
/**************************************************************
Function name : IIC_Ack
Description : Output Acknowledge
Input Arguments : void
Returns : void
othor :
***************************************************************/
void IIC_Send_Ack(void)
{
SCL_L;
Delay_1ms(1);
Set_IIC_DAT_Output(); //切换为输入模式
Delay_1ms(1);
SDA_L;
Delay_1ms(1); // t > 4.7/2us
SCL_H;
Delay_1ms(1); // t > 4.0us
SCL_L;
Delay_1ms(1); // t > 4.7/2us
SDA_H;
}
/**************************************************************
Function name : IIC_Send_no_Ack
Description : Output Acknowledge
Input Arguments : void
Returns : void
othor :
***************************************************************/
void IIC_Send_no_Ack(void)
{
Delay_1ms(1); // t > 4.7/2us
SCL_L;
Delay_1ms(1);
Set_IIC_DAT_Output(); //切换为输入模式
Delay_1ms(1);
SDA_H;
Delay_1ms(1); // t > 4.7/2us
SCL_H;
Delay_1ms(1); // t > 4.0us
SCL_L;
Delay_1ms(1); // t > 4.7/2us
}
/****************************************************************
Function name : IIC_Check_Ack
Description : receive a Acknowledge single
Input Arguments : void
Returns : int
othor :
****************************************************************/
int IIC_Check_Ack(void)
{
volatile unsigned int temp;
Set_IIC_DAT_Input();
Delay_1ms(1);
SCL_L;
Delay_1ms(1);
SCL_H;
Delay_1ms(1);
if(rGPEDAT & (1 << 15)) //read ack signal
temp = 1; // 1 : no ack
else // 0 : ack
temp = 0;
Set_IIC_DAT_Output();
Delay_1ms(1);
SCL_L;
Delay_1ms(1);
return temp;
}
/**************************************************************
Function name : Write
Description : write a data to EEPROM wtih IIC
Input Arguments : data
Returns : void
othor :
**************************************************************/
void Write(unsigned char data)
{
volatile unsigned int i;
Set_IIC_DAT_Output();
Delay_1ms(1);
for(i = 1; i <= 8; i++) // transmit a 8bits data
{
SCL_L;
Delay_1ms(1);
if(data & (1 << (8 - i))) //verdict a bit is 1 or 0
SDA_H;
else
SDA_L;
Delay_1ms(1);
SCL_H;
Delay_1ms(1);
}
SCL_L;
Delay_1ms(1);
}
/**************************************************************
Function name : Read
Description : read a data from EEPROM wtih IIC
Input Arguments : *data
Returns : void
othor :
**************************************************************/
void Read(unsigned char *data)
{
volatile unsigned int i;
unsigned char *pdata = data;
Set_IIC_DAT_Input();
Delay_1ms(1);
for(i = 1; i <= 8; i++) // receive a 8bits data
{
SCL_L;
Delay_1ms(1);
SCL_H;
Delay_1ms(1);
if(rGPEDAT & (1 << 15)) //verdict a bit is 1 or 0
*pdata = (*pdata) | (1 << (8 - i));
else
*pdata = (*pdata) & (~(1 << (8 - i)));
Delay_1ms(1);
}
SCL_L;
Delay_1ms(1);
Set_IIC_DAT_Output();
Delay_1ms(1);
}
/***************************************************************
Function name : IIC_Read_Hand
Description : read a data from EEPROM wtih IIC
Input Arguments : device_addr, *data and worde_addr
Returns : void
othor :
***************************************************************/
void IIC_Read_Hand(unsigned char device_addr, unsigned char worde_addr, unsigned char *data)
{
volatile unsigned int k;
volatile unsigned int temp;
unsigned char *pdata = data;
Set_IIC_DAT_Output();
Delay_1ms(1);
IIC_Start(); //start
Write(device_addr & (~(1 << 0))); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k) // k = 1 read failed
{ // 0 read succeed
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_read_stop;
}
Write(worde_addr); //transmit memory address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write memory address no ack! /n");
temp = 0;
goto iic_read_stop;
}
IIC_Start(); //start
Write(device_addr | (1 << 0)); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_read_stop;
}
Read(pdata); //read data
IIC_Send_no_Ack(); //send no ack
temp = 1;
iic_read_stop:
IIC_Stop(); //stop
/*
if(temp)
Uart_Printf(" read succeed . /n"); //temp = 1 read false
else // 0 read true
Uart_Printf(" read failed ! /n");
*/
}
/***************************************************************
Function name : IIC_ReadPage_Hand
Description : read a data from EEPROM wtih IIC
Input Arguments : device_addr, *data and worde_addr
Returns : void
othor :
***************************************************************/
void IIC_ReadPage_Hand(unsigned char device_addr, unsigned char worde_addr, unsigned char *data)
{
volatile unsigned int i, k;
volatile unsigned int temp;
unsigned char *pdata = data;
Set_IIC_DAT_Output();
Delay_1ms(1);
IIC_Start(); //start
Write(device_addr & (~(1 << 0))); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k) // k = 1 read failed
{ // 0 read succeed
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_read_stop;
}
Write(worde_addr << 3); //transmit memory address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write memory address no ack! /n");
temp = 0;
goto iic_read_stop;
}
IIC_Start(); //start
Write(device_addr | (1 << 0)); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_read_stop;
}
for(i = 1; i <= 8; i++)
{
Read(pdata); //read data
if(i != 8)
IIC_Send_Ack(); //send a ack
pdata++;
}
IIC_Send_no_Ack(); //send no ack
temp = 1;
iic_read_stop:
IIC_Stop(); //stop
/*
if(temp)
Uart_Printf(" read succeed . /n"); //temp = 1 read false
else // 0 read true
Uart_Printf(" read failed ! /n");
*/
}
/***************************************************************
Function name : IIC_Write_Hand
Description : write a data to EEPROM wtih IIC
Input Arguments : device_addr , worde_addr and data
Returns : void
othor :
***************************************************************/
void IIC_Write_Hand(unsigned char device_addr, unsigned char worde_addr,unsigned char data)
{
volatile unsigned int k, temp;
Set_IIC_DAT_Output();
Delay_1ms(1);
IIC_Start(); // start
Write(device_addr & (~(1 << 0))); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k) // k = 1 read failed
{ // 0 read succeed
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_stop;
}
Write(worde_addr); //transmit memory address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write memory address no ack ! /n");
temp = 0;
goto iic_stop;
}
Write(data); //transmit data
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write data no ack ! /n");
temp = 0;
goto iic_stop;
}
else
temp = 1;
iic_stop:
IIC_Stop(); //stop
Delay_1ms(10);
/*
if(temp)
Uart_Printf(" write succeed . /n"); //temp = 1 read false
else // 0 read true
Uart_Printf(" write failed ! /n");
*/
}
/***************************************************************
Function name : IIC_WritePage_Hand
Description : write some data to EEPROM wtih IIC
Input Arguments : device_addr , worde_addr and *data
Returns : void
othor :
***************************************************************/
void IIC_WritePage_Hand(unsigned char device_addr, unsigned char worde_addr,unsigned char *data)
{
volatile unsigned int i;
volatile unsigned int k, temp;
unsigned char *pdata = data;
Set_IIC_DAT_Output();
Delay_1ms(1);
IIC_Start(); // start
Write(device_addr & (~(1 << 0))); //transmit device address
k = IIC_Check_Ack(); // raad a ack signal
if(k) // k = 1 read failed
{ // 0 read succeed
Uart_Printf(" write iic device address no ack! /n");
temp = 0;
goto iic_stop;
}
Write(worde_addr << 3); //transmit memory address
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write memory address no ack ! /n");
temp = 0;
goto iic_stop;
}
for(i = 1; i <= 8; i++)
{
Write(*pdata); //transmit data
k = IIC_Check_Ack(); // raad a ack signal
if(k)
{
Uart_Printf(" write data no ack ! /n");
temp = 0;
goto iic_stop;
}
else
temp = 1;
pdata++;
}
iic_stop:
IIC_Stop(); //stop
Delay_1ms(10);
/*
if(temp)
Uart_Printf(" write succeed . /n"); //temp = 1 read false
else // 0 read true
Uart_Printf(" write failed ! /n");
*/
}
void test_2(void)
{
unsigned int i;
unsigned char *paddress = address;
unsigned char num;
unsigned char data[8];
for(i = 0; i < 8; i++)
data[i] = 7;
Set_IIC_DAT_Output();
Uart_Printf("/n start write data ... /n"); //write data
for(i = 0; i < 32; i ++)
{
num = i;
//IIC_Write_Hand(0xa0,i,i);
IIC_WritePage_Hand(0xa0,i,data);
}
Uart_Printf(" start read data ... /n"); //read data
paddress = address;
for(i = 0; i < 32; i ++)
{
//IIC_Read_Hand(0xa0,i,paddress);
IIC_ReadPage_Hand(0xa0,i,paddress);
paddress = paddress + 8;
}
paddress = address;
for(i = 0; i < 256; i ++)
{
if(((i % 16) == 0) & (i != 0))
Uart_Printf("/n");
Uart_Printf(" %0x", *paddress);
paddress++;
}
}