STM32L4 I2C LED 驱动器

STM32L4 I2C LED Driver

我正在尝试使用 IS31FL3236A LED 驱动器来控制 LED,来自 LUMISSIL Microsystem 与 I2C 通信。

LED driver datasheet

我用的是STM32的HAL通讯协议,我可以点亮所有的LED,但是我不明白为什么我不能一个一个地控制LED或者选择LED的亮度。

这是我的代码。

IS31FL3236A.h配置所有通道地址和设备地址

#define Single 0
#define RGB 1

#define Addr_GND    0x78 // P7 datasheet 0x78 = 1111000 en bit (addr 1)
#define PWM 0x04
#define All_EN  0x4A
#define IS3236_REG_PWM_OUT1     0x01 //LED PWM
#define IS3236_REG_PWM_OUT2     0x02
#define IS3236_REG_PWM_OUT3     0x03
#define IS3236_REG_PWM_OUT4     0x04
#define IS3236_REG_PWM_OUT5     0x05
#define IS3236_REG_PWM_OUT6     0x06
#define IS3236_REG_PWM_OUT7     0x07
#define IS3236_REG_PWM_OUT8     0x08
#define IS3236_REG_PWM_OUT9     0x09
#define IS3236_REG_PWM_OUT10    0x0A
#define IS3236_REG_PWM_OUT11    0x0B
#define IS3236_REG_PWM_OUT12    0x0C
#define IS3236_REG_PWM_OUT13    0x0D
#define IS3236_REG_PWM_OUT14    0x0E
#define IS3236_REG_PWM_OUT15    0x0F
#define IS3236_REG_PWM_OUT16    0x10
#define IS3236_REG_PWM_OUT17    0x11
#define IS3236_REG_PWM_OUT18    0x12
#define IS3236_REG_PWM_OUT19    0x13
#define IS3236_REG_PWM_OUT20    0x14
#define IS3236_REG_PWM_OUT21    0x15
#define IS3236_REG_PWM_OUT22    0x16
#define IS3236_REG_PWM_OUT23    0x17
#define IS3236_REG_PWM_OUT24    0x18
#define IS3236_REG_PWM_OUT25    0x19
#define IS3236_REG_PWM_OUT26    0x1A
#define IS3236_REG_PWM_OUT27    0x1B
#define IS3236_REG_PWM_OUT28    0x1C
#define IS3236_REG_PWM_OUT29    0x1D
#define IS3236_REG_PWM_OUT30    0x1E
#define IS3236_REG_PWM_OUT31    0x1F
#define IS3236_REG_PWM_OUT32    0x20
#define IS3236_REG_PWM_OUT33    0x21
#define IS3236_REG_PWM_OUT34    0x22
#define IS3236_REG_PWM_OUT35    0x23
#define IS3236_REG_PWM_OUT36    0x24

#define IS3236_REG_CTRL_OUT1    0x26 //LED ONOFF
#define IS3236_REG_CTRL_OUT2    0x27
#define IS3236_REG_CTRL_OUT3    0x28
#define IS3236_REG_CTRL_OUT4    0x29
#define IS3236_REG_CTRL_OUT5    0x2A
#define IS3236_REG_CTRL_OUT6    0x2B
#define IS3236_REG_CTRL_OUT7    0x2C
#define IS3236_REG_CTRL_OUT8    0x2D
#define IS3236_REG_CTRL_OUT9    0x2E
#define IS3236_REG_CTRL_OUT10   0x2F
#define IS3236_REG_CTRL_OUT11   0x30
#define IS3236_REG_CTRL_OUT12   0x31
#define IS3236_REG_CTRL_OUT13   0x32
#define IS3236_REG_CTRL_OUT14   0x33
#define IS3236_REG_CTRL_OUT15   0x34
#define IS3236_REG_CTRL_OUT16   0x35
#define IS3236_REG_CTRL_OUT17   0x36
#define IS3236_REG_CTRL_OUT18   0x37
#define IS3236_REG_CTRL_OUT19   0x38
#define IS3236_REG_CTRL_OUT20   0x39
#define IS3236_REG_CTRL_OUT21   0x3A
#define IS3236_REG_CTRL_OUT22   0x3B
#define IS3236_REG_CTRL_OUT23   0x3C
#define IS3236_REG_CTRL_OUT24   0x3D
#define IS3236_REG_CTRL_OUT25   0x3E
#define IS3236_REG_CTRL_OUT26   0x3F
#define IS3236_REG_CTRL_OUT27   0x40
#define IS3236_REG_CTRL_OUT28   0x41
#define IS3236_REG_CTRL_OUT29   0x42
#define IS3236_REG_CTRL_OUT30   0x43
#define IS3236_REG_CTRL_OUT31   0x44
#define IS3236_REG_CTRL_OUT32   0x45
#define IS3236_REG_CTRL_OUT33   0x46
#define IS3236_REG_CTRL_OUT34   0x47
#define IS3236_REG_CTRL_OUT35   0x48
#define IS3236_REG_CTRL_OUT36   0x49
#define Imax    0x11
#define update  0x25
#define freq    0x4B
#define mode    0x01

