1202 lines
31 KiB
C
1202 lines
31 KiB
C
|
/*
|
||
|
******************************************************************************
|
||
|
* @file driver_i2c.c
|
||
|
* @author FreqChip Firmware Team
|
||
|
* @version V1.0.0
|
||
|
* @date 2021
|
||
|
* @brief I2C module driver.
|
||
|
* This file provides firmware functions to manage the
|
||
|
* Inter-Integrated Circuit bus (I2C) peripheral
|
||
|
******************************************************************************
|
||
|
* @attention
|
||
|
*
|
||
|
* Copyright (c) 2021 FreqChip.
|
||
|
* All rights reserved.
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
#include "fr30xx.h"
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_IRQHandler
|
||
|
*
|
||
|
* @brief Handle I2C interrupt request.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
void i2c_IRQHandler(I2C_HandleTypeDef *hi2c)
|
||
|
{
|
||
|
/* Is INT_TX_ABRT enable */
|
||
|
if (i2c_is_int_enable(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
hi2c->b_RxBusy = false;
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
i2c_int_disable(hi2c, INT_RX_FULL);
|
||
|
i2c_int_disable(hi2c, INT_TX_ABRT);
|
||
|
i2c_int_disable(hi2c, INT_TX_EMPTY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Master */
|
||
|
if (hi2c->Init.I2C_Mode & I2C_MASK_MASTER)
|
||
|
{
|
||
|
/* Is INT_TX_EMPTY enabled */
|
||
|
if (i2c_is_int_enable(hi2c, INT_TX_EMPTY))
|
||
|
{
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_EMPTY))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_EMPTY);
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
if (hi2c->u32_TxCount < hi2c->u32_TxSize)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++] | CMD_STOP;
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_TX_EMPTY);
|
||
|
i2c_int_disable(hi2c, INT_TX_ABRT);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_TX_EMPTY);
|
||
|
i2c_int_disable(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Is INT_RX_FULL enabled */
|
||
|
if (i2c_is_int_enable(hi2c, INT_RX_FULL))
|
||
|
{
|
||
|
if (i2c_get_int_status(hi2c, INT_RX_FULL))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_RX_FULL);
|
||
|
|
||
|
while (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->p_RxData[hi2c->u32_RxCount++] = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
if (hi2c->u32_RxCount >= hi2c->u32_RxSize)
|
||
|
{
|
||
|
hi2c->b_RxBusy = false;
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_RX_FULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while ((!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx)) && hi2c->b_TxBusy == true)
|
||
|
{
|
||
|
if (hi2c->u32_TxCount < hi2c->u32_RxSize - 1)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ;
|
||
|
|
||
|
hi2c->u32_TxCount++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ | CMD_STOP;
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/* Slave */
|
||
|
else
|
||
|
{
|
||
|
/* Is INT_RD_REQ enabled */
|
||
|
if(i2c_is_int_enable(hi2c, INT_RD_REQ))
|
||
|
{
|
||
|
if(i2c_get_int_status(hi2c, INT_RD_REQ))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_RD_REQ);
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_RD_REQ);
|
||
|
|
||
|
while(!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
if(hi2c->u32_TxCount < hi2c->u32_TxSize)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(hi2c->u32_TxCount < hi2c->u32_TxSize)
|
||
|
{
|
||
|
i2c_int_enable(hi2c, INT_TX_EMPTY);
|
||
|
i2c_int_enable(hi2c, INT_TX_ABRT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Is INT_TX_EMPTY enabled */
|
||
|
if (i2c_is_int_enable(hi2c, INT_TX_EMPTY))
|
||
|
{
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_EMPTY))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_EMPTY);
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
if (hi2c->u32_TxCount < hi2c->u32_TxSize)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_TX_EMPTY);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
i2c_int_disable(hi2c, INT_TX_EMPTY);
|
||
|
i2c_int_disable(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Is INT_RX_FULL enabled */
|
||
|
if (i2c_is_int_enable(hi2c, INT_RX_FULL))
|
||
|
{
|
||
|
if (i2c_get_int_status(hi2c, INT_RX_FULL))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_RX_FULL);
|
||
|
|
||
|
while (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->p_RxData[hi2c->u32_RxCount++] = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
if (hi2c->u32_RxCount >= hi2c->u32_RxSize)
|
||
|
{
|
||
|
hi2c->b_RxBusy = false;
|
||
|
|
||
|
i2c_int_disable(hi2c, INT_RX_FULL);
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_init
|
||
|
*
|
||
|
* @brief Initialize the I2C according to the specified parameters in the struct_I2CInit_t
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
void i2c_init(I2C_HandleTypeDef *hi2c)
|
||
|
{
|
||
|
uint32_t lu32_TempValue;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
/* Master */
|
||
|
if (hi2c->Init.I2C_Mode & I2C_MASK_MASTER)
|
||
|
{
|
||
|
hi2c->I2Cx->CTRL.SLAVE_DISABLE = 1;
|
||
|
hi2c->I2Cx->CTRL.MASTER_MODE = 1;
|
||
|
hi2c->I2Cx->CTRL.SPEED = 2;
|
||
|
|
||
|
hi2c->I2Cx->TAR.ADDR_MASTER_10BIT = (hi2c->Init.I2C_Mode & I2C_MASK_10BIT) ? 1 : 0;
|
||
|
hi2c->I2Cx->TAR.SPECIAL = 0;
|
||
|
hi2c->I2Cx->TAR.DEVICE_ID = 0;
|
||
|
}
|
||
|
/* Slave */
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->CTRL.SLAVE_DISABLE = 0;
|
||
|
hi2c->I2Cx->CTRL.MASTER_MODE = 0;
|
||
|
hi2c->I2Cx->CTRL.SPEED = 2;
|
||
|
|
||
|
hi2c->I2Cx->CTRL.ADDR_SLAVE_10BIT = (hi2c->Init.I2C_Mode & I2C_MASK_10BIT) ? 1 : 0;
|
||
|
|
||
|
hi2c->I2Cx->SAR = hi2c->Init.Slave_Address >> 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Rate config */
|
||
|
if (hi2c->Init.I2C_Mode & I2C_MASK_MASTER)
|
||
|
{
|
||
|
/* SCL_HCNT Minimum limit */
|
||
|
if (hi2c->Init.SCL_HCNT < 6)
|
||
|
{
|
||
|
hi2c->I2Cx->FS_SCL_HCNT = 6;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->FS_SCL_HCNT = hi2c->Init.SCL_HCNT;
|
||
|
}
|
||
|
/* SCL_LCNT Minimum limit */
|
||
|
if (hi2c->Init.SCL_LCNT < 8)
|
||
|
{
|
||
|
hi2c->I2Cx->FS_SCL_LCNT = 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->FS_SCL_LCNT = hi2c->Init.SCL_LCNT;
|
||
|
}
|
||
|
|
||
|
|
||
|
lu32_TempValue = hi2c->Init.SCL_LCNT / 2;
|
||
|
|
||
|
if (lu32_TempValue > 0xFF)
|
||
|
{
|
||
|
hi2c->I2Cx->SDA_SETUP = 0xFF;
|
||
|
hi2c->I2Cx->SDA_HOLD.SDA_TX_HOLD = hi2c->Init.SCL_LCNT - 0xFF;
|
||
|
|
||
|
/* Maximum limit */
|
||
|
if (hi2c->Init.SCL_LCNT - 0xFF > 0xFFFF)
|
||
|
{
|
||
|
hi2c->I2Cx->SDA_HOLD.SDA_TX_HOLD = 0xFFFF;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->SDA_SETUP = lu32_TempValue;
|
||
|
/* Minimum limit */
|
||
|
if (lu32_TempValue < 8)
|
||
|
{
|
||
|
hi2c->I2Cx->SDA_SETUP = 8;
|
||
|
}
|
||
|
|
||
|
hi2c->I2Cx->SDA_HOLD.SDA_TX_HOLD = lu32_TempValue;
|
||
|
/* Minimum limit */
|
||
|
if (lu32_TempValue < 5)
|
||
|
{
|
||
|
hi2c->I2Cx->SDA_HOLD.SDA_TX_HOLD = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->FS_SCL_HCNT = 6;
|
||
|
hi2c->I2Cx->FS_SCL_LCNT = 8;
|
||
|
|
||
|
hi2c->I2Cx->SDA_SETUP = 8;
|
||
|
hi2c->I2Cx->SDA_HOLD.SDA_TX_HOLD = 1;
|
||
|
}
|
||
|
/* Rate config end */
|
||
|
|
||
|
|
||
|
/* Default configuration */
|
||
|
hi2c->I2Cx->CTRL.STOP_DET_IF_MASTER_ACTIVE = 1;
|
||
|
hi2c->I2Cx->CTRL.STOP_DET_IF_ADDR_ESSED = 1;
|
||
|
hi2c->I2Cx->CTRL.RX_FIFO_FULL_HLD_CTRL = 1;
|
||
|
hi2c->I2Cx->CTRL.TX_EMPTY_CTRL = 1;
|
||
|
hi2c->I2Cx->CTRL.RESTART_EN = 1;
|
||
|
/* nonblocking */
|
||
|
hi2c->I2Cx->ENABLE.TX_CMD_BLOCK = 0;
|
||
|
/* Disable all interrupt */
|
||
|
hi2c->I2Cx->INT_MASK = 0;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_master_transmit
|
||
|
*
|
||
|
* @brief master send an amount of data in blocking mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_master_transmit(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
while (fu32_Size - 1)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++ | CMD_STOP;
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
while (__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_master_receive
|
||
|
*
|
||
|
* @brief master receive an amount of data in blocking mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_master_receive(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
uint32_t lu32_RxCount = fu32_Size;
|
||
|
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
while (fu32_Size - 1)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ | CMD_STOP;
|
||
|
|
||
|
while (lu32_RxCount)
|
||
|
{
|
||
|
if (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_master_transmit_IT
|
||
|
*
|
||
|
* @brief master send an amount of data in interrupt mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_master_transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0) return false;
|
||
|
if (hi2c->b_TxBusy) return false;
|
||
|
if (hi2c->b_RxBusy) return false;
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_TxFIFO_THRESHOLD_LEVEL(hi2c->I2Cx, 16);
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->u32_TxSize = fu32_Size - 1;
|
||
|
hi2c->u32_TxCount = 0;
|
||
|
hi2c->p_TxData = fp_Data;
|
||
|
hi2c->b_TxBusy = true;
|
||
|
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
i2c_clear_int_status(hi2c, INT_TX_EMPTY);
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
if (hi2c->u32_TxCount < hi2c->u32_TxSize)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = hi2c->p_TxData[hi2c->u32_TxCount++] | CMD_STOP;
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while(__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
|
||
|
/* DevAddress NACK */
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->b_TxBusy = false;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
i2c_int_enable(hi2c, INT_TX_EMPTY);
|
||
|
i2c_int_enable(hi2c, INT_TX_ABRT);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_master_receive_IT
|
||
|
*
|
||
|
* @brief master receive an amount of data in interrupt mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_master_receive_IT(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0) return false;
|
||
|
if (hi2c->b_TxBusy) return false;
|
||
|
if (hi2c->b_RxBusy) return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_RxFIFO_THRESHOLD_LEVEL(hi2c->I2Cx, 0);
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->u32_RxSize = fu32_Size;
|
||
|
hi2c->u32_RxCount = 0;
|
||
|
hi2c->u32_TxCount = 0;
|
||
|
hi2c->p_RxData = fp_Data;
|
||
|
hi2c->b_RxBusy = true;
|
||
|
hi2c->b_TxBusy = true;
|
||
|
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
i2c_clear_int_status(hi2c, INT_RX_FULL);
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
if (hi2c->u32_TxCount < hi2c->u32_RxSize - 1)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ;
|
||
|
|
||
|
hi2c->u32_TxCount++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ | CMD_STOP;
|
||
|
hi2c->b_TxBusy = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->b_RxBusy = false;
|
||
|
hi2c->b_TxBusy = false;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
i2c_int_enable(hi2c, INT_RX_FULL);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_slave_transmit
|
||
|
*
|
||
|
* @brief slave send an amount of data in blocking mode..
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_slave_transmit(I2C_HandleTypeDef *hi2c, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
while(!(i2c_get_int_status(hi2c, INT_RD_REQ)));
|
||
|
i2c_clear_int_status(hi2c, INT_RD_REQ);
|
||
|
|
||
|
while (fu32_Size)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_slave_receive
|
||
|
*
|
||
|
* @brief slave receive an amount of data in blocking mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_slave_receive(I2C_HandleTypeDef *hi2c, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
while (fu32_Size)
|
||
|
{
|
||
|
if (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_slave_transmit_IT
|
||
|
*
|
||
|
* @brief slave send an amount of data in interrupt mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_slave_transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0) return false;
|
||
|
if (hi2c->b_TxBusy) return false;
|
||
|
if (hi2c->b_RxBusy) return false;
|
||
|
|
||
|
__I2C_TxFIFO_THRESHOLD_LEVEL(hi2c->I2Cx, 16);
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->u32_TxSize = fu32_Size;
|
||
|
hi2c->u32_TxCount = 0;
|
||
|
hi2c->p_TxData = fp_Data;
|
||
|
hi2c->b_TxBusy = true;
|
||
|
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
i2c_clear_int_status(hi2c, INT_TX_EMPTY);
|
||
|
i2c_clear_int_status(hi2c, INT_RD_REQ);
|
||
|
|
||
|
i2c_int_enable(hi2c,INT_RD_REQ);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_slave_receive_IT
|
||
|
*
|
||
|
* @brief slave receive an amount of data in interrupt mode.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
*/
|
||
|
bool i2c_slave_receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0) return false;
|
||
|
if (hi2c->b_TxBusy) return false;
|
||
|
if (hi2c->b_RxBusy) return false;
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
i2c_clear_int_status(hi2c, INT_RX_FULL);
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
__I2C_RxFIFO_THRESHOLD_LEVEL(hi2c->I2Cx, 0);
|
||
|
|
||
|
hi2c->u32_RxSize = fu32_Size;
|
||
|
hi2c->u32_RxCount = 0;
|
||
|
hi2c->p_RxData = fp_Data;
|
||
|
hi2c->b_RxBusy = true;
|
||
|
|
||
|
i2c_int_enable(hi2c, INT_RX_FULL);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_memory_write
|
||
|
*
|
||
|
* @brief i2c memory write.
|
||
|
*/
|
||
|
bool i2c_memory_write(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint16_t fu16_MemAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
//hi2c->I2Cx->DATA_CMD = (fu16_MemAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu16_MemAddress & 0xFF;
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
|
||
|
/* DevAddress NACK */
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
//printf("ack:%x %x\r\n",fu16_DevAddress,(fu16_DevAddress>>1));
|
||
|
while (fu32_Size - 1)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++ | CMD_STOP;
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
while(i2c_memory_is_busy(hi2c, fu16_DevAddress));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_sensor_write
|
||
|
*
|
||
|
* @brief i2c sensor write, fu8_AddressLength: The value can be 8, 16, or 32.
|
||
|
*/
|
||
|
bool i2c_sensor_write(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint32_t fu32_RegAddress, uint8_t fu8_AddressLength, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
if(fu8_AddressLength == 8)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
else if(fu8_AddressLength == 16)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 24) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 16) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
|
||
|
while (fu32_Size - 1)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = *fp_Data++ | CMD_STOP;
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
while(i2c_memory_is_busy(hi2c, fu16_DevAddress));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_memory_read
|
||
|
*
|
||
|
* @brief i2c memory read.
|
||
|
*/
|
||
|
bool i2c_memory_read(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint16_t fu16_MemAddress, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
uint32_t lu32_RxCount = fu32_Size;
|
||
|
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
// hi2c->I2Cx->DATA_CMD = (fu16_MemAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu16_MemAddress & 0xFF;
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
|
||
|
/* DevAddress NACK */
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (fu32_Size > 1)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_RESTART | CMD_READ;
|
||
|
|
||
|
while (fu32_Size - 2)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ | CMD_STOP;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_RESTART | CMD_READ | CMD_STOP;
|
||
|
}
|
||
|
|
||
|
while (lu32_RxCount)
|
||
|
{
|
||
|
if (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_sensor_read
|
||
|
*
|
||
|
* @brief i2c sensor read, fu8_AddressLength: The value can be 8, 16, or 32.
|
||
|
*/
|
||
|
bool i2c_sensor_read(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress, uint32_t fu32_RegAddress, uint8_t fu8_AddressLength, uint8_t *fp_Data, uint32_t fu32_Size)
|
||
|
{
|
||
|
uint32_t lu32_RxCount = fu32_Size;
|
||
|
|
||
|
if (fu32_Size == 0)
|
||
|
return false;
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
if(fu8_AddressLength == 8)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
else if(fu8_AddressLength == 16)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 24) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 16) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = (fu32_RegAddress >> 8) & 0xFF;
|
||
|
hi2c->I2Cx->DATA_CMD = fu32_RegAddress & 0xFF;
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
|
||
|
if (fu32_Size > 1)
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_RESTART | CMD_READ;
|
||
|
|
||
|
while (fu32_Size - 2)
|
||
|
{
|
||
|
if (!__I2C_IS_TxFIFO_FULL(hi2c->I2Cx))
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ;
|
||
|
|
||
|
fu32_Size--;
|
||
|
}
|
||
|
|
||
|
while (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Last byte with stop */
|
||
|
while (__I2C_IS_TxFIFO_FULL(hi2c->I2Cx));
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_READ | CMD_STOP;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hi2c->I2Cx->DATA_CMD = CMD_RESTART | CMD_READ | CMD_STOP;
|
||
|
}
|
||
|
|
||
|
while(__I2C_IS_BUSY(hi2c->I2Cx));
|
||
|
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
while (lu32_RxCount)
|
||
|
{
|
||
|
if (!__I2C_IS_RxFIFO_EMPTY(hi2c->I2Cx))
|
||
|
{
|
||
|
*fp_Data++ = hi2c->I2Cx->DATA_CMD & 0xFF;
|
||
|
|
||
|
lu32_RxCount--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_memory_is_busy
|
||
|
*
|
||
|
* @brief i2c memory is busy.
|
||
|
*/
|
||
|
bool i2c_memory_is_busy(I2C_HandleTypeDef *hi2c, uint16_t fu16_DevAddress)
|
||
|
{
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->TAR.TAR = fu16_DevAddress >> 1;
|
||
|
|
||
|
__I2C_ENABLE(hi2c->I2Cx);
|
||
|
|
||
|
hi2c->I2Cx->DATA_CMD = 0x00;
|
||
|
hi2c->I2Cx->DATA_CMD = 0x00 | CMD_STOP;
|
||
|
|
||
|
while (!__I2C_IS_TxFIFO_EMPTY(hi2c->I2Cx));
|
||
|
|
||
|
/* DevAddress NACK */
|
||
|
if (i2c_get_int_status(hi2c, INT_TX_ABRT))
|
||
|
{
|
||
|
i2c_clear_int_status(hi2c, INT_TX_ABRT);
|
||
|
|
||
|
__I2C_DISABLE(hi2c->I2Cx);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_int_enable
|
||
|
*
|
||
|
* @brief I2C interrupt enable.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
* fe_INT_Index: interrupt index.
|
||
|
*/
|
||
|
void i2c_int_enable(I2C_HandleTypeDef *hi2c, enum_INT_Index_t fe_INT_Index)
|
||
|
{
|
||
|
hi2c->I2Cx->INT_MASK |= fe_INT_Index;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_int_disable
|
||
|
*
|
||
|
* @brief I2C interrupt disable.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
* fe_INT_Index: interrupt index.
|
||
|
*/
|
||
|
void i2c_int_disable(I2C_HandleTypeDef *hi2c, enum_INT_Index_t fe_INT_Index)
|
||
|
{
|
||
|
hi2c->I2Cx->INT_MASK &= ~fe_INT_Index;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_is_int_enable
|
||
|
*
|
||
|
* @brief Is I2C interrupt enable.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
* fe_INT_Index: interrupt index.
|
||
|
*/
|
||
|
bool i2c_is_int_enable(I2C_HandleTypeDef *hi2c, enum_INT_Index_t fe_INT_Index)
|
||
|
{
|
||
|
return (hi2c->I2Cx->INT_MASK & fe_INT_Index) ? true : false;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_get_int_status
|
||
|
*
|
||
|
* @brief I2C interrupt Status.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
* fe_INT_Index: interrupt index.
|
||
|
*/
|
||
|
bool i2c_get_int_status(I2C_HandleTypeDef *hi2c, enum_INT_Index_t fe_INT_Index)
|
||
|
{
|
||
|
bool lb_Status = (hi2c->I2Cx->RAW_INT_STAT & fe_INT_Index) ? true : false;
|
||
|
|
||
|
return lb_Status;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn i2c_clear_int_status
|
||
|
*
|
||
|
* @brief I2C interrupt status clear.
|
||
|
*
|
||
|
* @param hi2c: I2C handle.
|
||
|
* fe_INT_Index: interrupt index.
|
||
|
*/
|
||
|
void i2c_clear_int_status(I2C_HandleTypeDef *hi2c, enum_INT_Index_t fe_INT_Index)
|
||
|
{
|
||
|
volatile uint32_t lu32_Temp;
|
||
|
|
||
|
switch (fe_INT_Index)
|
||
|
{
|
||
|
case INT_RX_UNDER: lu32_Temp = hi2c->I2Cx->CLR_RX_UNDER; break;
|
||
|
case INT_RX_OVER: lu32_Temp = hi2c->I2Cx->CLR_RX_OVER; break;
|
||
|
case INT_TX_OVER: lu32_Temp = hi2c->I2Cx->CLR_TX_OVER; break;
|
||
|
case INT_RD_REQ: lu32_Temp = hi2c->I2Cx->CLR_RD_REQ; break;
|
||
|
case INT_TX_ABRT: lu32_Temp = hi2c->I2Cx->CLR_TX_ABRT; break;
|
||
|
case INT_RX_DONE: lu32_Temp = hi2c->I2Cx->CLR_RX_DONE; break;
|
||
|
case INT_ACTIVITY: lu32_Temp = hi2c->I2Cx->CLR_ACTIVITY; break;
|
||
|
case INT_STOP_DET: lu32_Temp = hi2c->I2Cx->CLR_STOP_DET; break;
|
||
|
case INT_START_DET: lu32_Temp = hi2c->I2Cx->CLR_START_DET; break;
|
||
|
case INT_RESTART_DET: lu32_Temp = hi2c->I2Cx->CLR_RESTART_DET; break;
|
||
|
case INT_SCL_STUCK_AT_LOW: lu32_Temp = hi2c->I2Cx->CLR_SCL_STUCK_DET; break;
|
||
|
|
||
|
default: break;
|
||
|
}
|
||
|
}
|