/*
********************************************************************************
*
* BSP_I2c.c
*
* File : BSP_I2c.c
* Version : V1.0
* Author : whq
* Mode : Thumb2
* Toolchain :
* Description : STM32F4xx I2C驱动程序
*
* History :
* Date : 2013.07.24
*******************************************************************************/
#include <string.h>
#include "misc.h"
#include "stm32f4xx_i2c.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "BSP_I2c.h"
static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);
static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);
static I2C_PARAM_TYPE I2C_PARAM[I2Cn] = {0};
static I2C_TypeDef* const I2C_NUM[I2Cn] = {
#if I2C_1_EN
BSP_I2C1,
#endif
#if I2C_2_EN
BSP_I2C2,
#endif
#if I2C_3_EN
BSP_I2C3,
#endif
};
static const uint32_t I2C_CLK[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_CLK,
#endif
#if I2C_2_EN
BSP_I2C2_CLK,
#endif
#if I2C_3_EN
BSP_I2C3_CLK,
#endif
};
static const uint32_t I2C_AF_PORT[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_AF_Port,
#endif
#if I2C_2_EN
BSP_I2C2_AF_Port,
#endif
#if I2C_3_EN
BSP_I2C3_AF_Port,
#endif
};
static const uint8_t I2C_SCL_AF_Source[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SCL_AF_Source,
#endif
#if I2C_2_EN
BSP_I2C2_SCL_AF_Source,
#endif
#if I2C_3_EN
BSP_I2C3_SCL_AF_Source,
#endif
};
static const uint8_t I2C_SDA_AF_Source[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SDA_AF_Source,
#endif
#if I2C_2_EN
BSP_I2C2_SDA_AF_Source,
#endif
#if I2C_3_EN
BSP_I2C3_SDA_AF_Source,
#endif
};
static GPIO_TypeDef* const I2C_SCL_PORT[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SCL_GPIO_PORT,
#endif
#if I2C_2_EN
BSP_I2C2_SCL_GPIO_PORT,
#endif
#if I2C_3_EN
BSP_I2C3_SCL_GPIO_PORT,
#endif
};
static const uint32_t I2C_SCL_CLK[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SCL_GPIO_CLK,
#endif
#if I2C_2_EN
BSP_I2C2_SCL_GPIO_CLK,
#endif
#if I2C_3_EN
BSP_I2C3_SCL_GPIO_CLK,
#endif
};
static const uint16_t I2C_SCL_PIN[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SCL_PIN,
#endif
#if I2C_2_EN
BSP_I2C2_SCL_PIN,
#endif
#if I2C_3_EN
BSP_I2C3_SCL_PIN,
#endif
};
static GPIO_TypeDef* const I2C_SDA_PORT[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SDA_GPIO_PORT,
#endif
#if I2C_2_EN
BSP_I2C2_SDA_GPIO_PORT,
#endif
#if I2C_3_EN
BSP_I2C3_SDA_GPIO_PORT,
#endif
};
static const uint32_t I2C_SDA_CLK[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SDA_GPIO_CLK,
#endif
#if I2C_2_EN
BSP_I2C2_SDA_GPIO_CLK,
#endif
#if I2C_3_EN
BSP_I2C3_SDA_GPIO_CLK,
#endif
};
static const uint16_t I2C_SDA_PIN[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_SDA_PIN,
#endif
#if I2C_2_EN
BSP_I2C2_SDA_PIN,
#endif
#if I2C_3_EN
BSP_I2C3_SDA_PIN,
#endif
};
static const uint32_t I2C_IRQn[I2Cn] = {
#if I2C_1_EN
BSP_I2C1_IRQn,
#endif
#if I2C_2_EN
BSP_I2C2_IRQn,
#endif
#if I2C_3_EN
BSP_I2C3_IRQn,
#endif
};
/*******************************************************************************
* Function Name : void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
* Description : 打开I2C口
* Input : I2C_x: I2C_1, I2C_2
clockSpeed: 时钟线频率
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable peripheral clocks ----------------------------------------------*/
/* Enable I2C clock */
RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], ENABLE);
/* Enable GPIOB clock */
RCC_AHB1PeriphClockCmd(I2C_SCL_CLK[I2C_x] | I2C_SDA_CLK[I2C_x], ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
I2C_DeInit(I2C_NUM[I2C_x]);
/* Connect I2C_SCL*/
GPIO_PinAFConfig(I2C_SCL_PORT[I2C_x], I2C_SCL_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);
/* Connect I2C_SDA*/
GPIO_PinAFConfig(I2C_SDA_PORT[I2C_x], I2C_SDA_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);
/* Configure I2C pins: SCL and SDA ---------------------------------------*/
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
/* DISABLE I2C event and buffer interrupt */
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
/* I2C configuration -----------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = clockSpeed;
I2C_Init(I2C_NUM[I2C_x], &I2C_InitStructure);
memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));
/* Configure and enable I2C interrupt ------------------------------------*/
NVIC_InitStructure.NVIC_IRQChannel = I2C_IRQn[I2C_x];
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable I2C ------------------------------------------------------------*/
I2C_Cmd(I2C_NUM[I2C_x], ENABLE);
}
/*******************************************************************************
* Function Name : void _I2CDelay(volatile uint32_t count)
* Description : 延迟程序
* Input :
* Output :
* Other :
* Date : 2013.08.15
*******************************************************************************/
void _I2CDelay(volatile uint32_t count)
{
for (; count > 0; count--);
}
/*******************************************************************************
* Function Name : void BSP_I2cClose(uint8_t I2C_x)
* Description : 关闭I2C口 并释放总线
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
void BSP_I2cClose(uint8_t I2C_x)
{
GPIO_InitTypeDef GPIO_InitStructure;
uint16_t i = 0;
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, DISABLE);
I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
I2C_DeInit(I2C_NUM[I2C_x]);
/* Configure I2C pins: SCL and SDA ---------------------------------------*/
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
_I2CDelay(100);
for (i = 16; i > 0; i--) //16个时钟 脉冲 释放I2C总线
{
GPIO_ResetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
_I2CDelay(100);
GPIO_SetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
_I2CDelay(100);
}
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));
}
/*******************************************************************************
* Function Name : uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
* Description : I2C向从机发送数据
* Input : I2C_x: I2C_1, I2C_2
buff: 要发送的数据
i2cSaleAddress: 从机ID号
writeAddress: 写入的地址
writeLen: 要写入的数据长度
* Output :
* Other : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
* Date : 2013.07.24
*******************************************************************************/
uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
{
if (I2C_x >= I2C_MAX)
return 0;
if (NULL == buff)
return 0;
if (0 == writeLen)
return 0;
if (0 != I2C_PARAM[I2C_x].idle)
return 0;
I2C_PARAM[I2C_x].idle = 1;
I2C_PARAM[I2C_x].id = i2cSaleAddress;
I2C_PARAM[I2C_x].addr = writeAddress;
I2C_PARAM[I2C_x].index = 0;
I2C_PARAM[I2C_x].r_w = 0;
I2C_PARAM[I2C_x].bufLen = writeLen;
I2C_PARAM[I2C_x].pBuff = buff;
I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
/* Send I2C START condition */
I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
return writeLen;
}
/*******************************************************************************
* Function Name : uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
* Description : I2C 读取数据
* Input : I2C_x: I2C_1, I2C_2
buff: 读数缓冲区
i2cSaleAddress: 从机ID号
readAddress: 读取的地址
readLen: 要读取的数据长度
* Output :
* Other : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
* Date : 2013.07.24
*******************************************************************************/
uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
{
if (I2C_x >= I2C_MAX)
return 0;
if (NULL == buff)
return 0;
if (0 == readLen)
return 0;
if (0 != I2C_PARAM[I2C_x].idle)
return 0;
I2C_PARAM[I2C_x].idle = 1;
I2C_PARAM[I2C_x].id = i2cSaleAddress;
I2C_PARAM[I2C_x].addr = readAddress;
I2C_PARAM[I2C_x].index = 0;
I2C_PARAM[I2C_x].r_w = 1;
I2C_PARAM[I2C_x].bufLen = readLen;
I2C_PARAM[I2C_x].pBuff = buff;
I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
/* Send I2C START condition */
I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
return readLen;
}
/*******************************************************************************
* Function Name : uint32_t BSP_I2cIdleState(uint8_t I2C_x)
* Description : 查询是否总线空闲 如果为空闲则读取参数
* Input : I2C_x: I2C_1, I2C_2
* Output : return: 0)空闲 1)忙碌
* Other :
* Date : 2013.07.24
*******************************************************************************/
uint32_t BSP_I2cIdleState(uint8_t I2C_x)
{
return (I2C_PARAM[I2C_x].idle || I2C_GetFlagStatus(I2C_NUM[I2C_x], I2C_FLAG_BUSY));
}
/*******************************************************************************
* Function Name : static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
* Description : 发送数据中断函数
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
{
switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
{
/* Test on I2Cx EV5 and clear it */
case I2C_EVENT_MASTER_MODE_SELECT:
I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Transmitter);
break;
/* Test on I2Cx EV6 and first EV8 and clear them */
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
/* Send the first data */
I2C_SendData(I2C_NUM[I2C_x], pParam->addr); /* EV8 just after EV6 */
break;
case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
if((pParam->index < pParam->bufLen) && (pParam->r_w == 0))
{
/* Transmit buffer data */
I2C_SendData(I2C_NUM[I2C_x], pParam->pBuff[pParam->index++]);
}
else
{
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, DISABLE);
}
break;
/* Test on I2Cx EV8 and clear it */
case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
if (pParam->r_w != 0)
{
pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cRxIRQ;
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, ENABLE);
I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
}
else
{
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
pParam->idle = 0; //接收结束标志
}
break;
}
}
/*******************************************************************************
* Function Name : static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
* Description : 接收数据中断函数
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
{
switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
{
/* Test on I2Cx EV5 and clear it */
case I2C_EVENT_MASTER_MODE_SELECT:
/* Send I2Cx slave Address for write */
I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Receiver);
break;
/* Test on I2Cx EV6 and first EV8 and clear them */
case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
if (pParam->index == (pParam->bufLen - 1))
{
I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
}
break;
/* Test on I2Cx EV2 and clear it */
case I2C_EVENT_MASTER_BYTE_RECEIVED:
pParam->pBuff[pParam->index++] = I2C_ReceiveData(I2C_NUM[I2C_x]);
if (pParam->index == (pParam->bufLen - 1))
{
I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
}
else if (pParam->index >= pParam->bufLen)
{
pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ; //默认进接收中断
I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
pParam->idle = 0;
}
break;
}
}
#if I2C_1_EN
/*******************************************************************************
* Function Name : void I2C1_EV_IRQHandler(void)
* Description : I2C1中断函数
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
void I2C1_EV_IRQHandler(void)
{
if (I2C_PARAM[I2C_1].FunCallBack)
{
I2C_PARAM[I2C_1].FunCallBack(I2C_1, &I2C_PARAM[I2C_1]);
}
}
#endif
#if I2C_2_EN
/*******************************************************************************
* Function Name : void I2C2_EV_IRQHandler(void)
* Description : I2C2中断函数
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
void I2C2_EV_IRQHandler(void)
{
if (I2C_PARAM[I2C_2].FunCallBack)
{
I2C_PARAM[I2C_2].FunCallBack(I2C_2, &I2C_PARAM[I2C_2]);
}
}
#endif
#if I2C_3_EN
/*******************************************************************************
* Function Name : void I2C3_EV_IRQHandler(void)
* Description : I2C3中断函数
* Input :
* Output :
* Other :
* Date : 2013.07.24
*******************************************************************************/
void I2C3_EV_IRQHandler(void)
{
if (I2C_PARAM[I2C_3].FunCallBack)
{
I2C_PARAM[I2C_3].FunCallBack(I2C_3, &I2C_PARAM[I2C_3]);
}
}
#endif
BSP_I2c.c