📄 i2c.c
字号:
/*********************************************************************
* Description:
* This pgm demostrate the I2C block control and setting.
* All processing is based on interrupt mothed.
* History:
* 1) Rev. 1.0: primarily version; by felix; Oct.10/2002
*
* Status:
* Function test only, not overall. Please contat us if bug detected.
* All rights reserved by Fudan JHB Tech. Co. Ltd.
*
* Any quesiton or comments, please feel free to contact us.
*********************************************************************/
#include "global_function.h"
#include "I2C.h"
extern _EscFlag;
//* global variables
B32 _iicStatus;
B32 _iicMode;
B8 _iicData[MaxRDByte]; //only _iicData[MaxRDByte-1:0] is valid for read result, MSB is reserved
B32 _iicIndex; //array index for _iicData[ ]
B8 IIC_demo(void)
{
B8 SlaveAddr, Addr = 0x00; //SlaveAddr: chip address; Addr: word address in a chip
B8 Data = 0;
B8 Input;
printf("\n\n\r------------------ I2C demo ------------------\n\r");
printf(": read/write I2C device on the board\n\r");
printf(":Esc to return\n\r");
Config_PortF_as_IIC();
IIC_Init();
SlaveAddr = (B8)IIC_ChipAddr; //Slave address
while(!_EscFlag)
{
printf(": Read/Write?(r/w): ");
Input = Uart0_GetInput();
Uart0_SendByte(Input);
while(!(Input == 'r' || Input == 'w'))
{
Uart0_SendByte(0x08);
Input = Uart0_GetInput();
Uart0_SendByte(Input);
if(_EscFlag)
return;
}
printf("\n\r: Address(0-255) = ");
while((Addr = Uart0_GetInput()) != '\r')
Addr += (Addr * 10);
if(_EscFlag)
return;
if(Input == 'r')
{
Data = IIC_Rx(SlaveAddr, Addr); // read in 1 byte from [SlaveAddr+Addr]
printf("\n\r: Read ");
Uart0_SendByte(Data);
printf(" from IIC-EEPROM at ");
Uart0_SendByte(Addr);
printf("\n\r");
}
else
{
printf("\n\r: DataOut(0-255) = ");
while((Data = Uart0_GetInput()) != '\r')
Data += (Data * 10);
IIC_Tx(SlaveAddr, Addr, Data);
printf("\n\r: Write ");
Uart0_SendByte(Data);
printf(" to IIC-EEPROM at ");
Uart0_SendByte(Addr);
printf("\n\r");
}
}
return(TRUE);
}
void Config_PortF_as_IIC(void)
{
//* port init
rPCONF = 0xa; //config I/O port as IIC interface
rPUPF = 0x3; //pull-up disable
}
void IIC_Init(void)
{
//* int init
rINTCON = 0x1; // IRQ/vectored IRQ enable
rINTMOD = 0x0; // IRQ mode
rINTMSK &= ~BIT_IIC; // int enable
//* int priority is default
//rINTPSLV
//rINTPMST
pISR_IIC = (int)IIC_Serv; //map int serve function address
}
////////////////////////////////////////////////////////////////////
// See S3C44B0X manual page 16-7 for detailed IIC Transmit operation flow //
///////////////////////////////////////////////////////////////////
B8 IIC_Tx(B8 SlaveAddr, B8 Addr, B8 Data)
{
//* initialize
rIICCON = 0xe4; // int and ACK enable, clock setting
//* transfer slave address
_iicMode = WRITE;
rIICDS = SlaveAddr; // word address
rIICSTAT = 0xf0; // MasterTx; Start
//Clearing the pending bit isn't needed here because the pending bit has been cleared.
//* transfer word address and data
_iicIndex = 0;
_iicData[0] = Addr;
_iicData[1] = Data;
while(_iicIndex <= 2); // wait until write is done: 2 bytes (Addr+Data) and a Stop condition
// write operation is handled in int serv func
_iicMode = POLLACK;
while(TRUE)
{
//* start a slaveaddr transfer porecss to get device status
rIICDS = SlaveAddr;
_iicStatus = 0x100; // this value is used to test only
rIICSTAT = 0xf0; // MasterTx,Start;
rIICCON &= 0xef; // resumes IIC operation.
while(_iicStatus == 0x100); // waiting for int serv func
if(!(_iicStatus&0x1)) // Slave is busy(in internal write cycle)
break; // when ACK is received, break while loop
}
rIICSTAT = 0xd0; //stop MasterTx condition
rIICCON &= 0xef; //resumes IIC operation.
Delay(10); //wait until stop condition is in effect.
return(TRUE);
}
///////////////////////////////////////////////////////////////////
// See S3C44B0X manual page 16-7 for detailed IIC Receive operation flow //
///////////////////////////////////////////////////////////////////
B8 IIC_Rx(B8 SlaveAddr, B8 Addr)
{
//* initialize
rIICCON = 0xe4; // int and ACK enable, clock setting
//* set target address
_iicMode = SETRDADDR;
_iicIndex = 0;
_iicData[0] = Addr;
rIICDS = SlaveAddr;
rIICSTAT = 0xf0; // MasterTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicIndex < 2); // wait int serv func: send word address
_iicMode = READ; // byte read
_iicIndex = 1; // read n byte(s), set to n
rIICDS = SlaveAddr;
rIICSTAT = 0xb0; // MasterRx, Start to send Slave addres
rIICCON &= 0xef; // resumes IIC operation: clear int pending bit
while(_iicIndex != -1); // waiting for int serv func
return(_iicData[0]); // not _iicData[1]
}
void __irq IIC_Serv(void)
{
B32 iicStatus, i;
iicStatus = rIICSTAT;
if (iicStatus & 0x8) {} // when bus arbitration is failed.
if (iicStatus & 0x4) {} // when a slave address is matched with IICADD
if (iicStatus & 0x2) {} // when a slave address is 0000000b
if (iicStatus & 0x1) {} // when ACK isn't received
switch(_iicMode) // global var set in main()
{
case POLLACK:
_iicStatus = iicStatus; //return status register
rIICCON &= 0xef; //resumes IIC operation.
break;
case READ:
if(_iicIndex == 0)
{ // is last byte
_iicData[_iicIndex--] = rIICDS;
rIICSTAT = 0x90; //stop MasRx condition
rIICCON &= 0xef; //resumes IIC operation.
Delay(10); //wait until stop condtion is in effect.
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicIndex--] = rIICDS;
if((_iicIndex) == 0) //The last data has to be read with no ack
rIICCON &= 0x6f; //resumes IIC operation with no ACK.
else
rIICCON &= 0xef; //resumes IIC operation with ACK
break;
case WRITE:
if(_iicIndex == 2)
{
rIICSTAT = 0xd0; //stop MasTx condition
rIICCON &= 0xef; //resumes IIC operation
_iicIndex++;
Delay(10); //wait until stop condtion is in effect.
//The pending bit will not be set after issuing stop condition.
break;
}
rIICDS = _iicData[_iicIndex++]; //_iicData[0] has dummy.
for(i = 0; i < 10; i++); //for setup time until rising edge of IICSCL
rIICCON &= 0xef; //resumes IIC operation.
break;
case SETRDADDR:
if(_iicIndex == 1)
{
_iicIndex++;
break; //IIC operation is stopped because of IICCON[4] not cleared
}
rIICDS = _iicData[_iicIndex++];
for(i = 0; i < 50; i++); //for setup time until rising edge of IICSCL
rIICCON &= 0xef; //resumes IIC operation.
break;
default:
break;
}
rI_ISPC=BIT_IIC; // clear pending bit
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -