2021-09-16 03:41 AM
I am a beginner and learning I2C DMA, could you tell me what I'm doing wrong?
I connected the LCD to Blue Pill and it works fine with function "HAL_I2C_Master_Transmit" i.e. without DMA!
But, when DMA is configured, it is dosn't works!
Very simple code, but I can not find a mistake!
Link to my main.c https://pastebin.com/cz7b2Bbu
Solved! Go to Solution.
2021-09-16 03:56 AM
Hello @DK.7
I advise you to start with the I2C example available under STM32CubeF1 MCU package, to use I2C via DMA:
\STM32Cube_FW_F1_V1.8.4\Projects\STM32F103RB-Nucleo\Examples\I2C\I2C_TwoBoards_ComDMA
Have a look at this FAQ "STM32 I2C does not work" describes few tips related to I2C peripheral on STM32 devices.
When your question is answered, please close this topic by choosing Select as Best.
Imen
2021-09-16 03:47 AM
You need to wait for the transfer to complete before starting another DMA transfer. You can do so by polling the state of the handle.
You should always monitor the return status from HAL_* to verify it succeeds (HAL_OK).
2021-09-16 03:56 AM
Hello @DK.7
I advise you to start with the I2C example available under STM32CubeF1 MCU package, to use I2C via DMA:
\STM32Cube_FW_F1_V1.8.4\Projects\STM32F103RB-Nucleo\Examples\I2C\I2C_TwoBoards_ComDMA
Have a look at this FAQ "STM32 I2C does not work" describes few tips related to I2C peripheral on STM32 devices.
When your question is answered, please close this topic by choosing Select as Best.
Imen
2021-09-16 06:01 AM
Thanks for answers! I rewrote my code according to the example, but something does not work! Link to my new main.c https://pastebin.com/BvDa3ivg
2021-09-16 08:10 AM
I found my mistake, one more time THANK YOU!
my code now https://pastebin.com/yP56NqX8
2024-10-14 02:37 PM - edited 2024-10-17 01:33 PM
Very interesting, I also try to drive an LCD with DMA but with black pill.
My application is a realtime synthesizer which should print its parameters on changes (by midi controller etc) frequently to the display. I have a time critical loop and applied a timer, which fires the lcd update 10 times a second. When fired and changes have to be displayed, it sets the cursor to 0,0. After that, I wait for I2C Ready and them I write the 32 char string via DMA. So far so good, it works great! But the while loop for waiting I2C Ready is still there after the LCD Command, I want to get rid of it. When I try to move the wait loop to the beginning of the string write, it does not work. I also tried to decouple setPos and writeString into 2 parts, processing my audio data between them. That also does not work. It only works when I have the while loop for waiting I2C ready DIRECTLY after the LCD command setPos. What can be the problem? I use also I2S with DMA and SPI with DMA, maybe there are conflicts? Each Interface should have its own DMA stream and they work independently, right?
BTW: Certainly I turned on the DMA Interrupt for I2C.
EDIT:
Oh my god I made it work! I don't know where the problem was, but now I can drive the LCD with DMA without any DELAYs. The solution is to wait for I2C Complete Interrupt:
void HAL_I2C_MasterTxCpltCallback (I2C_HandleTypeDef * hi2c)
{
lcdComplete=1;
}
In my main loop, there are many things running but the secret was to have an additional state variable which switches between 0 and 1. Thus, the loop executes alternately setCursor and writeString. Before each call, it waits for a timer interrupt (interval), the i2c complete flag (lcdComplete) and a dirty flag (lcdDirty) which is set when data has changed.
if (interval && lcdComplete && lcdDirty) {
if (lcdState==0) {
I2C_LCD_SetCursor_DMA(MyI2C_LCD, 0, 1);
lcdState=1;
} else {
sprintf(lcdstr, "Param %3d = %3d", ccnum, ccvalue);
I2C_LCD_WriteString_DMA(MyI2C_LCD, lcdstr);
lcdState=0;
lcdDirty=0;
}
interval=0;
lcdComplete=0;
}