cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 I2C Receive using DMA in Circular mode

bubulindo
Associate
Posted on April 22, 2016 at 10:39

Hello,

I'm starting out using the CubeMX software to configure my NucleoF103 and one of my first test applications was the I2C bus. I got it working by polling. Then I started looking into the DMA and can use DMA to receive in direct mode as well, using HAL_I2C_Master_Receive_DMA. So far, so good. However, after reading the circular mode of the DMA description in the manual (which is very little...), I got the impression that if the DMA is configured in circular mode it would continuously call the HAL_I2C_Master_Receive_DMA function thus avoiding my having to worry about calling it. However, this is not the case and the circular mode doesn't restart. The only way I got it running was by calling again the Receive_DMA function in the DMA complete interrupt function, which defeats the purpose. Is this even possible, or is there something I may be missing?

/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration 
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA 
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_I2C1_ENABLE();
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* Peripheral DMA init*/
hdma_i2c1_rx.Instance = DMA1_Channel7;
hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c1_rx.Init.Mode = DMA_CIRCULAR;
hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_i2c1_rx);
__HAL_LINKDMA(hi2c,hdmarx,hdma_i2c1_rx);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}

Thanks in advance.
3 REPLIES 3
Walid FTITI_O
Senior II
Posted on April 22, 2016 at 20:29

Hi cardosi.carlo,

When using DMA, master reception of a single byte is not supported.

for further help, refer to application note

http://www.st.com/st-web-ui/static/active/jp/resource/technical/document/application_note/CD00209826.pdf

''STM32F10xxx I2C optimized examples''.

-Hannibal-

bubulindo
Associate
Posted on May 02, 2016 at 17:21

Hello,

I'm trying to receive 64 bytes in circular mode. According to the very little information about the Circular mode from ST, this should be possible, but I cannot find anything about this example in particular.

This would be fairly useful on my application (a DS1307 RTC) as I wouldn't have to worry about launching an I2C read, but instead just read the memory location in RAM to where my DMA would push the RTC data to.

Walid FTITI_O
Senior II
Posted on May 03, 2016 at 13:00

Hi cardosi.carlo,

In your case, why you don't use the Backup SRAM register to store and read the RTC data.

-Hannibal-