olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
4.91k stars 1.02k forks source link

[Bug]: STM32 with SSD1306 using the standard peripheral library #2397

Open ShiinaKaze opened 3 months ago

ShiinaKaze commented 3 months ago

Device: STM32F103C8T6 Library: Standard peripheral library Module: 0.96 inch OLED with SSD1306

I have read port tutorial.

Problem: I need to write the following code, and if I change it a little, it won't work, I tried to wrap it as a function, but it wouldn't work.

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t *data = (uint8_t *)arg_ptr;
  uint8_t data_length = arg_int;
  uint8_t retry = 0;
  switch (msg)
  {
  case U8X8_MSG_BYTE_INIT:
    /* add your custom code to init i2c subsystem */
    HW_I2C_Init();
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && retry < 200)
    {
      retry++;
    }
    retry = 0;
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && retry < 200)
    {
      retry++;
    }
    retry = 0;
    I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && retry < 200)
    {
      retry++;
    }
    break;
  case U8X8_MSG_BYTE_SEND:
    for (int i = 0; i < data_length; i++)
    {
      I2C_SendData(I2C1, data[i]);
      while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET)
      {
      }
    }
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    I2C_GenerateSTOP(I2C1, ENABLE);
    break;
  default:
    return 0;
  }
  return 1;
}
olikraus commented 3 months ago

Not sure how I can help here..

ShiinaKaze commented 3 months ago

Not sure how I can help here..

Sorry, let me be clear If I just wrap as a function like this, it dose not work.

void i2c_transfer(uint8_t address, uint8_t data_length, uint8_t *data)
{
  uint8_t retry = 0;
  I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && retry < 200)
  {
    retry++;
  }
  for (int i = 0; i < data_length; i++)
  {
    I2C_SendData(I2C1, data[i]);
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET)
    {
    }
  }
}

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t *data = (uint8_t *)arg_ptr;
  uint8_t data_length = arg_int;
  uint8_t retry = 0;
  switch (msg)
  {
  case U8X8_MSG_BYTE_INIT:
    /* add your custom code to init i2c subsystem */
    HW_I2C_Init();
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && retry < 200)
    {
      retry++;
    }
    retry = 0;
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && retry < 200)
    {
      retry++;
    }
    break;
  case U8X8_MSG_BYTE_SEND:
    i2c_transfer(u8x8_GetI2CAddress(u8x8), data_length, data);
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    I2C_GenerateSTOP(I2C1, ENABLE);
    break;
  default:
    return 0;
  }
  return 1;
}
olikraus commented 3 months ago

The code is not the same. You are sending the address during data transfer in the second case.

ShiinaKaze commented 3 months ago

The code is not the same. You are sending the address during data transfer in the second case.

well, I've tried sending the address 0x78 directly, it still not working properly

void i2c_transfer(uint8_t address, uint8_t data_length, uint8_t *data)
{
  uint8_t retry = 0;
  I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && retry < 200)
  {
    retry++;
  }
  for (int i = 0; i < data_length; i++)
  {
    I2C_SendData(I2C1, data[i]);
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET)
    {
    }
  }
}

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t *data = (uint8_t *)arg_ptr;
  uint8_t data_length = arg_int;
  uint8_t retry = 0;
  switch (msg)
  {
  case U8X8_MSG_BYTE_INIT:
    /* add your custom code to init i2c subsystem */
    HW_I2C_Init();
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && retry < 200)
    {
      retry++;
    }
    retry = 0;
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && retry < 200)
    {
      retry++;
    }
    break;
  case U8X8_MSG_BYTE_SEND:
    i2c_transfer(0x78, data_length, data);
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    I2C_GenerateSTOP(I2C1, ENABLE);
    break;
  default:
    return 0;
  }
  return 1;
}
olikraus commented 3 months ago

ok, still i don't know how to help is. I don't know your low level functions. It also looks strange that you have to send start/stop conditions. It should be part of the transfer procedure.