我正在使用一个STM32F4,我想与我的LSM303加速度计通信。为此,我使用I2C,只是使用I2C工作正常,但当我尝试使用DMA时,它停止工作。 当我使用HAL_I2C_Master_Transmit_DMA它工作,我得到了IRQHandler和。但是在那之后,我想使用HAL_I2C_Master_Receive_DMA,它说I2C的状态还没准备好...... 我读到I2C与STM32FX搞混了,但我不明白为什么没有DMA就能正常工作。
当它遇到Master_Transmit_DMA的回调I2C_DMAXferCplt时,它表示I2C_HandleTypeDef的CurrentState仍然等于HAL_I2C_STATE_BUSY_TX,因此它不会将状态恢复为READY。这就是为什么当我调用Master_Receive_DMA时它没有收到任何东西。
这是我的I2C init:
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);
}
}
当我使用带I2C的DMA时,你有什么想法吗?
谢谢,
维克多
答案 0 :(得分:1)
当我在DMA中断之上启用I2C_event中断时,它为我工作,请参见下面的生成的代码和CubeMX配置
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
选择DMA时,CubeMX不会自动检查I2C1事件全局中断,我认为应该这样做(意法半导体(STmicro)请解决此问题),因为我看不到没有它如何工作。
答案 1 :(得分:0)
我遇到了同样的问题。我已经通过降低频率来解决它。
ST勘误文件说,您必须将I2C频率降低到 88kHz 才能解决其他问题。
我知道它并不能解释为什么在阻塞模式下不会发生此错误,而是在DMA中发生此错误,但我希望它会有所帮助。
答案 2 :(得分:0)
我一直在 STM32F407 和 I2C1 上遇到相同的问题。
在搜索程序流程中的潜在错误之后,我发现函数HAL_I2C_Master_Transmit_DMA
导致以下行:
dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize);
第一次传输后,它不会返回HAL_OK
,这对于继续传输是必需的。
因此,我的解决方案是简单地中止传输完成后调用的回调函数中的前一个DMA中断。 HAL_I2C_Master_Receive_DMA
可以暗示相同的含义。为了解决该问题,我在main.c
中添加了以下回调函数:
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if (hi2c->Instance==hi2c1.Instance)
{
HAL_DMA_Abort_IT(hi2c->hdmatx);
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if (hi2c->Instance==hi2c1.Instance)
{
HAL_DMA_Abort_IT(hi2c->hdmarx);
}
}
请考虑这只是一种解决方法。如果有人发现,我想进一步了解此错误的根本原因。