/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition
* @brief I2C handle Structure definition
* @{
*/
typedef struct __I2C_HandleTypeDef
{
I2C_TypeDef *Instance; /*!< I2C registers base address */
I2C_InitTypeDef Init; /*!< I2C communication parameters */
uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */
uint16_t XferSize; /*!< I2C transfer size */
__IO uint16_t XferCount; /*!< I2C transfer counter */
__IO uint32_t XferOptions; /*!< I2C sequantial transfer options, this parameter can
be a value of @ref I2C_XFEROPTIONS */
__IO uint32_t PreviousState; /*!< I2C communication Previous state */
HAL_StatusTypeDef(*XferISR)(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); /*!< I2C transfer IRQ handler function pointer */
DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */
HAL_LockTypeDef Lock; /*!< I2C locking object */
__IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */
__IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */
__IO uint32_t ErrorCode; /*!< I2C Error code */
__IO uint32_t AddrEventCount; /*!< I2C Address Event counter */
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Tx Transfer completed callback */
void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Rx Transfer completed callback */
void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Tx Transfer completed callback */
void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Rx Transfer completed callback */
void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Listen Complete callback */
void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Tx Transfer completed callback */
void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Rx Transfer completed callback */
void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Error callback */
void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Abort callback */
void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< I2C Slave Address Match callback */
void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp Init callback */
void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp DeInit callback */
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
} I2C_HandleTypeDef;
一 XferCount
作用和应用场景
在嵌入式系统编程,尤其是涉及到通信或数据传输的场景中,经常会有用于追踪传输进度或管理数据量的计数器。变量uint16_t XferCount;
就是这样一个计数器,它用于记录I2C传输中的数据传输数量或剩余需传输的数据包数量。以下是对其作用和应用场景的详细解释:
-
类型定义:
uint16_t
是一个无符号16位整型,常用于存储正整数值,最大值为65,535(即2^16 - 1)。这种类型的选择通常基于对计数范围的需求,确保它足够大以覆盖可能的最大数据传输量,同时又不会过度消耗存储空间。 -
XferCount:
-
初始化:在开始一个I2C传输前,
XferCount
通常会被初始化为预计要传输的数据量。例如,如果你打算通过I2C发送或接收100个字节,那么XferCount
会被设置为100。 -
传输计数:在每次数据传输完成时(例如,每次接收到一个字节或发送完一个字节后),
XferCount
的值会递减,用来跟踪还有多少数据需要处理。在中断服务例程(ISR)或DMA传输完成的回调中,通常会减少这个计数器的值。 -
传输监控与完成判断:开发人员可以通过检查
XferCount
的值来监控传输进度或判断传输是否完成。当XferCount
减至0时,表明预定的数据传输已经全部完成,这时可以执行一些收尾操作,如关闭I2C接口、更新状态标志或唤醒其他任务等。 -
灵活性与控制:这个计数器提供了对传输过程的细粒度控制,允许在传输过程中动态调整行为,比如在传输大量数据时分批处理,或者在遇到错误时快速确定剩余待处理的数据量。
-
综上所述,XferCount
作为一个简单的计数器变量,在I2C数据传输中扮演着关键角色,帮助管理数据流,确保数据的准确无误传输,并提供传输状态的实时反馈。
二 如何使用`XferCount`进行分批I2C数据传输
使用`XferCount`进行分批处理,主要是为了管理较大的数据传输,避免一次性处理大量数据可能导致的内存或性能问题,尤其是在资源有限的嵌入式系统中。下面是一个简化的示例,展示如何利用`XferCount`来实现分批发送或接收数据:
### 分批发送数据
假设你需要通过I2C发送1000个字节的数据,但决定每次只处理100字节的批次。
1. **初始化**:
uint16_t XferCount = 1000; // 总数据量
const uint8_t *pData = yourDataArray; // 指向待发送数据的指针
const uint16_t batchSize = 100; // 批次大小
2. **发送批次**:
while(XferCount > 0)
{
uint16_t currentBatchSize = MIN(batchSize, XferCount); // 计算本次实际发送的字节数
// 假设SendNextBatch是自定义函数,处理实际的I2C发送操作
if (!SendNextBatch(pData, currentBatchSize))
{
// 发送失败处理
break;
}
pData += currentBatchSize; // 移动数据指针到下一个批次的起始位置
XferCount -= currentBatchSize; // 减少剩余需发送的数据量
// 根据应用需求,可能需要在这里添加延时或检查其他条件
}
### 分批接收数据
分批接收的逻辑类似,但需要在每次接收到一批数据后更新数据缓冲区,并根据`XferCount`来决定是否继续等待接收下一批数据。
uint16_t XferCount = 1000; // 需要接收的总字节数
uint8_t *pData = yourBuffer; // 存储接收数据的缓冲区
const uint16_t batchSize = 100;
while(XferCount > 0)
{
uint16_t currentBatchSize = MIN(batchSize, XferCount);
// 假设ReceiveNextBatch是自定义函数,处理实际的I2C接收操作
if (!ReceiveNextBatch(pData, currentBatchSize))
{
// 接收失败处理
break;
}
pData += currentBatchSize; // 更新缓冲区指针
XferCount -= currentBatchSize; // 减少剩余待接收的数据量
// 可能需要的额外处理,如数据验证、处理或等待下一次接收的条件
}
在这两个示例中,`XferCount`不仅用于追踪总体传输进度,还在每个循环迭代中决定当前批次的大小,从而有效地管理了分批处理的逻辑。这种方式提高了代码的健壮性和灵活性,特别是对于大数据量的传输。