📄 i2c_ee.c
字号:
/**
******************************************************************************
* @file I2C/M24C08_EEPROM/i2c_ee.c
* @author MCD Application Team
* @version V3.0.0
* @date 04/06/2009
* @brief This file provides a set of functions needed to manage the
* communication between I2C peripheral and I2C M24C08 EEPROM.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE 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 FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2009 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "i2c_ee.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
/** @addtogroup StdPeriph_Examples
* @{
*/
/** @addtogroup I2C_M24C08_EEPROM
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/******* specified by user ************/
//#define I2C_REMAP
//#define SLAVE_10BIT_ADDRESS
/* timeout for check target's internal write procedure --> set 1s as max */
#define CHECK_TIMEOUT (1000000*one_us_unit)
#define BUS_BUSY_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define SEND_START_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define SEND_ADDR7_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define SEND_ADDR_HEADER_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define SEND_DATA_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define RECEIVE_DATA_TIMEOUT (i2c_10clk_us*one_us_unit)*100
#define WAIT_COMM_TIMEOUT
#define RECEIVE_STOP_TIMEOUT (i2c_10clk_us*one_us_unit)/5
/******* specify by user ************/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t EEPROM_ADDRESS;
static uint32_t one_us_unit=0;
static uint32_t i2c_10clk_us=0;
static __IO bool I2C_OT = FALSE;
/* Private function prototypes -----------------------------------------------*/
void GPIO_Configuration(void);
void I2C_Configuration(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Configure the used I/O ports pin
* @param None
* @retval : None
*/
void systick_isr()
{
I2C_OT = TRUE;
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
}
/* SCL SDA remaped SCL SDA
I2C1 PB.6 PB.7 PB.8 PB.9
I2C2 PB.10 PB.11
PB.ODR : ((u32 *)0x40010c0c)
<PB.0~7> @ 0x40010c0c
PB.6(I2C1.SCL) set *((u8 *)0x40010c0c) |=0x40; reset *((u8* )0x40010c0c) &= 0xbf;
PB.7(I2C1SDA) set *((u8 *)0x40010c0c) |=0x80; reset *((u8* )0x40010c0c) &= 0x7f;
<PB.9~15> @ 0x40010c0d
PB.8(remap I2C1.SCL) set *((u8 *)0x40010c0d) |=0x01; reset *((u8* )0x40010c0c) &= 0xfe;
PB.9(remap I2C1.SDA) set *((u8 *)0x40010c0d) |=0x02; reset *((u8* )0x40010c0c) &= 0xfd;
PB.10(I2C2.SCL) set *((u8 *)0x40010c0d) |=0x04; reset *((u8* )0x40010c0c) &= 0xfb;
PB.11(I2C2.SDA) set *((u8 *)0x40010c0d) |=0x08; reset *((u8* )0x40010c0c) &= 0xf7;
*/
/**
* @brief configu check the status of the line of I2C, and recove it.
* @param None
* @retval : None
*/
void SysTick_configuration(void)
{
}
/**
* @brief check the status of the line of I2C, and recover it.
* @param None
* @retval : None
*/
void I2C_Comm_Verify(I2C_TypeDef* I2Cx)
{
GPIO_InitTypeDef GPIO_InitStructure;
__IO uint32_t i=0,j=0;
__IO uint16_t tmp=0;
if (I2Cx == I2C1) /* enable I2C clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
else
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* enable GPIOB clock */
if (I2Cx == I2C1)
{
#ifdef I2C_REMAP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
#else
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
#endif
}
else {
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
}
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure); /* initiate the SCK&SDA to input */
tmp = GPIOB->IDR; /* get the status of the SCK&SDA */
if (I2Cx == I2C1)
{
#ifdef I2C_REMAP
if (!(tmp & GPIO_Pin_8) && (tmp & GPIO_Pin_9)) /* if the SCK&SDK is not High */
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; /* send 9 clocks to recover it */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
j = 9;
while(j--)
{
GPIOB->BSRR = 0x00000100; /* SCK High */
i=0xf;
while(i--); /* delay */
GPIOB->BSRR = 0x01000000; /* SCK Low */
i=0xf;
while(i--); /* delay */
}
GPIOB->BSRR = 0x00000300; /* SCK & DATA High */
}
#else
if (!(tmp & GPIO_Pin_6) && (tmp & GPIO_Pin_7)) /* if the SCK&SDK is not High */
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; /* send 9 clocks to recover it */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
j = 9;
while(j--)
{
GPIOB->BSRR = 0x00000040; /* SCK High */
i=0xf;
while(i--); /* delay */
GPIOB->BSRR = 0x00400000; /* SCK Low */
i=0xf;
while(i--); /* delay */
}
GPIOB->BSRR = 0x000000c0; /* SCK & DATA High */
}
#endif
}
else
{
if (!(tmp & GPIO_Pin_10) && (tmp & GPIO_Pin_11)) /* if the SCK&SDK is not High */
{
/* send 9 clock out using GPIO emulation */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; /* send 9 clocks to recover it */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
j = 9;
while(j--)
{
GPIOB->BSRR = 0x00000400; /* SCK High */
i=0xf;
while(i--); /* delay */
GPIOB->BSRR = 0x04000000; /* SCK Low */
i=0xf;
while(i--); /* delay */
}
GPIOB->BSRR = 0x00000c00; /* SCK & DATA High */
}
}
}
void I2C_Comm_Init(I2C_TypeDef* I2Cx, uint32_t I2CSpeed, uint16_t I2CAddr)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_ClocksTypeDef rcc_clocks;
I2C_InitTypeDef I2C_InitStructure;
uint32_t hclk;
if(I2Cx == I2C1)
{
#ifdef I2C_REMAP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
#else
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
#endif
}
else if (I2Cx == I2C2)
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10| GPIO_Pin_11;
}
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*********** I2C periphral configuration **********/
I2C_DeInit(I2Cx);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; /* fixed */
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; /* fixed */
I2C_InitStructure.I2C_OwnAddress1 = I2CAddr; /* user parameter */
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; /* fixed */
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2CSpeed; /* user parameter */
I2C_Cmd(I2Cx, ENABLE);
I2C_Init(I2Cx, &I2C_InitStructure);
/********** SysTick for timeout configuration *****/
RCC_GetClocksFreq(&rcc_clocks);
hclk = rcc_clocks.HCLK_Frequency;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
one_us_unit = hclk/1000000;
i2c_10clk_us = 1000000*10/I2CSpeed;
*(uint32_t *)0xe000e010 |= 2; //SysTick_ITConfig(ENABLE);
}
I2C_Result I2C_Comm_MasterSend(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
{
__IO uint32_t check_time = 0;
/*wait 5us min for bus free time limitation for later transaction*/
*(uint32_t *)0xe000e014 = one_us_unit*5; //SysTick_SetReload(one_us_unit*5);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!I2C_OT);
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
I2C_OT = FALSE;
/*wait bus free*/
*(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT; //SysTick_SetReload(BUS_BUSY_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
return BUS_BUSY;
}
/*send start and wait*/
I2C_GenerateSTART(I2Cx, ENABLE);
*(uint32_t *)0xe000e014 = SEND_START_TIMEOUT; //SysTick_SetReload(SEND_START_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
return SEND_START_ERR;
}
/* send 7-bit slave address and wait */
I2C_Send7bitAddress(I2Cx, (u8)(slaveaddr & 0xFF), I2C_Direction_Transmitter);
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; //SysTick_SetReload(SEND_ADDR7_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200); //wait while stop bit not cleared
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return ADDR_MATCH_ERR;
}
/* send offset if needed */
if (offset != 0xff)
{
I2C_SendData(I2Cx, offset);
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT; //SysTick_SetReload(SEND_DATA_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200); //wait while stop bit not cleared
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
}
I2C_SendData(I2Cx, *pBuffer++);
length--;
while (length--)
{
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
*(u32 *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while (((I2C_GetLastEvent(I2Cx) & 0x04) != 0x04)&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200);
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
I2C_SendData(I2Cx, *pBuffer++);
}
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while (!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200);
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -