⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 三星mcu S3C4510B评估板的原码
💻 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 + -