【问题标题】:Does anyone have an STM32L0xx with TLC59116 I2C Example code?有人有带有 TLC59116 I2C 示例代码的 STM32L0xx 吗?
【发布时间】:2019-09-05 00:09:30
【问题描述】:

我正在编写一个基本的 LED 程序,以使用 STM32L0xx 芯片和 TI TLC59116F 在定制板上点亮 LED,但我在解释数据表时遇到了一些问题。

我使用 STM32CubeMX 设置初始引脚和初始化 I2C,并根据我找到的一些示例提出以下内容。

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "led.h"

/* Private variables ---------------------------------------------------------*/

void TLC59116_Init(void)
{
    // Set default register values
    TLC59116_WriteReg(TLC59116_MODE1, TLC59116_MODE1_DEFAULT);
    TLC59116_WriteReg(TLC59116_MODE2, TLC59116_MODE2_DEFAULT);

    // Set all PWM values to 0x00 (OFF)
    uint8_t aTXBuffer[] = { TLC59116_PWM0_AUTOINCR, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF,
            TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF,
            TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF,
            TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF,
            TLC59116_LEDOUT_OFF, TLC59116_LEDOUT_OFF };

    TLC59116_WriteStream(sizeof(aTXBuffer), aTXBuffer);

    // Set all LEDs to PWM Control
    TLC59116_WriteReg(TLC59116_LEDOUT0, TLC59116_LEDOUT_ON);
    TLC59116_WriteReg(TLC59116_LEDOUT1, TLC59116_LEDOUT_ON);
    TLC59116_WriteReg(TLC59116_LEDOUT2, TLC59116_LEDOUT_ON);
    TLC59116_WriteReg(TLC59116_LEDOUT3, TLC59116_LEDOUT_ON);

}

static void TLC59116_WriteReg(uint8_t reg, uint8_t val)
{
    uint8_t aTXBuffer[] = { reg, val };
    while(HAL_I2C_Master_Transmit(&hi2c1, TLC59116_ADDR, aTXBuffer, sizeof(aTXBuffer), 100) != HAL_OK)
        {
            if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
            {
                Error_Handler();
            }
        }
}

static void TLC59116_WriteStream(uint8_t len, uint8_t *pData)
{
    if (len == 0)
    {
        Error_Handler();
    }
    while(HAL_I2C_Master_Transmit(&hi2c1, TLC59116_ADDR, pData, len, 100) != HAL_OK)
    {
        if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
        {
            Error_Handler();
        }
    }
}

void TLC59116_LED(uint8_t led, uint8_t state)
{
    if ((led < 0) || (led > 15)) {
        Error_Handler();
    } else {
        TLC59116_WriteReg(led + TLC59116_PWM0, state);
    }
}

void TLC59116_SLEEP(void)
{
    TLC59116_WriteReg(TLC59116_MODE1, TLC59116_MODE1_SLEEP);
}

void TLC59116_WAKE(void)
{
    TLC59116_WriteReg(TLC59116_MODE1, TLC59116_MODE1_DEFAULT);
    HAL_Delay(5);
}

然后在main.c中

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USB_PCD_Init();
  TLC59116_Init();
  TLC59116_LED(TLC59116_PWM5, 0x01); // Sets LED 5 to ON 

}

编辑:这是一个更完整的代码示例,包含 HAL 错误检查等。

【问题讨论】:

  • 子寻址是一个 I2C 术语,并不特定于 TI 部分。子寻址是指选择 TI 部分中的特定寄存器。访问任何 I2C 设备时,首先发送设备/从机地址,然后是子地址,最后是写入寄存器值时的数据值。请参阅数据表中的第 26 页,第一行说明了在关闭自动增量的情况下写入单个寄存器。
  • 坚持用HAL学习,后期用LL优化,或者硬着头皮坚持用LL。在您上面提供的 LL 示例中,LL_I2C_TransmitData8(...) 仅通过 I2C 总线发送单个 8 位值,而不是整个 aTxBuffer。
  • 我完全忽略了 8... 天哪。我将浏览 DS 并提出一个修改后的示例。谢谢。
  • 我添加了更多信息,并切换到 HAL。
  • 好多了。 TLC59116_WriteReg() 看起来正确,但是 TLC59116_WriteStream() 将不起作用。您还需要在方法调用中添加一个大小参数,并直接在 HAL_I2C_Master_Transmit() 中使用指针和大小。照原样,TLC59116_WriteStream() 将坏数据发送到总线上。使用自动增量功能时,请务必遵循数据表的第 22 页。另外,请记住,您定义的 TLC59116_ADDR 应仅用于写入 (0xC0)。如果/当您需要读取寄存器内容时,需要定义一个新定义 (0xC1)。

标签: c stm32 stm32ldiscovery stm32f0


【解决方案1】:

假设您有 STM32CubeMX 为您的 I2C 总线生成正确的初始化,那么您可以使用您引用的轮询方法评估 TLC59116:

HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

设置 DevAddress 的值在数据表的第 23 页上定义,您必须查看原理图并将位 0 ​​设置为 0 写入寄存器时。假设板上的 A[3:0] = 0x0,DevAddress 将变为:

  • 0xC0 用于写入 (writeAddr) 到 TLC59116
  • 0xC1 用于从 TLC59116 读取 (readAddr)

接下来,您需要设置包含要设置的寄存器地址和寄存器值的有效负载。例如(参见数据表第 18 页):

uint8_t aTxBuffer[2] = {};
aTxBuffer[0] = 0x14; /* LEDOUT0 register */
aTxBuffer[1] = 0x05; /* Turn on LED 0 and LED 1 */

HAL_I2C_Master_Transmit(hi2c1, writeAddr, aTxBuffer, sizeof(aTxBuffer), 100);

但是,请务必在执行上述操作之前查看 MODE1 寄存器。您需要清除 OSC 位,否则您将永远不会点亮 LED。

uint8_t aTxBuffer[2] = {};
aTxBuffer[0] = 0x00; /* MODE1 register */
aTxBuffer[1] = 0x00; /* Example only, review each bit */

HAL_I2C_Master_Transmit(hi2c1, writeAddr, aTxBuffer, sizeof(aTxBuffer), 100);

上面说明了写入单个寄存器,以将数据流式传输到多个寄存器位置:

void TLC59116_WriteStream(uint8_t len, uint8_t *pData)
{
    if (len == 0)
    {
        ErrorHandler();
    }
    HAL_I2C_Master_Transmit(&h12c1, TLC59116_ADDR, pData, len, 100);
}

其中TLC59116_ADDR = 0xC0 和 pData 指向要发送到 TI 设备的消息的基地址。

将所有 16 个 PWM 寄存器设置为 0x00 或关闭:

uint8_t aTXBuffer[] = { TLC59116_PWM0_AUTOINCR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
TLC59116_WriteStream(sizeof(aTXBuffer), aTXBuffer);

在哪里TLC59116_PWM0_AUTOINCR = 0x82;

【讨论】:

  • 太棒了!谢谢你。我一直在考虑废弃 HAL 并改用 LL。这是我在 LL 的主帖中提出的。
  • 嗨@TyrantUT,如果这个或任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
猜你喜欢
  • 2010-10-03
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2011-09-27
  • 2011-02-22
相关资源
最近更新 更多