【发布时间】: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