📄 i2c.c
字号:
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* source\i2c.c 1.0 */
/* */
/* DESCRIPTION */
/* */
/* DIAGNOSTIC CODE for S3C4510B0 */
/* */
/* */
/* DATA STRUCTURES */
/* */
/* FUNCTIONS : serial EEPROM 24C256 read and write , etc */
/* */
/* DEPENDENCIES */
/* */
/* */
/* NAME: Nicolas Park */
/* The last Modification date: 18-April-2002 */
/* REMARKS: Created initial version 1.0 */
/* */
/* Copyright (C) 2002 AIJISYSTEM CO.,LTD */
/*************************************************************************/
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "std.h"
#include "apdialog.h"
#include "s3c4510b0.h"
#include "uart.h"
#include "isr.h"
#include "pollio.h"
#include "i2c.h"
#include "c_lcd.h"
#include "memory.h"
#include "sysconf.h"
#define MAX_LINE_BUF 250
IIC_DATA_TX_FORMAT iic_txmit;
IIC_DATA_RX_FORMAT iic_recv;
void IicSetup(void)
{
// Reset IIC Controller
IICCON = IICRESET ;
// Set Prescale Value: fSCL is IIC serial clock frequency
// fSCL defined at sysconf.h
IICPS = SetPreScaler((int)fSCL); //support upto 100KHz
}
int SetPreScaler(int sclk)
{
return((int)(((fMCLK/sclk)-3.0)/16.0)-0.5); //add 0.5 for
}
void IICWriteIsr(void)
{
if(!(iic_txmit.FLAG & (U32)iic_byte_addr_msb)) {
/* Send byte address: MSB */
IICBUF = iic_txmit.BYTE_ADDR_MSB;
iic_txmit.FLAG |= (U32)iic_byte_addr_msb;
}
else if(!(iic_txmit.FLAG & (U32)iic_byte_addr_lsb)) {
/* Send byte address: LSB */
IICBUF = iic_txmit.BYTE_ADDR_LSB;
iic_txmit.FLAG |= (U32)iic_byte_addr_lsb;
}
else if(iic_txmit.BuffByteCnt < iic_txmit.WriteDataSize) {
IICBUF = iic_txmit.PAGE_BUFFER[iic_txmit.BuffByteCnt++];
}
else {
/* STOP IIC Controller */
IICCON = STOP;
/* byte data or page data transmit done */
iic_txmit.FLAG |= (U32)iic_page_tx_done;
}
}
void IICReadIsr(void)
{
if(!(iic_recv.FLAG & (U32)iic_byte_addr_msb)) {
//else if(!(iic_recv.FLAG & (U32)iic_byte_addr_msb)) {
/* Send byte address: MSB */
IICBUF = iic_recv.BYTE_ADDR_MSB;
iic_recv.FLAG |= (U32)iic_byte_addr_msb; /* send msb byte addr */
}
else if(!(iic_recv.FLAG & (U32)iic_byte_addr_lsb)) {
/* Send byte address: LSB */
IICBUF = iic_recv.BYTE_ADDR_LSB;
iic_recv.FLAG |= (U32)iic_byte_addr_lsb; /* send lsb byte addr */
}
else if(!(iic_recv.FLAG & (U32)iic_repeat_start)) {
/* Repeat Start */
IICCON = RESTART;
IICCON = START|ACK|IEN;
IICBUF = iic_recv.SLAVE_ADDR|S_READ;
iic_recv.FLAG |= (U32)iic_repeat_start;
}
else if(!(iic_recv.FLAG & (U32)iic_multi_recv)) {
/* Receive multiple data */
IICCON = ACK|IEN;
iic_recv.FLAG |= (U32)iic_multi_recv;
}
else if(iic_recv.ByteReadCnt < iic_recv.ReadDataSize) {
*(iic_recv.RCV_BUFFER)++ = IICBUF;
iic_recv.ByteReadCnt++;
}
else if(!(iic_recv.FLAG & (U32)iic_no_more_recv)) {
/* Now,no more received data is required from slave */
IICCON = NOACK|IEN;
iic_recv.FLAG |= (U32)iic_no_more_recv;
}
else { /* Receive last data and STOP */
*(iic_recv.RCV_BUFFER)++ = IICBUF;
/* STOP IIC Controller */
IICCON = STOP;
/* byte data receive done */
iic_recv.FLAG |= (U32)iic_byte_rx_done;
}
}
void IICWriteInt(U8 SlaveAddr,U32 WriteAddr,U8 *data,U32 SizeOfData)
{
int page,j;
int no_of_page; /* Number of page */
int remain_byte;
U32 PageAccessAddr;
SysSetInterrupt(nIIC_INT,IICWriteIsr) ; /*Setup IIC Tx interrupt */
Enable_Int(nIIC_INT) ;
PageAccessAddr = WriteAddr;
iic_txmit.SLAVE_ADDR = SlaveAddr;
no_of_page = (int)(ceil(SizeOfData/(U32)SizeOfPage));
remain_byte = (int)(SizeOfData%(U32)SizeOfPage);
for(page=0; page <= no_of_page;page++)
{
if(SizeOfData < SizeOfPage) {
for(j=0; j < SizeOfData; j++)
iic_txmit.PAGE_BUFFER[j] = *data++;
iic_txmit.WriteDataSize = SizeOfData;
}
else {
if(page == no_of_page) {
for(j=0; j < remain_byte; j++)
iic_txmit.PAGE_BUFFER[j] = *data++;
iic_txmit.WriteDataSize = remain_byte;
}
else {
for(j=0; j < SizeOfPage; j++)
iic_txmit.PAGE_BUFFER[j] = *data++;
iic_txmit.WriteDataSize = SizeOfPage;
}
}
IicSetup();
iic_txmit.FLAG = 0x0;
iic_txmit.BuffByteCnt = 0x0;
iic_txmit.BYTE_ADDR_MSB = (U8)((PageAccessAddr>>8) & 0xff);
iic_txmit.BYTE_ADDR_LSB = (U8)(PageAccessAddr & 0xff);
/* Step 1: Setup IICON register for transmit start */
while(IICCON & BUSY); /* Wait! the iic bus is busy */
IICCON = START|ACK|IEN; /* Now, Start to transmit */
/* Send Slave Address and Write command */
IICBUF = iic_txmit.SLAVE_ADDR|S_WRITE;
while(!(iic_txmit.FLAG & iic_page_tx_done));
PageAccessAddr += SizeOfPage;
for(j=0; j< (int)Write_Cycle_ms(5); j++); /* for 5ms write cycle */
}
}
void *IICReadInt(U8 SlaveAddr,U32 ReadAddr,U32 SizeOfData)
{
U8 *ReadPtr; /* data read pointer */
IicSetup();
SysSetInterrupt(nIIC_INT,IICReadIsr) ; /*Setup IIC Tx interrupt */
Enable_Int(nIIC_INT) ;
/*Memory alloc for receive data */
if((ReadPtr = (U8 *)malloc((unsigned)SizeOfData)) == (U8 *)(NULL))
Print("\rMemory allocation error occurred!!!\r");
iic_recv.RCV_BUFFER = ReadPtr;
iic_recv.FLAG = 0x0;
iic_recv.ByteReadCnt = 0x0;
iic_recv.ReadDataSize = SizeOfData;
iic_recv.SLAVE_ADDR = SlaveAddr;
iic_recv.BYTE_ADDR_MSB = (U8)((ReadAddr>>8) & 0xff);
iic_recv.BYTE_ADDR_LSB = (U8)(ReadAddr & 0xff);
/* Step 1: Setup IICON register for receive start */
while(IICCON & BUSY); /* Wait! the iic bus is busy */
IICCON = START|ACK|IEN;
/* Send Slave Address and Write command */
IICBUF = iic_recv.SLAVE_ADDR|S_WRITE;
while(!(iic_recv.FLAG & iic_byte_rx_done));
return(ReadPtr); /* return receive data pointer */
}
/******************************************************************
* *
* IIC Test using IIC 64Kbit Serial EEPROM *
* *
******************************************************************/
void IICTest(void)
{
char TestItemSel ;
IicSetup() ;// Initialize IIC control block
Enable_Int(nGLOBAL_INT); //enable global interrupt mask
do {
Print("\n\n") ;
Print("\n##########################################\r") ;
Print("\n# IIC Test Items #\r") ;
Print("\n##########################################\r") ;
Print("\n# 1. IIC Page Write Test(INT) - [W] #\r") ;
Print("\n# 2. IIC Sequential Read Test(INT) - [R] #\r") ;
Print("\n# 3. IIC Read/Write Test(INT.) - [L] #\r") ;
Print("\n# 4. IIC Loopback test(INT) - [B] #\r") ;
Print("\n# 5. IIC configuration view - [C] #\r") ;
Print("\n# 6. Quit IIC Test - [Q] #\r") ;
Print("\n##########################################\r") ;
Print("\n\rSelect Test Item : ") ;
TestItemSel = get_byte() ;
switch(TestItemSel)
{
case 'W' : case 'w' : IICWriteTest() ; break ;
case 'R' : case 'r' : IICReadTest() ; break ;
case 'L' : case 'l' : IICAutoTest() ; break ;
case 'B' : case 'b' : IICLoopBackTest() ; break ;
case 'C' : case 'c' : config_iic() ; break ;
case 'Q' : case 'q' : break ;
default : return ;
}
Print("\n Press Any Key to Continue IIC Test") ;
get_byte() ;
} while ( (TestItemSel != 'Q') && (TestItemSel != 'q') ) ;
}
/******************************************************************
* *
* IIC EEPROM READ & WRITE TEST MODULE *
* *
******************************************************************/
/* IIC Write Test Program */
void IICWriteTest(void)
{
U8 TestData[StorageSize] ;
U32 i, GetDataSize=0 ;
U32 ByteAddr;
Print("\n\rEnter Byte write address of IIC EEPROM.");
Print("\n\r=>[0x%x]: ",(int)StorageSize);
ByteAddr = gethex2dec(4); get_byte();
Print("\n\rInput Write Character.");
Print("\n\r=>(upto %dbytes): ",(int)StorageSize) ;
while ((TestData[GetDataSize] = get_byte()) != CR ) GetDataSize++ ;
Print("\n%d bytes received : ",GetDataSize);
for (i=0;i<GetDataSize;i++) put_byte(TestData[i]) ;
IICWriteInt((U8)IIC_DEV_0,(U32)ByteAddr,TestData,GetDataSize);
Print("\n\rIIC Serial EEPROM write done.\r");
}
/* IIC Read Test Program */
void IICReadTest(void)
{
U8 *DataBuff;
U32 ReadDataSize ;
int i,p;
U32 ByteAddr;
Print("\n\rEnter Byte write address of IIC EEPROM.");
Print("\n\r=>[0x%x]: ",(int)StorageSize);
ByteAddr = gethex2dec(4); get_byte();
Print("\n\r >>> Input Read Data Size : ") ;
ReadDataSize = get_digit() ;
Print("\n\r\r <<< READ DATA FROM IIC SERIAL EEPROM >>>\r\r") ;
DataBuff=(U8 *)IICReadInt((U8)IIC_DEV_0,(U32)ByteAddr,ReadDataSize);
for (i=0,p=0;i<ReadDataSize;i++)
{
if(!(i%SizeOfPage)) Print("\n\r[%d]0x%x: ",p++,ByteAddr);
put_byte(*DataBuff++);
ByteAddr++;
}
}
/* IIC Read/Write Test Program by interrupt method */
void IICAutoTest(void)
{
U8 *DataBuff;
U8 TestData[] = "IIC Read/Write Test Pattern. ";
U8 TempData ;
U32 i, TestSize, TestLoop ;
TestLoop = TestSize = sizeof(TestData) ;
l2Print("IIC Test","=>IICAutoTest");
while(TestLoop--) {
Print("\r $$ ") ;
/* Write IIC test pattern to Serial EEPROM */
IICWriteInt((U8)IIC_DEV_0,(U32)IICTestAddr,TestData,TestSize);
for (i=0;i<(int)Write_Cycle_ms(5);i++); /* 5ms write cycle */
/* Read IIC test pattern to Serial EEPROM */
DataBuff=(U8 *)IICReadInt((U8)IIC_DEV_0,(U32)IICTestAddr,TestSize);
for (i=0;i<(int)Write_Cycle_ms(5);i++); /* 5ms write cycle */
for (i=0;i<TestSize;i++) put_byte(*DataBuff++) ;
/* Next Test Pattern Generation */
TempData = TestData[TestSize] ;
TestData[TestSize] = TestData[0] ;
for (i=0;i<TestSize;i++) TestData[i] = TestData[i+1] ;
} // End of while loop
}
/* IIC Loopback Test */
int IICLoopBackTest(void)
{
U8 *DataBuff;
U8 *TestData, *TempData;
int i;
int TestFlag = 1;
Print("\n\r\r$IIC R&W Test with IIC EEPROM(%dKByte).\r",IICTestSize/1024);
/* Memory allocation for IIC test pattern */
if((TestData = (U8 *)malloc((unsigned)IICTestSize)) == (U8 *)(NULL))
Print("\n\rMemory allocation error occurred!!!\r");
/* To generate IIC test pattern */
//Print("\r=> Generating R,W pattern data(%dBytes).",IICTestSize);
TempData = TestData; /* copy test pattern data memory */
for(i=0; i < IICTestSize; i++) *TempData++ = (U8)PatternGen(i);
/* Write IIC test pattern to Serial EEPROM */
Print("\n\r=> Writing data.....");
IICWriteInt((U8)IIC_DEV_0,(U32)IICTestAddr,TestData,IICTestSize);
for (i=0;i<(int)Write_Cycle_ms(5);i++); /* 5ms write cycle */
/* Read IIC test pattern from Serial EEPROM */
Print("\n\r=> Reading data....");
DataBuff=(U8 *)IICReadInt((U8)IIC_DEV_0,(U32)IICTestAddr,IICTestSize);
for (i=0;i<(int)Write_Cycle_ms(5);i++); /* 5ms write cycle */
/* Compare the read/write test pattern */
TempData = TestData; /* copy test pattern data memory */
Print("\n\r=> Comparing data....");
for (i=0;i<IICTestSize-1;i++)
{
if (*TempData++ != *DataBuff++) {
Print("\n\r[ERROR] 0x%x : W=%d:R=%d\r",i,*TempData-1,*DataBuff-1);
TestFlag = 0; /* Indicate error occurred */
}
PrtIICStatus(i);
} // End of while loop
Print("\nOk\r");
free(TestData); /* Return allocated memory to user memory */
return(TestFlag);
}
void PrtIICStatus(int byte)
{
char buff[MAX_LINE_BUF];
int i;
sprintf(buff,"=> R&W pattern compare : %dbyte",byte);
put_string(buff); /* to console */
for(i=0;i < sizeof(buff);i++) put_byte('\b');
IOPDATA = ~(1<<(byte%4)); /* to LED */
}
void config_iic(void)
{
Print("\n\r<< IIC BUS Special Registers. >>\r\r");
Print("\nIICCON = 0x%x \r", IICCON);
Print("\nIICBUF = 0x%x \r", IICBUF);
Print("\nIICPS = 0x%x \r", IICPS);
Print("\nIICCOUNT = 0x%x \r", IICCOUNT);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -