[应用相关]

STM32F4XX高效驱动篇2 I2C

[复制链接]
556|9
手机看帖
扫描二维码
随时随地手机跟帖
condition|  楼主 | 2019-6-18 10:08 | 显示全部楼层 |阅读模式
说到I2C很多用过STMF10X硬件I2C方式的工程师,都感觉有点头痛。大部分还是使用软件模拟的方式,I2C由于一般的工作频率是400,100KHz。所以在平凡读取,或所读数据量大时,使用这模拟的方式,还是比较浪费CPU有效工作时间的。
         在之前的使用I2C的经历中,主要是I2C死锁问题让我也困扰了一段时间。不过后来经过多方资料,最后还是把这个问题解决了。以下驱动程序已集成了此功能。

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:08 | 显示全部楼层
什么是死锁,在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。 而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电 平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种 死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导 致I2C总线进入死锁状态。

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:09 | 显示全部楼层
解决死锁问题,我主要总结出两点:

1,连接MCU和I2C从机的复位引脚。(保证同时复位)

2,通过下图官方所述进行软件复位。
769385d0847d90262c.png

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:09 | 显示全部楼层
如果您所选的芯片符合如下时序,那么就可以使用这个驱动程序。
217175d0847ef4e727.png

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:10 | 显示全部楼层
这里对本驱动程序进行说明,主驱动程序主要使用中断的方式进行数据发送,官方列程是使用的DMA方式,在大数据量传送时使用DMA还是比较好的,这里使用中断方式,主要是为了方便操作。如果是小数据大量传送时,中断方式要更高效。

打开I2C

void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed);

关闭I2C

void BSP_I2cClose(uint8_t I2C_x);

向I2C从设备写数据

uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen);

从I2C从设备读数据

uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen);

读取I2C总线空闲状态

uint32_t BSP_I2cIdleState(uint8_t I2C_x);

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:11 | 显示全部楼层
/*
********************************************************************************
*
*                                 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

使用特权

评论回复
condition|  楼主 | 2019-6-18 10:11 | 显示全部楼层
/*
********************************************************************************
*
*                                 BSP_I2c.h
*
* File          : BSP_I2c.h
* Version       : V1.0
* Author        : whq
* Mode          : Thumb2
* Toolchain     :
* Description   : I2C驱动头文件
*               
* History       :
* Date          : 2013.07.24
*******************************************************************************/

#ifndef _BSP_I2C_H_
#define _BSP_I2C_H_

#include <stdint.h>

#define I2C_1_EN                        1   
#define I2C_2_EN                        1
#define I2C_3_EN                        1

#if !(I2C_1_EN || I2C_2_EN ||I2C_3_EN)
#error  "请至少打开一路I2C"
#endif

typedef enum {
#if I2C_1_EN
    I2C_1,
#endif
#if I2C_2_EN
    I2C_2,
#endif
#if I2C_3_EN
    I2C_3,
#endif
    I2C_MAX
}I2C_ENUM;

#define I2Cn                            I2C_MAX
#define I2C_1_0                         //无映射:I2C_1_0,映射1:I2C_1_1
#define I2C_2_0
#define I2C_3_0                         //无映射:I2C_3_0,映射1:I2C_3_1

#define I2C_SLAVE_ADDRESS                   0x30        //本STM32芯片地址


/******************************类型声明****************************************/

typedef struct {
    volatile uint8_t idle;    //空闲标志  0)空闲   1)忙碌
    uint8_t r_w;              //读写标志  0)写     1)读
    uint8_t id;               //从机设备ID号
    uint8_t addr;             //要读写的地址
    volatile uint16_t index;  //当前缓冲区数据长度
    uint16_t bufLen;          //要发送或接收的数据长度   
    uint8_t * volatile pBuff; //缓冲区首地址   
    void (* volatile FunCallBack)(uint8_t, void *);//中断回调函数
}I2C_PARAM_TYPE;

/******************************************************************************/


/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  I2C1 Interface pins
  */  
#define BSP_I2C1                            I2C1
#define BSP_I2C1_CLK                        RCC_APB1Periph_I2C1
#define BSP_I2C1_AF_Port                    GPIO_AF_I2C1
#define BSP_I2C1_IRQn                       I2C1_EV_IRQn

#if defined(I2C_1_2)                        //自由组合区
#define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
#define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
#define BSP_I2C1_SCL_GPIO_PORT              GPIOB
#define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

#define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
#define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
#define BSP_I2C1_SDA_GPIO_PORT              GPIOB
#define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB

#elif defined(I2C_1_1)
#define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
#define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
#define BSP_I2C1_SCL_GPIO_PORT              GPIOB
#define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

#define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
#define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
#define BSP_I2C1_SDA_GPIO_PORT              GPIOB
#define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB

#else
#define BSP_I2C1_SCL_AF_Source              GPIO_PinSource6
#define BSP_I2C1_SCL_PIN                    GPIO_Pin_6
#define BSP_I2C1_SCL_GPIO_PORT              GPIOB
#define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

#define BSP_I2C1_SDA_AF_Source              GPIO_PinSource7
#define BSP_I2C1_SDA_PIN                    GPIO_Pin_7
#define BSP_I2C1_SDA_GPIO_PORT              GPIOB
#define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
#endif

/**
  * @brief  I2C2 Interface pins
  */  
#define BSP_I2C2                            I2C2
#define BSP_I2C2_CLK                        RCC_APB1Periph_I2C2
#define BSP_I2C2_AF_Port                    GPIO_AF_I2C2
#define BSP_I2C2_IRQn                       I2C2_EV_IRQn

#if defined(I2C_2_3)                        //自由组合区
#define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
#define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
#define BSP_I2C2_SCL_GPIO_PORT              GPIOH
#define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

#define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
#define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
#define BSP_I2C2_SDA_GPIO_PORT              GPIOH
#define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

#elif defined(I2C_2_2)
#define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
#define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
#define BSP_I2C2_SCL_GPIO_PORT              GPIOH
#define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

#define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
#define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
#define BSP_I2C2_SDA_GPIO_PORT              GPIOH
#define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

#elif defined(I2C_2_1)
#define BSP_I2C2_SCL_AF_Source              GPIO_PinSource1
#define BSP_I2C2_SCL_PIN                    GPIO_Pin_1
#define BSP_I2C2_SCL_GPIO_PORT              GPIOF
#define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOF

#define BSP_I2C2_SDA_AF_Source              GPIO_PinSource0
#define BSP_I2C2_SDA_PIN                    GPIO_Pin_0
#define BSP_I2C2_SDA_GPIO_PORT              GPIOF
#define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOF

#else
#define BSP_I2C2_SCL_AF_Source              GPIO_PinSource10
#define BSP_I2C2_SCL_PIN                    GPIO_Pin_10
#define BSP_I2C2_SCL_GPIO_PORT              GPIOB
#define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

#define BSP_I2C2_SDA_AF_Source              GPIO_PinSource11
#define BSP_I2C2_SDA_PIN                    GPIO_Pin_11
#define BSP_I2C2_SDA_GPIO_PORT              GPIOB
#define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
#endif

/**
  * @brief  I2C3 Interface pins
  */  
#define BSP_I2C3                            I2C3
#define BSP_I2C3_CLK                        RCC_APB1Periph_I2C3
#define BSP_I2C3_AF_Port                    GPIO_AF_I2C3
#define BSP_I2C3_IRQn                       I2C3_EV_IRQn

#if defined(I2C_3_2)                        //自由组合区
#define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
#define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
#define BSP_I2C3_SCL_GPIO_PORT              GPIOA
#define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA

#define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
#define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
#define BSP_I2C3_SDA_GPIO_PORT              GPIOH
#define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

#elif defined(I2C_3_1)
#define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
#define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
#define BSP_I2C3_SCL_GPIO_PORT              GPIOA
#define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA

#define BSP_I2C3_SDA_AF_Source              GPIO_PinSource9
#define BSP_I2C3_SDA_PIN                    GPIO_Pin_9
#define BSP_I2C3_SDA_GPIO_PORT              GPIOC
#define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOC

#else
#define BSP_I2C3_SCL_AF_Source              GPIO_PinSource7
#define BSP_I2C3_SCL_PIN                    GPIO_Pin_7
#define BSP_I2C3_SCL_GPIO_PORT              GPIOH
#define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

#define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
#define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
#define BSP_I2C3_SDA_GPIO_PORT              GPIOH
#define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
#endif



/******************************函数声明****************************************/
void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed);
void BSP_I2cClose(uint8_t I2C_x);
uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen);
uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen);
uint32_t BSP_I2cIdleState(uint8_t I2C_x);



#endif

BSP_I2c.h

使用特权

评论回复
heimaojingzhang| | 2019-7-8 11:15 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
keaibukelian| | 2019-7-8 11:27 | 显示全部楼层
感谢楼主分享啊

使用特权

评论回复
labasi| | 2019-7-8 11:30 | 显示全部楼层

非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

256

帖子

1

粉丝