0,0 → 1,615 |
/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** |
* File Name : 91x_i2c.c |
* Author : MCD Application Team |
* Version : V2.1 |
* Date : 12/22/2008 |
* Description : This file provides all the I2C firmware functions. |
******************************************************************************** |
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS |
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. |
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, |
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE |
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING |
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. |
*******************************************************************************/ |
|
/* Includes ------------------------------------------------------------------*/ |
#include "91x_i2c.h" |
#include "91x_scu.h" |
|
/* Private typedef -----------------------------------------------------------*/ |
/* Private define ------------------------------------------------------------*/ |
|
/* I2C IT enable */ |
#define I2C_IT_Enable 0x01 |
#define I2C_IT_Disable 0xFE |
|
/* I2C Peripheral Enable/Disable */ |
#define I2C_PE_Set 0x20 |
#define I2C_PE_Reset 0xDF |
|
/* Address direction bit */ |
#define I2C_ADD0_Set 0x01 |
#define I2C_ADD0_Reset 0xFE |
|
/* I2C START Enable/Disable */ |
#define I2C_Start_Enable 0x08 |
#define I2C_Start_Disable 0xF7 |
|
/* I2C STOP Enable/Disable */ |
#define I2C_Stop_Enable 0x02 |
#define I2C_Stop_Disable 0xFD |
|
/* I2C Masks */ |
#define I2C_Frequency_Mask 0x1F |
#define I2C_AddressHigh_Mask 0xF9 |
#define I2C_OwnAddress_Mask 0x0300 |
#define I2C_StandardMode_Mask 0x7f |
#define I2C_FastMode_Mask 0x80 |
#define I2C_Event_Mask 0x3FFF |
#define I2C_HeaderSet_Mask 0xF1 |
#define I2C_HeaderReset_Mask 0xFE |
|
/* Private macro -------------------------------------------------------------*/ |
/* Private variables ---------------------------------------------------------*/ |
/* Private function prototypes -----------------------------------------------*/ |
/* Private functions ---------------------------------------------------------*/ |
/******************************************************************************* |
* Function Name : I2C_DeInit |
* Description : Deinitializes the I2C peripheral registers to their default |
* reset values. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* Output : None |
* Return : None |
*******************************************************************************/ |
void I2C_DeInit(I2C_TypeDef* I2Cx) |
{ |
if (I2Cx == I2C0) |
{ |
/* Reset the I2C0 registers values */ |
SCU_APBPeriphReset(__I2C0, ENABLE); |
SCU_APBPeriphReset(__I2C0, DISABLE); |
} |
if (I2Cx == I2C1) |
{ |
/* Reset the I2C1 registers values */ |
SCU_APBPeriphReset(__I2C1, ENABLE); |
SCU_APBPeriphReset(__I2C1, DISABLE); |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_Init |
* Description : Initializes the I2C peripheral according to the specified |
* parameters in the I2C_InitTypeDef structure. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* |
* - I2C_InitStruct: pointer to an I2C_InitTypeDef structure that |
* contains the configuration information for the specified I2C |
* peripheral. |
* Output : None |
* Return : None |
*******************************************************************************/ |
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct) |
{ |
u16 wResult = 0x0F; |
u32 dPCLK = 25000000; |
|
/* Get PCLK frequency value */ |
dPCLK = SCU_GetPCLKFreqValue()*1000; |
/* Disable I2C peripheral to set FR[2:0] bits */ |
I2C_Cmd (I2Cx, DISABLE); |
/* Clear frequency FR[2:0] bits */ |
I2Cx->OAR2 &= I2C_Frequency_Mask; |
/* Set frequency bits depending on PCLK value */ |
if ((dPCLK <1667000) & (dPCLK > 10000000)) |
I2Cx->OAR2 |= 0x20; |
else if (dPCLK < 26670000) |
I2Cx->OAR2 |= 0x40; |
else if (dPCLK < 40000000) |
I2Cx->OAR2 |= 0x60; |
else if (dPCLK < 53330000) |
I2Cx->OAR2 |= 0x80; |
else if (dPCLK < 66000000) |
I2Cx->OAR2 |= 0xA0; |
else if (dPCLK < 80000000) |
I2Cx->OAR2 |= 0xC0; |
else if (dPCLK < 100000000) |
I2Cx->OAR2 |= 0xE0; |
I2C_Cmd (I2Cx, ENABLE); |
|
/* Configure general call */ |
if (I2C_InitStruct->I2C_GeneralCall == I2C_GeneralCall_Enable) |
{ |
/* Enable general call */ |
I2Cx->CR |= I2C_GeneralCall_Enable; |
} |
else |
{ |
/* Disable general call */ |
I2Cx->CR &= I2C_GeneralCall_Disable; |
} |
/* Configure acknowledgement */ |
if (I2C_InitStruct->I2C_Ack == I2C_Ack_Enable) |
{ |
/* Enable acknowledgement */ |
I2Cx->CR |= I2C_Ack_Enable; |
} |
else |
{ |
/* Disable acknowledgement */ |
I2Cx->CR &= I2C_Ack_Disable; |
} |
|
/* Configure LSB own address */ |
I2Cx->OAR1 = I2C_InitStruct->I2C_OwnAddress; |
/* Clear MSB own address ADD[9:8] bits */ |
I2Cx->OAR2 &= I2C_AddressHigh_Mask; |
/* Set MSB own address value */ |
I2Cx->OAR2 |= (I2C_InitStruct->I2C_OwnAddress & I2C_OwnAddress_Mask)>>7; |
|
/* Configure speed in standard mode */ |
if (I2C_InitStruct->I2C_CLKSpeed <= 100000) |
{ |
/* Standard mode speed calculate */ |
wResult = ((dPCLK/I2C_InitStruct->I2C_CLKSpeed)-7)/2; |
/* Set speed value and clear FM/SM bit for standard mode in LSB clock divider */ |
I2Cx->CCR = wResult & I2C_StandardMode_Mask; |
} |
/* Configure speed in fast mode */ |
else if (I2C_InitStruct->I2C_CLKSpeed <= 400000) |
{ |
/* Fast mode speed calculate */ |
wResult = ((dPCLK/I2C_InitStruct->I2C_CLKSpeed)-9)/3; |
/* Set speed value and set FM/SM bit for fast mode in LSB clock divider */ |
I2Cx->CCR = wResult | I2C_FastMode_Mask; |
} |
/* Set speed in MSB clock divider */ |
I2Cx->ECCR = wResult >>7; |
} |
|
/******************************************************************************* |
* Function Name : I2C_StructInit |
* Description : Initialize the I2C Init Structure parameters |
* Input : - I2C_InitStruct: pointer to an I2C_InitTypeDef structure |
which will be initialized. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct) |
{ |
/* Initialize the I2C_CLKSpeed member */ |
I2C_InitStruct->I2C_CLKSpeed = 5000; |
|
/* Initialize the I2C_OwnAddress member */ |
I2C_InitStruct->I2C_OwnAddress = 0x0; |
|
/* Initialize the I2C_GeneralCall member */ |
I2C_InitStruct->I2C_GeneralCall = I2C_GeneralCall_Disable; |
|
/* Initialize the I2C_Ack member */ |
I2C_InitStruct->I2C_Ack = I2C_Ack_Disable; |
} |
|
/******************************************************************************* |
* Function Name : I2C_Cmd |
* Description : Enables or disables the specified I2C peripheral. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - NewState: new state of the I2C peripheral. This parameter |
* can be: ENABLE or DISABLE. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState) |
{ |
if (NewState == ENABLE) |
{ |
/* Enable the I2C peripheral by setting twice the PE bit on the CR register */ |
I2Cx->CR |= I2C_PE_Set; |
I2Cx->CR |= I2C_PE_Set; |
} |
else |
{ |
/* Disable the I2C peripheral */ |
I2Cx->CR &= I2C_PE_Reset; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_GenerateSTART |
* Description : Generates I2C communication START condition. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* |
* - NewState: new state of the Start condition. This parameter |
* can be: ENABLE or DISABLE. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_GenerateStart(I2C_TypeDef* I2Cx, FunctionalState NewState) |
{ |
if (NewState == ENABLE) |
{ |
/* Generate a START condition */ |
I2Cx->CR |= I2C_Start_Enable; |
} |
else |
{ |
/* Disable the START condition generation */ |
I2Cx->CR &= I2C_Start_Disable; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_GenerateSTOP |
* Description : Generates I2C communication STOP condition. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* |
* - NewState: new state of the Stop condition. This parameter |
* can be: ENABLE or DISABLE. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState) |
{ |
if (NewState == ENABLE) |
{ |
/* Generate a SIOP condition */ |
I2Cx->CR |= I2C_Stop_Enable; |
} |
else |
{ |
/* Disable the STOP condition generation */ |
I2Cx->CR &= I2C_Stop_Disable; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_AcknowledgeConfig |
* Description : Enables or disables I2C acknowledge feature. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - NewState: new state of the Acknowledgement. This parameter |
* can be: ENABLE or DISABLE. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_AcknowledgeConfig(I2C_TypeDef *I2Cx, FunctionalState NewState) |
{ |
if (NewState == ENABLE) |
{ |
/* Enable the acknowledgement */ |
I2Cx->CR |= I2C_Ack_Enable; |
} |
else |
{ |
/* Disable the acknowledgement */ |
I2Cx->CR &= I2C_Ack_Disable; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_ITConfig |
* Description : Enables or disables I2C interrupt feature. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - NewState: new state of the specified I2C interrupt. |
* This parameter can be: ENABLE or DISABLE. |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_ITConfig(I2C_TypeDef *I2Cx, FunctionalState NewState) |
{ |
if (NewState == ENABLE) |
{ |
/* Enable the I2C interrupt */ |
I2Cx->CR |= I2C_IT_Enable; |
} |
else |
{ |
/* Disable the I2C interrupt */ |
I2Cx->CR &= I2C_IT_Disable; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_ReadRegister |
* Description : Reads any I2C register and returns its value. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - I2C_Register: the I2C register to be read. This parameter |
* can be one of the following values: |
* - I2C_CR: CR register. |
* - I2C_SR1: SR1 register. |
* - I2C_SR2: SR2 register. |
* - I2C_CCR: CCR register. |
* - I2C_OAR1: OAR1 register. |
* - I2C_OAR2: OAR2 register. |
* - I2C_DR: DR register. |
* - I2C_ECCR: ECCR register. |
* Output : None |
* Return : The value of the register passed as parameter |
*******************************************************************************/ |
u8 I2C_ReadRegister(I2C_TypeDef* I2Cx, u8 I2C_Register) |
{ |
/* Return the selected register value */ |
if (I2Cx == I2C0) |
{ |
return (*(u8 *)(I2C0_BASE + I2C_Register)); |
} |
if (I2Cx == I2C1) |
{ |
return (*(u8 *)(I2C1_BASE + I2C_Register)); |
} |
return 0; |
} |
|
/******************************************************************************* |
* Function Name : I2C_GetFlagStatus |
* Description : Checks whether the specified I2C flag is set or not. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - I2C_FLAG: flag to check. This parameter can be one of the |
* following values: |
* - I2C_FLAG_SB: Start bit flag |
* - I2C_FLAG_M_SL: Master/Slave flag |
* - I2C_FLAG_ADSL: Adress matched flag |
* - I2C_FLAG_BTF: Byte transfer finished flag |
* - I2C_FLAG_BUSY: Bus busy flag |
* - I2C_FLAG_TRA: Transmitter/Receiver flag |
* - I2C_FLAG_ADD10: 10-bit addressing in Master mode flag |
* - I2C_FLAG_EVF: Event flag |
* - I2C_FLAG_GCAL: General call flag |
* - I2C_FLAG_BERR: Bus error flag |
* - I2C_FLAG_ARLO: Arbitration lost flag |
* - I2C_FLAG_STOPF: Stop detection flag |
* - I2C_FLAG_AF: Acknowledge failure flag |
* - I2C_FLAG_ENDAD: End of address transmission flag |
* - I2C_FLAG_ACK: Acknowledge enable flag |
* Output : None |
* Return : The NewState of the I2C_Flag (SET or RESET). |
*******************************************************************************/ |
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, u16 I2C_FLAG) |
{ |
u16 wFlag1=0, wFlag2=0, wTmp=0; |
|
wFlag1 = I2Cx->SR2; |
wFlag1 = wFlag1<<8; |
wFlag2 = I2Cx->CR & 0x04; |
|
/* Get all the I2C flags in a unique register*/ |
wTmp = (((I2Cx->SR1 | (wFlag1)) & I2C_Event_Mask) | (wFlag2<<12)); |
|
/* Check the status of the specified I2C flag */ |
if((wTmp & I2C_FLAG) != RESET) |
{ |
/* Return SET if I2C_FLAG is set */ |
return SET; |
} |
else |
{ |
/* Return RESET if I2C_FLAG is reset */ |
return RESET; |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_ClearFlag |
* Description : Clears the I2C Flag passed as a parameter |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - I2C_FLAG: flag to check. This parameter can be one of the |
* following values: |
* - I2C_FLAG_SB: Start bit flag |
* - I2C_FLAG_M_SL: Master/Slave flag |
* - I2C_FLAG_ADSL: Adress matched flag |
* - I2C_FLAG_BTF: Byte transfer finished flag |
* - I2C_FLAG_BUSY: Bus busy flag |
* - I2C_FLAG_TRA: Transmitter/Receiver flag |
* - I2C_FLAG_ADD10: 10-bit addressing in Master mode flag |
* - I2C_FLAG_EVF: Event flag |
* - I2C_FLAG_GCAL: General call flag |
* - I2C_FLAG_BERR: Bus error flag |
* - I2C_FLAG_ARLO: Arbitration lost flag |
* - I2C_FLAG_STOPF: Stop detection flag |
* - I2C_FLAG_AF: Acknowledge failure flag |
* - I2C_FLAG_ENDAD: End of address transmission flag |
* - I2C_FLAG_ACK: Acknowledge enable flag |
* - parameter needed in the case that the flag to be cleared |
* need a write in one register |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_ClearFlag(I2C_TypeDef* I2Cx, u16 I2C_FLAG, ...) |
{ |
u8 bTmp = (u8)*((u32 *) & I2C_FLAG + sizeof(I2C_FLAG)); |
|
/* flags that need a read of the SR2 register to be cleared */ |
if ((I2C_FLAG==I2C_FLAG_ADD10) || (I2C_FLAG==I2C_FLAG_EVF) || (I2C_FLAG==I2C_FLAG_BERR) || (I2C_FLAG==I2C_FLAG_ARLO) | |
(I2C_FLAG==I2C_FLAG_STOPF) ||(I2C_FLAG==I2C_FLAG_AF) || (I2C_FLAG==I2C_FLAG_ENDAD)) |
{ |
/* Read the SR2 register */ |
I2Cx->SR2; |
|
/* Two flags need a second step to be cleared */ |
switch (I2C_FLAG) |
{ |
case I2C_FLAG_ADD10: |
/* Send the MSB 10bit address passed as second parameter */ |
I2Cx->DR = bTmp; |
break; |
case I2C_FLAG_ENDAD: |
/* Write to the I2C_CR register by setting PE bit */ |
I2Cx->CR |= I2C_PE_Set; |
break; |
} |
} |
|
/* flags that need a read of the SR1 register to be cleared */ |
else if (I2C_FLAG==I2C_FLAG_SB || I2C_FLAG==I2C_FLAG_ADSL || I2C_FLAG==I2C_FLAG_BTF || I2C_FLAG==I2C_FLAG_TRA) |
{ |
/* Read the SR1 register */ |
(void)I2Cx->SR1; |
|
/* three flags need a second step to be cleared */ |
if (I2C_FLAG == I2C_FLAG_SB) |
{ |
/* Send the address byte passed as second parameter */ |
I2Cx->DR = bTmp; |
} |
else if (I2C_FLAG==I2C_FLAG_BTF || I2C_FLAG==I2C_FLAG_TRA) |
{ |
/* return the received byte in the variable passed as second parameter */ |
bTmp=I2Cx->DR; |
} |
} |
|
/* flags that need to disable the I2C interface */ |
else if ( I2C_FLAG==I2C_FLAG_M_SL || I2C_FLAG==I2C_FLAG_GCAL) |
{ |
I2C_Cmd(I2Cx, DISABLE); |
I2C_Cmd(I2Cx, ENABLE); |
} |
} |
|
/******************************************************************************* |
* Function Name : I2C_Send7bitAddress |
* Description : Transmits the address byte to select the slave device. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - Address: specifies the slave address which will be transmitted |
* - Direction: specifies whether the I2C device will be a |
* Transmitter or a Receiver. This parameter can be one of the |
* following values |
* - I2C_MODE_TRANSMITTER: Transmitter mode |
* - I2C_MODE_RECEIVER: Receiver mode |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, u8 Address, u8 Direction) |
{ |
/* Test on the direction to define the read/write bit */ |
if (Direction == I2C_MODE_RECEIVER) |
{ |
/* Set the address bit0 for read */ |
Address |= I2C_ADD0_Set; |
} |
else |
{ |
/* Reset the address bit0 for write */ |
Address &= I2C_ADD0_Reset; |
} |
/* Send the address */ |
I2Cx->DR = Address; |
} |
|
/******************************************************************************* |
* Function Name : I2C_SendData |
* Description : Send a data byte. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - bData : the byte to be sent |
* Output : None |
* Return : None. |
*******************************************************************************/ |
void I2C_SendData(I2C_TypeDef* I2Cx, u8 bData) |
{ |
/* Write in the DR register the byte to be sent */ |
I2Cx->DR = bData; |
} |
|
/******************************************************************************* |
* Function Name : I2C_ReceiveData |
* Description : Read the received byte. |
* Input : - I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* Output : None |
* Return : The received byte |
*******************************************************************************/ |
u8 I2C_ReceiveData(I2C_TypeDef* I2Cx) |
{ |
/* Return from the DR register the received byte */ |
return I2Cx->DR; |
} |
|
/******************************************************************************* |
* Function Name : I2C_GetLastEvent |
* Description : Get the Last happened I2C Event. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* Output : None |
* Return : The Last happened Event. |
*******************************************************************************/ |
u16 I2C_GetLastEvent(I2C_TypeDef* I2Cx) |
{ |
u16 wFlag1=0, wFlag2 =0, wLastEvent=0; |
wFlag2 = I2Cx->SR1; |
wFlag1 = I2Cx->SR2; |
wFlag1 = wFlag1<<8; |
/* Get the last event value from I2C status register */ |
wLastEvent = ((( wFlag2 | (wFlag1)) & I2C_Event_Mask)); |
/* Return the last event */ |
return wLastEvent; |
} |
|
/******************************************************************************* |
* Function Name : I2C_CheckEvent |
* Description : Checks whether the Last I2C Event is equal to the one passed |
* as parameter. |
* Input :- I2Cx: I2C peripheral can be: |
* - I2C0 |
* - I2C1 |
* - I2C_EVENT: the event to check. This parameter can be one of |
* the following values: |
* - I2C_EVENT_SLAVE_ADDRESS_MATCHED |
* - I2C_EVENT_SLAVE_BYTE_RECEIVED |
* - I2C_EVENT_SLAVE_BYTE_TRANSMITTED |
* - I2C_EVENT_MASTER_MODE_SELECT |
* - I2C_EVENT_MASTER_MODE_SELECTED |
* - I2C_EVENT_MASTER_BYTE_RECEIVED |
* - I2C_EVENT_MASTER_BYTE_TRANSMITTED |
* - I2C_EVENT_MASTER_MODE_ADDRESS10 |
* - I2C_EVENT_SLAVE_STOP_DETECTED |
* - I2C_EVENT_SLAVE_ACK_FAILURE |
- I2C_EV31 |
* Output : None |
* Return : An ErrorStatus enumuration value: |
* - SUCCESS: Last event is equal to the I2C_Event |
* - ERROR: Last event is different from the I2C_Event |
*******************************************************************************/ |
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx,u16 I2C_EVENT) |
{ |
u16 wLastEvent = I2C_GetLastEvent(I2Cx); |
|
/* Check whther the last event is equal to I2C_EVENT */ |
if (wLastEvent == I2C_EVENT) |
{ |
/* Return SUCCESS when last event is equal to I2C_EVENT */ |
return SUCCESS; |
} |
else |
{ |
/* Return ERROR when last event is different from I2C_EVENT */ |
return ERROR; |
} |
} |
|
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ |