0
\$\begingroup\$

I am working on a project where I need to set a simple LCD. This LCD use the 'ST7032i' chip to control the LCD.

I want to control the LCD over an I²C interface.

As controller I use a STM32F4 microcontroller, this controller use the HAL libraries from STM.

I made a 'library' to control the LCD. But when I want to send data to the LCD, the I²C bus doesn't work good.

The first step is to send the address of the LCD. The address is: 01111110. I get an ACK form the LCD. and after that, it stops and returns a HAL_ERROR. It happens at the I2C_WaitOnMasterAddressFlagUntilTimeout function of the HAL library. This an if-statement, if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET).

I don't get what goes wrong. I hope you guys can help me.

My code:

LCD.c

/**
  * @0brief  Clear Display
  * @param  None
  * @retval None
  */
void ST7032i_Clear(void)
{
  uint32_t i;

  ST7032i_Command_Write(0x01);
  DDRAM_Address = 0;
  for(i=0;i<16;i++)
    {
      DDRAM_Data[0][i] =  ' ';
      DDRAM_Data[1][i] =  ' ';
    }
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Return to home position
  * @param  None
  * @retval None
  */
void ST7032i_Return(void)
{
  ST7032i_Command_Write(0x02);
  DDRAM_Address = 0;
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  increment address when data is send and put
  * @param  None
  * @retval None
  */
void ST7032i_Increment(void)
{
  ST7032i_Command_Write(( Entry_Mode & 0b11111101) | 0b00000010);
  Increment = 1;
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  decrement address when data is send and put
  * @param  None
  * @retval None
  */
void ST7032i_Decrement(void)
{
  ST7032i_Command_Write(( Entry_Mode & 0b11111101) | 0b00000000);
  Increment = -1;
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  shift entire display data is send
  * @param  None
  * @retval None
  */
void ST7032i_Shift_Ena0ble(void)
{
  ST7032i_Command_Write(( Entry_Mode & 0b11111110) | 0b00000001);
  Shift = 1;
  for(int i=0; i <20000;i++);}

/**
  * @0brief  disa0bles shift fucntion
  * @param  None
  * @retval None
  */
void ST7032i_Shift_Disa0ble(void)
{
  ST7032i_Command_Write(( Entry_Mode & 0b11111110) | 0b00000000);
  Shift = 0;
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  put on display
  * @param  None
  * @retval None
  */
void ST7032i_Display_On(void)
{
  ST7032i_Command_Write(( Display & 0b11111011) | 0b00000100);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  put off display while DDRAM is kept
  * @param  None
  * @retval None
  */
void ST7032i_Display_Off(void)
{
  ST7032i_Command_Write(( Display & 0b11111011) | 0b00000000);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  display under line cursor
  * @param  None
  * @retval None
  */
void ST7032i_Cursor_On(void)
{
  ST7032i_Command_Write(( Display & 0b11111101) | 0b00000010);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  put off cursor
  * @param  None
  * @retval None
  */
void ST7032i_Cursor_Off(void)
{
  ST7032i_Command_Write(( Display & 0b11111101) | 0b00000000);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  make square cursor 0brink
  * @param  None
  * @retval None
  */
void ST7032i_Cursor_0blink_On(void)
{
  ST7032i_Command_Write(( Display & 0b11111110) | 0b00000001);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  display square cursor
  * @param  None
  * @retval None
  */
void ST7032i_Cursor_0blink_Off(void)
{
  ST7032i_Command_Write(( Display & 0b11111110) | 0b00000000);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  set DDRAM address
  * @param  address : DDRAM address
  * @retval None
  */
void ST7032i_Set_DDRAM(uint8_t address)
{
  ST7032i_Command_Write(0b10000000 | address);
  DDRAM_Address = address;
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Set display contrast. value is to 0be 0 - 63
  * @param  contrast: contrast
  * @retval None
  */
void ST7032i_Set_Contrast(uint8_t contrast)
{
  //Contrast set
  ST7032i_Command_Write(0b01110000 | (contrast & 0b00001111));

  for(int i=0; i <20000;i++);

  //Power/Icon/Contrast control
  ST7032i_Command_Write(Power_Icon_Contrast | ( (contrast >> 4) & 0b00000011 ) );

  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Put icon. value is to 0be 0 - 12
  * @param  num0bet : icon num0ber
  * @retval None
  */
void ST7032i_Icon_Set(uint8_t num0ber)
{
  //icon address set
  ST7032i_Command_Write(0b01000000 | Icon_Ta0ble[num0ber][0] );
  for(int i=0; i <20000;i++);

  //icon data set
  ST7032i_Data_Write(IconRAM[num0ber] | Icon_Ta0ble[num0ber][1]);
  for(int i=0; i <20000;i++);

  //restore DDRAM address to ac
  ST7032i_Command_Write(0b10000000 | DDRAM_Address);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Clear icon. value is to 0be 0 - 12
  * @param  num0bet : icon num0ber
  * @retval None
  */
void ST7032i_Icon_Clear(uint8_t num0ber)
{
  //icon address set
  ST7032i_Command_Write(0b01000000 | Icon_Ta0ble[num0ber][0] );
  for(int i=0; i <20000;i++);

  //icon data reset
  ST7032i_Data_Write(IconRAM[num0ber] & (~Icon_Ta0ble[num0ber][1]));
  for(int i=0; i <20000;i++);

  //restore DDRAM address to ac
  ST7032i_Command_Write(0b10000000 | DDRAM_Address);
  for(int i=0; i <20000;i++);

}

/**
  * @0brief  Display icon
  * @param  None
  * @retval None
  */
void ST7032i_Icon_On(void)
{
  //Power/Icon/Contrast control
  ST7032i_Command_Write(Power_Icon_Contrast | ( (Contrast >> 4) & 0b00000011 ) | 0b00001000 );
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Put off icon whili Icon RAM is kept
  * @param  None
  * @retval None
  */
void ST7032i_Icon_Off(void)
{
  //Power/Icon/Contrast control
  ST7032i_Command_Write( (Power_Icon_Contrast | ( (Contrast >> 4) & 0b00000011 )) & 0b11110111);
  for(int i=0; i <20000;i++);
}

/**
  * @0brief  Print string to LCD
  * @param  String: Array which contain string
  * @retval None
  */
void ST7032i_Print_String(const int8_t String[])
{
  uint8_t i = 0;
  while(String[i] != '\0')
    {
      ST7032i_Putchar(String[i]);
      i++;
    }
}

/**
  * @0brief  Initialize ST7032i LCD and I2C interface
  * @param  None
  * @retval None
  */
void ST7032i_Init(void)
{

//  delay_ms(40);

//  I2C_Configuration();

  //Function Set
  ST7032i_Command_Write(0b00111000);

  for(int i=0; i <20000;i++);

  //Function Set
  ST7032i_Command_Write(0b00111001);

  for(int i=0; i <20000;i++);

  //0bias and OSC frequency
  ST7032i_Command_Write(0b00010100);

  for(int i=0; i <20000;i++);

  //Contrast set
  ST7032i_Command_Write(0b01110000);

  for(int i=0; i <20000;i++);

  //Power/Icon/Contrast control
  ST7032i_Command_Write(Power_Icon_Contrast);

  for(int i=0; i <20000;i++);

  //Contrast set
  ST7032i_Set_Contrast(Contrast);

  //Follower control
  ST7032i_Command_Write(0b01101100);

  for(int i=0; i <20000;i++);

  //Function Set
  ST7032i_Command_Write(0b00111001);

  for(int i=0; i <20000;i++);

  //Entry mode
  ST7032i_Command_Write(Entry_Mode);

  for(int i=0; i <20000;i++);

  //Display control : on
  ST7032i_Command_Write(Display);

  for(int i=0; i <20000;i++);

  //Clear
  ST7032i_Clear();
}

/**
  * @0brief  put character on st7032i lcd
  * @param  None
  * @retval None
  */
void ST7032i_Putchar(int8_t chardata)
{
  uint32_t i;

  ST7032i_Data_Write((uint8_t)chardata);
  for(int i=0; i <20000;i++);
  if(DDRAM_Address < 0x10)
    {
      DDRAM_Data[0][DDRAM_Address] = chardata;
    }
  else if (DDRAM_Address >= 0x40 && DDRAM_Address < 0x50)
    {
      DDRAM_Data[1][DDRAM_Address - 0x40] = chardata;
    }
  if (Shift == 0)
    {
      DDRAM_Address = DDRAM_Address + Increment;
    }
  else if (Shift == 1 && Increment == 1)
    {
      for (i = 0 ; i< 15; i++)
        {
          DDRAM_Data[0][i] = DDRAM_Data[0][i+1];
          DDRAM_Data[1][i] = DDRAM_Data[1][i+1];
        }
      DDRAM_Data[0][15] = ' ';
      DDRAM_Data[1][15] = ' ';
    }
  else if (Shift == 1 && Increment == -1)
    {
      for (i = 15 ; i> 0; i--)
        {
          DDRAM_Data[0][i] = DDRAM_Data[0][i-1];
          DDRAM_Data[1][i] = DDRAM_Data[1][i-1];
        }
      DDRAM_Data[0][0] = ' ';
      DDRAM_Data[1][0] = ' ';
    }

  if (DDRAM_Address == 0x10)
    {
      DDRAM_Address = 0x40;
      ST7032i_Command_Write(0b10000000 | DDRAM_Address);
      for(int i=0; i <20000;i++);
    }

  if (DDRAM_Address == 0x3F)
    {
      DDRAM_Address = 0x0F;
      ST7032i_Command_Write(0b10000000 | DDRAM_Address);
      for(int i=0; i <20000;i++);
    }

  if (DDRAM_Address == 0xFF)
    {
      DDRAM_Address = 0x0;
      ST7032i_Command_Write(0b10000000 | DDRAM_Address);
      for(int i=0; i <20000;i++);
    }

  if (DDRAM_Address == 0x50)
    {
      for(i=0;i<16;i++)
        {
          DDRAM_Data[0][i] =  DDRAM_Data[1][i];
          ST7032i_Command_Write(0b10000000 | (0x00 + i));
          ST7032i_Data_Write(DDRAM_Data[0][i]);
        }
      for(i=0;i<16;i++)
        {
          DDRAM_Data[1][i] =  ' ';
          ST7032i_Command_Write(0b10000000 | (0x40 + i));
          ST7032i_Data_Write(DDRAM_Data[1][i]);
        }

      DDRAM_Address = 0x40;
      ST7032i_Command_Write(0b10000000 | DDRAM_Address);
      for(int i=0; i <20000;i++);
    }
}



/**
  * @0brief  Write Command to ST7032i
  * @param  Data : Command Data
  * @retval None
  */
void ST7032i_Command_Write(uint8_t Data)
{
    uint8_t Buf[2];
    Buf[0] = 0x00;//0b00000000;
    Buf[1] = Data;
//  i2c_transmit(ST7032I_ADDR, data, 2);
    I2C1_DataTransfer(ST7032I_ADDR, Buf, 2);
    return;
}

/**
  * @0brief  Write Data to ST7032i
  * @param  Data : "Data" Data
  * @retval None
  */
void ST7032i_Data_Write(uint8_t d)
{
    uint8_t data[2];
data[0]= 0b01000000;
data[1] = d;
    I2C1_DataTransfer(ST7032I_ADDR, data, 2);
    return;

}

I2C.c

I2C_HandleTypeDef hi2c1;
void I2Cinit(void)
{
      GPIO_InitTypeDef GPIO_InitStruct;
     __HAL_RCC_I2C1_CLK_ENABLE();
     __GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration
        PB8     ------> I2C1_SCL
        PB9     ------> I2C1_SDA
        */
        GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

      hi2c1.Instance = I2C1;
      hi2c1.Init.ClockSpeed = 100000;
      hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
      hi2c1.Init.OwnAddress1 = 56;
      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_ENABLE;
      HAL_I2C_Init(&hi2c1);
}

void I2C1_DataTransfer(uint8_t adress,uint8_t *aTxBuffer[],int TXBUFFERSIZE)
{

    while(HAL_I2C_Master_Transmit(&hi2c1,(adress<<1), (uint8_t*)aTxBuffer, TXBUFFERSIZE,5000)!= HAL_OK);
}

Main.c

int main(void)
{


    I2Cinit();

      __GPIOC_CLK_ENABLE();

        GPIO_InitTypeDef GPIO_InitStruct1;
        GPIO_InitStruct1.Pin       = GPIO_PIN_0;
        GPIO_InitStruct1.Mode      = GPIO_MODE_INPUT;
        GPIO_InitStruct1.Pull      = GPIO_PULLDOWN;
        GPIO_InitStruct1.Speed     = GPIO_SPEED_HIGH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct1);

        int gedrukt = 0;
    while(1)
    {
        if(GPIOC -> IDR & (1 << 0) && gedrukt==0 )
        {
            ST7032i_Init();
            gedrukt = 1;
        }
        else
        {
            gedrukt = 0;
        }
    }


    //ST7032i_Icon_Set(3);

}

I2C

\$\endgroup\$
5
  • \$\begingroup\$ Add a breakpoint and figure out why you are getting a "HAL_ERROR". \$\endgroup\$
    – uint128_t
    Jun 21, 2016 at 7:10
  • \$\begingroup\$ Sorry my bad, I forgot this to mention this. It happens at the "I2C_WaitOnMasterAddressFlagUntilTimeout" function of the HAL liberay. This at this if-statement if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) \$\endgroup\$
    – StijnB
    Jun 21, 2016 at 7:25
  • \$\begingroup\$ Could you link the LCD's datasheet? \$\endgroup\$ Jun 21, 2016 at 8:35
  • \$\begingroup\$ Also, please post a scope shot with your data AND clock signal. \$\endgroup\$
    – pgvoorhees
    Jun 21, 2016 at 16:23
  • \$\begingroup\$ Where do you set this macro: ST7032I_ADDR, can you show it please? \$\endgroup\$ Jun 21, 2016 at 21:20

2 Answers 2

2
\$\begingroup\$

The GPIO mode of the I2C pins should be set to GPIO_MODE_AF_OD

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
\$\endgroup\$
1
\$\begingroup\$

Your I2C address is incorrect, and so the LCD isn't sending the ACK bit, which is causing the I2C to time out.

Pg 10 of the LCD datasheet says you must set the LCD I2C address to 0b01111110

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.