main.c 打开所有 LED

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  //I2C_GPIO_Init();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART2_UART_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */

  //I2C_GPIO_Init();
  IS31FL3236A_Init();
  static const uint16_t LED19 = 0x13;
  static const uint16_t LED19PWM = 0x38;
  static const uint16_t deviceAddr = 0x78;
  static const uint16_t Update = 0x25;
  static const uint16_t Freq = 0x4B;
  static const uint16_t intensityPWM = 0x02;
  static const uint16_t CurrentMax = 0x00;
  static const uint16_t Mode = 0x01;

  uint8_t pwm[bufSize];
  uint8_t current[bufSize];
  uint8_t mode1[bufSize];

  pwm[0] = 0x7B;
  current[0] = 0x00;
  mode1[0] = 0x01;


  uint8_t i=0;
  /*for(i=0;i<=0x49;i++){
      HAL_I2C_Mem_Write(&hi2c1, Addr_GND, i, I2C_MEMADD_SIZE_16BIT, (uint8_t*)PWM, 1, HAL_MAX_DELAY);
  }
  for(i=0;i<=0x24;i++){
          HAL_I2C_Mem_Write(&hi2c1, Addr_GND, i, sizeof(i), (uint8_t*)Imax, sizeof(Imax), 10);

      }*/
  HAL_I2C_Mem_Write(&hi2c1, deviceAddr, LED19PWM, I2C_MEMADD_SIZE_8BIT, pwm, bufSize, 10);
  HAL_I2C_Mem_Write(&hi2c1, deviceAddr, LED19, I2C_MEMADD_SIZE_8BIT, current, bufSize, 10);

  HAL_I2C_Mem_Write(&hi2c1, deviceAddr, Freq, I2C_MEMADD_SIZE_8BIT, current, bufSize, 10);
  HAL_I2C_Mem_Write(&hi2c1, deviceAddr, Mode, I2C_MEMADD_SIZE_8BIT, current, bufSize, 10);

  HAL_I2C_Mem_Write(&hi2c1, deviceAddr, Update, I2C_MEMADD_SIZE_8BIT, mode1, bufSize, 10);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {


      /*uint8_t i=0;
      for(i=0;i<=0x49;i++){
          HAL_I2C_Mem_Write(&hi2c1, Addr_GND, i, sizeof(i), (uint8_t*)PWM, sizeof(PWM), 10);
      }
      for(i=0;i<=0x24;i++){
              HAL_I2C_Mem_Write(&hi2c1, Addr_GND, i, sizeof(i), (uint8_t*)Imax, sizeof(Imax), 10);
          }

      HAL_I2C_Mem_Write(&hi2c1, Addr_GND, freq, sizeof(freq), (uint8_t*)Imax, sizeof(Imax), 10);
      HAL_I2C_Mem_Write(&hi2c1, Addr_GND, mode, sizeof(mode), (uint8_t*)Imax, sizeof(Imax), 10);
      HAL_I2C_Mem_Write(&hi2c1, Addr_GND, RESET, sizeof(RESET), (uint8_t*)mode, sizeof(mode), 10);
      HAL_I2C_Mem_Write(&hi2c1, Addr_GND, update, sizeof(update), (uint8_t*)mode, sizeof(mode), 10);*/

      //Swith();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

以 select LED 19 为例,我只是删除了两个 for 循环并添加了这个,但是 LED 不亮。

      HAL_I2C_Mem_Write(&hi2c1, GND, IS3236_REG_PWM_OUT19, sizeof(IS3236_REG_PWM_OUT19), (uint8_t*)PWM, sizeof(PWM), 10);
      HAL_I2C_Mem_Write(&hi2c1, GND, IS3236_REG_CTRL_OUT19, sizeof(IS3236_REG_CTRL_OUT19), (uint8_t*)Imax, sizeof(Imax), 10);
      HAL_I2C_Mem_Write(&hi2c1, GND, update, sizeof(update), (uint8_t*)mode, sizeof(mode), 10);

I2C 配置

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x00702991;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

stm32l4xx_hal_msp.c

/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hi2c->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PA9     ------> I2C1_SCL
    PA10     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }

}

/**
* @brief I2C MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
  if(hi2c->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspDeInit 0 */

  /* USER CODE END I2C1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_I2C1_CLK_DISABLE();

    /**I2C1 GPIO Configuration
    PA9     ------> I2C1_SCL
    PA10     ------> I2C1_SDA
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9);

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_10);

  /* USER CODE BEGIN I2C1_MspDeInit 1 */

  /* USER CODE END I2C1_MspDeInit 1 */
  }

}

