iic_driver.c
来自「M16C瑞萨平台」· C语言 代码 · 共 484 行
C
484 行
/****************** I2C device driver *******************************************
;;; Author: Gong Liang, @EIS LAB, Lulea University of Technology, Sweden
;;; Date : 09/NOV/'2007 (FRI)
;;; Object File Name : i2cbus
;;; MCU Type : M60 62a or 62p
;;; According to the Table 17.11 Registers to Be Used and Settings in I2C Mode (1)
;;; on the datasheet of M30626HPGP page 222 to 223 to set registers!
;;; Using UART2 for IIC bus control, the MCU works under IIC master conditions
******************************************************************************************/
#include "hardware.h"
// #include "intrins.h"
#define uchar unsigned char /*宏定义*/
#define uint unsigned int
// Defines needed by this module
#define XIN_FREQ 10000000
#define I2C_BIT_RATE 100000
#define TRUE 1
#define FALSE 0
#define ACKRELEASE 0x0100
#define ACKHOLD 0x0000
#define I2CISRLEVEL 1
#define READ 0
#define WRITE 1
#define SDA2 P7.BIT.P7_0
#define SCL2 P7.BIT.P7_1
int ACK_IS_SET;
int ACK;
void AckI2C_MstAck(int);
/************ SDA2 SCL2 ---- GPIO Test ***********
PD7.BIT.PD7_0 = OUTPUT;
PD7.BIT.PD7_1 = OUTPUT;
while(1){
P7.BIT.P7_0 = HIGH;idle();P7.BIT.P7_0 = LOW; idle();
P7.BIT.P7_1 = HIGH;idle();P7.BIT.P7_1 = LOW; idle();
};
//*****************************************/
//--------------------------------------------------------------------------------------
// Name: i2c_start
// Parameters: None
// Returns: None
// Description: Generates the start condition in the i2c line
//--------------------------------------------------------------------------------------
void i2c_start(void)
{
PD7.BIT.PD7_0 = OUTPUT; // Reset SDA2 as Output Mode
SDA2 = HIGH;
SCL2 = LOW;// Put it at the first row ...
idle();
SCL2 = HIGH;
idle();
SDA2 = LOW;
idle();
SCL2 = LOW;
}
//--------------------------------------------------------------------------------------
// Name: i2c_stop
// Parameters: None
// Returns: None
// Description: Generates the stop condition in the i2c line
//--------------------------------------------------------------------------------------
void i2c_stop(void)
{
PD7.BIT.PD7_0 = OUTPUT; // Reset SDA2 as Output Mode
SCL2 = LOW;
idle();
SDA2 = LOW;
idle();
SCL2 = HIGH;
idle();
SDA2 = HIGH;
idle();
SCL2 = LOW;
}
//--------------------------------------------------------------------------------------
// Name: SendByte(uchar c)
// Parameters: uchar c
// Returns: None
// Description: Send the data( or address) C and wait for acknowledge after finishing
// sending it. Nonacknowledge sets ACK=0 and normal sending sets ACK=1.
// Notice: ACK=0 indicates the slave device may be broken.
//--------------------------------------------------------------------------------------
void SendByte(uchar c)
{
PD7.BIT.PD7_0 = OUTPUT; // Reset SDA2 as Output Mode
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*Byte length 8*/
{
SCL2 = LOW;
if((c<<BitCnt)&0x80) SDA2 = HIGH; /* MSB sending logic*/
else SDA2 = LOW;
transition(); /* Use this function to adjust the baut rate of I2C bus*/
SCL2 = HIGH; /* Set SCL2 high to inform slave of receiving sth.*/
transition(); /* Greater than 4μs*/
SCL2 = LOW;
}
//Slave ACK, use ack or nack alternatively
// transition(); // SCL2 holds low state at the 9th clock pulse
SDA2 = HIGH; // Release SDA2 for ACK after sending 8 bits
transition();
SCL2 = HIGH;
transition();
SCL2 = LOW;
// ...Check the ACK from the receiver....
// if(SDA2==1){ACK=0;} /* ACK received?*/
// else ACK= 1;
// SCL2 = LOW;
// transition();
} //End of SendByte(uchar c)
//******************************************************************************************************
// Name: TxNByte(uchar Ad_slave,uchar Ad_sub,uchar *DataBuf,uchar ByteNum)
// Parameters: Ad_slave -- The address of slave device;
// Ad_sub -- The address of slave device registers;
// *DataBuf -- The pointer to the data memory;
// ByteNum -- The number of bytes for transmission;
// Returns: None
// Description: Send multiple bytes to the slave.
//******************************************************************************************************
void TxNByte(uchar Ad_slave,uchar Ad_sub,uchar *DataBuf,uchar ByteNum){
PD7.BIT.PD7_0 = OUTPUT; // Reset SDA2 as Output Mode
uchar i;
i2c_start();
SendByte(Ad_slave);
SendByte(Ad_sub);
for(i=0;i<ByteNum;i++){
SendByte(*DataBuf);
DataBuf++;
}// Data transmission FOR loop
i2c_stop();
}
//********************************************************************************************************
//********************************************************************************************************
// Name: uchar RcvByte(void)
// Parameters: None
// Returns: The Char being received
// Description:
//********************************************************************************************************
uchar RcvByte()
{
PD7.BIT.PD7_0 = INPUT; // Set SDA2 Input Mode
uchar RetChar;
uchar BitCnt;
RetChar = 0; //Initially set to 0.
SCL2 = LOW;
// transition();
for(BitCnt=0;BitCnt<8;BitCnt++)
{
transition();
SCL2 = HIGH; /* Validate the RevData on the SDA2 line */
transition();
RetChar<<=1; /* Push each received bit toward MSB */
if(SDA2 ==1) RetChar+=1; /* Read the bit on SDA2 line*/
SCL2 = LOW;
}
// PD7.BIT.PD7_0 = OUTPUT; // Reset SDA2 as Output Mode
// AckI2C_MstAck(TRUE); //True master ACK.
return(RetChar);
}
//********************************************************************************************************
// Name: void AckI2C_MstAck(int MstAck)
// Parameters: MstAck= TRUE or FALSE
// Returns: None
// Description: Mater sends the ACK (LowLevel) or NACK(HoldHigh), working as a master-receiver.
// If master ack is needed, use the parameter TRUE. Or FALSE if not.
//********************************************************************************************************
void AckI2C_MstAck(int MstAck){
PD7.BIT.PD7_0 = OUTPUT; // Set SDA2 Output Mode
SCL2 = LOW;
if(MstAck == TRUE) SDA2 = LOW; //Master Ack
else SDA2 = HIGH; //Master Nack
transition();
SCL2 = HIGH;
transition();
SCL2 = LOW;
PD7.BIT.PD7_0 = INPUT; // Set SDA2 Input Mode
}
//*************************************************
//******************************************************************************************************
// Name: RV8564ByteWrite(uchar Ad_RV8564RW,uchar Ad_Reg,uchar RegContent)
// Parameters: Ad_RV8564RW -- The address of RV8564;
// Ad_Reg-- The address of RV8564 registers;
// RegContent -- The content written to the register;
// Returns: None
// Description: Write one specific RV8564 register.
//******************************************************************************************************
void RV8564ByteWrite(uchar Ad_RV8564RW,uchar Ad_Reg,uchar RegContent){
i2c_start();
SendByte(Ad_RV8564RW);
idle();
SendByte(Ad_Reg);
idle();
SendByte(RegContent);
idle();
i2c_stop();
}
//********************************************************************************************************
// File Local struct that contains data flow information
static struct{
unsigned char SlaveAddrMsgOne; /* Slave address to sent/receive message */
unsigned char NumOfBytesMsgOne; /* Number of bytes in message buffer */
unsigned char SlaveAddrMsgTwo; /* Slave address to sent/receive message */
unsigned char NumOfBytesMsgTwo; /* Number of bytes in message buffer */
unsigned char MsgFormat; /* What is the transfer format of the data */
unsigned char NumOfMsg; /* Total number of messages (used for combined format) */
unsigned char Bytes2Send; /* number of bytes to send in current message */
unsigned char * MsgPtr; /* pointer to current message */
unsigned char RdWrFlg : 1; /* '0' is a Read, '1' is a Write */
unsigned char Undefined : 2; /* Extras in case I need them for now */
unsigned char * MsgBufOne; /* Pointer for R/W buffer one from passed struct */
unsigned char * MsgBufTwo; /* Pointer for R/W buffer two from passed struct */
}I2CLocalStatus;
// Other misc. variables needed (GLOBAL)
struct{
unsigned char I2CBusBusy : 1; /* I2C Bus is busy */
unsigned char FailedArb : 1; /* Bus arbitration failed */
unsigned char SlaveNack : 1; /* Slave NACK'd a xmited data byte */
unsigned char Undefined : 3;
unsigned char I2CMsgComplete : 1; /* Message completed sucessfully */
}I2CGlobalStatus;
typedef struct{
unsigned char SlaveAddrMsgOne; /* Slave address to sent/receive message */
unsigned char NumOfBytesMsgOne; /* Number of bytes in message buffer */
unsigned char SlaveAddrMsgTwo; /* Slave address to sent/receive message */
unsigned char NumOfBytesMsgTwo; /* Number of bytes in message buffer */
unsigned char MsgFormat; /* What is the transfer format of the data */
unsigned char * MsgBufOne; /* Pointer for R/W buffer one from passed struct */
unsigned char * MsgBufTwo; /* Pointer for R/W buffer two from passed struct */
}I2CMessageSetup;
//--------------------------------------------------------------------------------------
/***************************************************************************************/
// Name: i2c_init -------------------------!
// Parameters: None
// Returns: None
// Description: This routine configures UART2 as i2c
/***************************************************************************************/
//--------------------------------------------------------------------------------------
void i2c_init(void)
{
asm("fclr i");
PD7.BIT.PD7_1 = OUTPUT;// SCL2 input port
PD7.BIT.PD7_0 = OUTPUT;// SDA2 input port
U2SMR.BYTE=0x01;//IICM=1 mode
U2MR.BYTE=0x00;// SMD2 to SMD0 bits in the UiMR register = 000b (Serial interface disabled).
//set the initial state for the SDA2 -------------------------!
// P7.BIT.P7_1 = HIGH;// SCL2 level
// P7.BIT.P7_0 = HIGH;// SDA2 level
//
U2BRG= 0xFF;
U2MR.BYTE=0x02;// SMD2-SMD0“010b”I2C MODE, CKDIR “0” master internal clock,IOPOL“0” no conversion-------------------------
U2C0.BYTE=0x92;//Uartform:msb,transmission/receiption at SCL falling/rising edge,SDA2 SCL2 n channel, f32
U2C1.BYTE=0x05;// enable reception and transmission
UCON.BYTE=0x00;//reset to 0.
U2SMR.BYTE=0x07;//IIC mode, BBS“0” STOP condition detected , arbitration lost by byte
U2SMR2.BYTE=0x00;//clock delayed, clock out cmos, with no data delay
U2SMR3.BYTE=0x02;//if IICM2=0(ACKint),CKPH=1, then the initial and ultimate values for CLK2 are LOW -------------------------Modified!
U2SMR4.BYTE=0x00;//clock delayed, clock out cmos, with no data delay
IFSR2A.BIT.IFSR26=1;// UART0 bus confliction detection
IFSR2A.BIT.IFSR27=1;// UART1 bus confliction detection
// U2SMR2.BIT.CSC=1;/* Clock-synchronous bit enable */
// idle();
// U2SMR2.BIT.SWC2=1;//
// idle(); idle();
// U2SMR2.BIT.SWC2=0;//*/
S2TIC.BYTE=0x04;
S2RIC.BYTE=0x04; //Set IIC_IPL=4;
BCNIC.BYTE=0x04;// 0x04;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,!!!modified!!!!!
// ABT_U2RB
asm("fset i");
}
//--------------------------------------------------------------------------------------
// ROM constants declaration - values declaration
//--------------------------------------------------------------------------------------
void i2c_restart(void)
{
U2SMR4.BYTE=0x02;// Start condition generate
idle();
U2SMR4.BYTE=0x0a;// STSP output enable
idle();
}
//--------------------------------------------------------------------------------------
// Name: i2c_enable_rx
// Parameters: None
// Returns: None
// Description: Enables the transmission of uart2
//--------------------------------------------------------------------------------------
void i2c_enable_rx(void)
{
U2C1.BIT.TE_U2C1 = 1;// TE set 1 to start
// U2C1.BYTE=U2C1.BYTE|0x05;// RE set 1 to receive enable
}
void i2c_disable_rx(void)
{
U2C1.BYTE=U2C1.BYTE&0xfe;// TE set 1 to start
U2C1.BYTE=U2C1.BYTE|0x05;// RE set 1 to receive enable
}
void I2C_WAIT_UNTIL_FINISHED(void)
{
//while(U2SMR.BIT.BBS);//IF bus busy,loop //wrong... while (U2SMR.BIT.BBS == 1);
// The bus is considered to be busy after the START
// condition. The bus is considered to be free again a certain
// time after the STOP condition. no stop, no free
// while(!U2C0.BIT.TXEPT);//Transmit end, U2C0.BIT.TXEPT=1, !U2C0.BIT.TXEPT=0
//if transmission not end, U2C0.BIT.TXEPT=0, !U2C0.BIT.TXEPT=1,loop to wait
// while(!U2C1.BIT.TI_U2C1); // wait for tx buffer to be empty
while(!ACK_IS_SET);
while(ACK);// Ack is 0 if it is ACK inter.
ACK_IS_SET=0;
// U2SMR2.BIT.SWC2= 1; //Set SCL output to low
// idle();
// U2SMR2.BIT.SWC2= 0; //SWC2 :1; /* SCL wait output bit 2
// idle();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?