Reputation: 29
I am trying to control LEDs using IS31FL3236A LED driver from LUMISSIL Microsystem which communicates with I2C.
I use the HAL communication protocol of the STM32, I am able to turn on all the LEDs but I don't understand why I can't control the LEDs one by one or choose the intensity of the LEDs.
Here is my code.
IS31FL3236A.h to configure the address of all channels and the device address.
#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 to turn on all LEDs
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 */
}
To select LED number 19 for example, I just removed the two for loops and added this but the LED does not light up.
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 configuration
/**
* @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 */
}
}
Upvotes: 0
Views: 979
Reputation: 29
The offset changes the device address, you should not do the offset, it works like this:
// 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);
Thanks for your help @Frebreeze now it works.
Upvotes: 0
Reputation: 212
Here is what STM32 expects
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);
Here is what you give:
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);
My blind guess as to why the system is able to turn the leds all on or off and at max brightness is due to address auto increment.
Try using the I2C_MEM_WRITE() using magic numbers and local variables, buffers, and pointers. If this works then it is likely your usage of #defines within your driver file.
Check the return type of HAL_StatusTypeDef between each call. Make sure that it is OK.
Here are two example for stm32 i2c:
------------ Reply 1 ------------
Dont use I2C_MEMADD_SIZE_16BIT for the Size param. You need to specify the num of of the buffer you are pointing to. Go to your local source code and look at the instructions for how to use I2C_mem_write(). Based on the data sheet, I believe you should also be using I2C_MEMADD_SIZE_8BIT instead of 16.
Suppose you have a buffer of size one. You want to only read one byte then.
#define bufSize 1
uint8_t myBuf[bufSize];
myBuf[0] = someDataVal;
HAL_I2C_Mem_Write(&hi2c1, deviceAddr, LED19, I2C_MEMADD_SIZE_8BIT, myBuf, bufSize , 10);
------------ Reply 2 ------------
Is bufSize defined? If so, what number is it?
You need to be assigning to the first index of each buf if you are only writing one byte from each buf. pwm[0], current[0] (not 1), mode1[0] (not 2).
uint8_t pwm[bufSize];
uint8_t current[bufSize];
uint8_t mode1[bufSize];
pwm[0] = 0x7B;
current[1] = 0x00;
mode1[2] = 0x01;
------------ Reply 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;
Upvotes: 1