5
votes

Edit:

The solution was to turn down the I2C clock in the initialization block. Although the STM could handle it, the data sheet for the LCD stated it could handle only up to 10kHz.
For the DMA there is an IRQ that must be enabled and setup in the CubeMX software that will enable DMA TX/RX lines.


I'm using an STM32 - Nucleo-F401RE board with freeRTOS. I've used freeRTOS a bit recently, but I have never really used I2C.

Trying to setup a simple LCD display using the I2C drivers that CubeMX generates.

So far it only sends about half the data I request to send. I've tested it with the simple "show firmware" command and this works. So I can verify that the I2C instance is setup correctly.

/* I2C1 init function */
static 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;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

}

It has international pull-up resistors set as well.

/* vdebugTask function */
void vdebugTask(void const * argument)
{
  /* USER CODE BEGIN vdebugTask */

  /* Infinite loop */
  for(;;)
  {
        char hi[6];
        hi[0]   = 'h';
        hi[1]   = 'e';
        hi[2]   = 'y';
        hi[3]   = 'a';
        hi[4]   = 'h';
        hi[5]   = '!';

        HAL_I2C_Master_Transmit_DMA(&hi2c1, (0x50), hi, 6);
        vTaskDelay(10);
  }
  /* USER CODE END vdebugTask */
}

This is the code I am trying to run, I have not changed the HAL function at all. I don't think that it could be more simple than this, however this is all that happens.

I followed the timing constraints in the data sheet for the LCD, and the CubeMX software didn't warn or state anywhere that their I2C drivers had any special requirements. Am I doing something wrong with the program?

missignletters

I have also tried using the non-DMA blocking mode polling transfer function that was also created by CubeMX

HAL_I2C_Master_Transmit(&hi2c1, (0x50), hi, 6, 1000);

This is even worse and just continuously spams the screen with unintelligible text.

1
By "It has international pull-up resistors set as well. " this you mean that you configured pull-up on the I2C pins of the Nucleo?Bence Kaulics
@BenceKaulics Yes, that is correct.Tropical_Peach
The Nucleo's logic level is 3 V and the LCD needs 5 V, so according to the datasheet the minimum logic high input value of the LCD is 5 V * 0.7 V = 3.5 V, too high if the bus is pulled to 3 V. You can also disable the pull-ups on Nucleo side (which are far to big, around 25-50 kO), because the LCD has its own 10kO pull-ups, R7, R8. There is a possibility that the LCD miss some data because of the inappropriate logic level, or do you use any level shifting circuit or the I2C bus is pulled up to 5 V and the Nucleo's I2C pins are 5 V tolerant?Bence Kaulics
@BenceKaulics I've just checked the board with a multi-meter and the I2C lines are running at 4.2V, which checks out with the LCD being 5V logic. I have the backlight supply connected to 3.3V so it is blue, everything else seems to checkout with the LCD specs. Disabling the internal pull ups had no effect.Tropical_Peach
Try to lower the I2C clock speed, for example to 50 kHz. So you will know that the clock is OK.Bence Kaulics

1 Answers

2
votes

The solution was to turn down the I2C clock in the initialization block. Although the STM could handle it, the data sheet for the LCD stated it could handle only up to 10kHz. For the DMA there is an IRQ that must be enabled and setup in the CubeMX software that will enable DMA TX/RX lines.

Note that the clock still must adhere to the hardware limitations. I assume that roughly 20% less than maximum stated in the data sheet will suffice. For my LCD this means that I am going to be using 80kHz.

First go to configuration : step 1

And then click on DMA to setup a DMA request. I've only selected TX as I don't care about an RX DMA from the LCD. step 2