这是STM32所期望的

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, 
                                    uint16_t DevAddress, 
                                    uint16_t MemAddress, 
                                    uint16_t MemAddSize, 
                                    uint8_t *pData, 
                                    uint16_t Size, 
                                    uint32_t Timeout);

这是你给的:

HAL_I2C_Mem_Write(&hi2c1, GND, IS3236_REG_PWM_OUT19, sizeof(IS3236_REG_PWM_OUT19), (uint8_t*)PWM, sizeof(PWM), 10);
HAL_I2C_Mem_Write(&hi2c1, GND, IS3236_REG_CTRL_OUT19, sizeof(IS3236_REG_CTRL_OUT19), (uint8_t*)Imax, sizeof(Imax), 10);
HAL_I2C_Mem_Write(&hi2c1, GND, update, sizeof(update), (uint8_t*)mode, sizeof(mode), 10);
  1. Do not take a sizeof(#define)
    • 重新绑定寄存器#defines 为静态常量。或者根据需要#define MemAddSize
  2. Don't use a pointer to a #define
  3. 将您的 MemAddSize 更改为:I2C_MEMADD_SIZE_16BIT、I2C_MEMADD_SIZE_8BIT

我盲目猜测为什么系统能够打开或关闭所有 LED 并达到最大亮度是由于地址自动递增。

尝试使用 I2C_MEM_WRITE() 使用幻数和局部变量、缓冲区和指针。如果这可行,那么很可能是您在驱动程序文件中使用了#defines。

在每次调用之间检查 HAL_StatusTypeDef 的 return 类型。确保一切正常。

这里有两个stm32 i2c的例子:

  1. Example using mem_write()
  2. Intro to stm32 i2c

------------回复1------------

不要对 Size 参数使用 I2C_MEMADD_SIZE_16BIT。您需要指定您指向的缓冲区的数量。转到本地源代码并查看有关如何使用 I2C_mem_write() 的说明。根据数据 sheet,我相信您也应该使用 I2C_MEMADD_SIZE_8BIT 而不是 16.

假设您有一个大小为 1 的缓冲区。那么您只想读取一个字节。

#define bufSize 1

uint8_t myBuf[bufSize];
myBuf[0] = someDataVal;

HAL_I2C_Mem_Write(&hi2c1, deviceAddr, LED19, I2C_MEMADD_SIZE_8BIT, myBuf, bufSize , 10);

------------回复2------------

  • 是否定义了bufSize?如果有,是几号?

  • 如果您只从每个 buf 写入一个字节,则需要分配给每个 buf 的第一个索引。 pwm[0]、电流[0](不是 1)、mode1[0](不是 2)。

    uint8_t pwm[bufSize];
    uint8_t current[bufSize];
    uint8_t mode1[bufSize];
    
    pwm[0] = 0x7B;
    current[1] = 0x00;
    mode1[2] = 0x01;
    

------------回复3------------

// First lets discuss device address
// What is your AD pin connected to (PG 7)
// Currently you have it configured to 0x78. Bit shift it for STM32 
// 0x78 << 1

uint8_t myBuf[1];

// Turn on the device by writing to register 0. Shutdown register
myBuf[0] = 0x01;
HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78) << 1, 0x00, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10;

// Then lets assign the pwm to the first LED (OUT1). Register 1. Reuse prior buffer. 
myBuf[0] = 0x80;
// Lets toggle LED 19
HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78) << 1, 0x01, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10;

// Enable OUT1 via Control register 26
myBuf[0] = 0x01;    // This would have maximum current settings (Pg. 9)
HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78) << 1, 0x26, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10;

// Tell system to update the registers. Register 25
myBuf[0] = 0x00;
HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78) << 1, 0x25, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10;
  • 我总是鼓励您查看每个 return 的 HAL_STATUS。你能告诉我是否可以吗?

偏移量改变了设备地址,你不应该做偏移量,它的工作原理是这样的:

  // First lets discuss device address
  // What is your AD pin connected to (PG 7)

  uint8_t myBuf[1];

  // First lets turn on the device by writing to register 0. Shutdown register
  myBuf[0] = 0x01;
  HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78), 0x00, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10);

  // Then lets assign the pwm to the first LED (OUT1). Register 1. Reuse prior buffer.
  myBuf[0] = 0xff;
  // Lets toggle LED 19
  HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78), 0x13, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10);

  // Enable OUT1 via Control register 26
  myBuf[0] = 0x01;    // This would have maximum current settings (Pg. 9)
  HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78), 0x38, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10);

  // Tell system to update the registers. Register 25
  myBuf[0] = 0x00;
  HAL_I2C_Mem_Write(&hi2c1, ((uint16_t) 0x78), 0x25, I2C_MEMADD_SIZE_8BIT, myBuf, 1, 10);

感谢您的帮助@Frebreeze 现在可以使用了。