我正在使用STM32F4并希望与LSM303加速度计通信。为此,我使用I2C,仅使用I2C时一切正常,但当我尝试将DMA与之结合使用时,它停止工作。
当我使用HAL_I2C_Master_Transmit_DMA时,它可以工作并成功获得IRQHandler。但是,在此之后,当我想要使用HAL_I2C_Master_Receive_DMA时,它显示I2C状态不可用...
我读到了STM32FX的I2C有点混乱,但我不明白为什么不使用DMA时一切正常。
还有,当它触发Master_Transmit_DMA的回调函数I2C_DMAXferCplt时,它显示I2C_HandleTypeDef的CurrentState仍然等于HAL_I2C_STATE_BUSY_TX,因此它不会将状态设置回READY。这就是为什么在我调用Master_Receive_DMA时它无法接收任何数据。
以下是我的I2C初始化代码:
当我使用HAL_I2C_Master_Transmit_DMA时,它可以工作并成功获得IRQHandler。但是,在此之后,当我想要使用HAL_I2C_Master_Receive_DMA时,它显示I2C状态不可用...
我读到了STM32FX的I2C有点混乱,但我不明白为什么不使用DMA时一切正常。
还有,当它触发Master_Transmit_DMA的回调函数I2C_DMAXferCplt时,它显示I2C_HandleTypeDef的CurrentState仍然等于HAL_I2C_STATE_BUSY_TX,因此它不会将状态设置回READY。这就是为什么在我调用Master_Receive_DMA时它无法接收任何数据。
以下是我的I2C初始化代码:
void MX_I2C2_Init(void)
{
I2C_ST_INS.Instance = I2C2;
I2C_ST_INS.Init.ClockSpeed = 400000;
I2C_ST_INS.Init.DutyCycle = I2C_DUTYCYCLE_2;
I2C_ST_INS.Init.OwnAddress1 = 0;
I2C_ST_INS.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2C_ST_INS.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
I2C_ST_INS.Init.OwnAddress2 = 0;
I2C_ST_INS.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
I2C_ST_INS.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
HAL_I2C_Init(&I2C_ST_INS);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(i2cHandle->Instance==I2C1)
{
//Not useful for this post
}
else if(i2cHandle->Instance==I2C2)
{
GPIO_InitStruct.Pin = MASTER_IMUB_I2C_SDA_Pin|MASTER_IMUB_I2C_SCL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
__HAL_RCC_I2C2_CLK_ENABLE();
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_i2c2_rx.Instance = DMA1_Stream2;
hdma_i2c2_rx.Init.Channel = DMA_CHANNEL_7;
hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_rx.Init.Mode = DMA_NORMAL;
hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_i2c2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_i2c2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2c2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx);
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
hdma_i2c2_tx.Instance = DMA1_Stream7;
hdma_i2c2_tx.Init.Channel = DMA_CHANNEL_7;
hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_tx.Init.Mode = DMA_NORMAL;
hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_i2c2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_i2c2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2c2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx);
HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
}
你有没有想过为什么在使用DMA和I2C时它不能正常工作?
谢谢,
维克多
while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY) { vTaskDelay(1); }
等待它准备好会怎样呢?看起来从设备接收命令后,从设备不会释放线路。你使用了什么上拉电阻? - Bulkin