Question
STM32L152 I2C communication with LCD (NHD-C0220BiZ)
Posted on February 12, 2014 at 15:07
Hello,
I'm trying to interface the STM32L152 Discovery with an LCD display (NHD-C0220BiZ-FSW-FBW-3V3M) through I2C. I'm finding a problem when trying to write the first command to the LCD the code gets stuck on the EV6 check:while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
From the LCD I have SDA connected to PB7 and SCL connected to PB6. This lines have 4.7K pull up resistors connected to them.
Any ideas why this is happening?
The I2C driver's code is the following:
void i2c_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
//I2C_DeInit(I2Cx);
/*!< I2C Periph clock enable */
RCC_APB1PeriphClockCmd(I2Cx_CLK, ENABLE);
/*!< SDA GPIO clock enable */
RCC_AHBPeriphClockCmd(I2Cx_SDA_GPIO_CLK, ENABLE);
/*!< SCL GPIO clock enable */
RCC_AHBPeriphClockCmd(I2Cx_SCL_GPIO_CLK, ENABLE);
/* Connect PXx to I2C_SCL */
GPIO_PinAFConfig(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_SOURCE, GPIO_AF_I2C1);
/* Connect PXx to I2C_SDA */
GPIO_PinAFConfig(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_SOURCE, GPIO_AF_I2C1);
/*!< Configure I2C SCL pin */
GPIO_InitStructure.GPIO_Pin = I2Cx_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStructure);
/*!< Configure I2C SDA pin */
GPIO_InitStructure.GPIO_Pin = I2Cx_SDA_PIN;
GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStructure);
// /* Configure the I2C event priority */
// NVIC_InitStructure.NVIC_IRQChannel = I2Cx_EV_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// /* Configure I2C error interrupt to have the higher priority */
// NVIC_InitStructure.NVIC_IRQChannel = I2Cx_ER_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
// NVIC_Init(&NVIC_InitStructure);
I2C_DeInit(I2Cx);
/*!< I2C Struct Initialize */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE;
I2C_InitStructure.I2C_OwnAddress1 = 0x60;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED1;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/*!< I2C Initialize */
I2C_Init(I2Cx, &I2C_InitStructure);
// /* Enable Error Interrupt */
// I2C_ITConfig(I2Cx, I2C_IT_ERR , ENABLE);
/* I2C ENABLE */
I2C_Cmd(I2Cx, ENABLE);
}
/*******************************************************************************
* Function Name : I2C_ByteWrite
* Description : write a Byte to I2C Bus
* Input : deviceAddr is the I2C address of the device
* WriteAddr is the register address you want to write to
* pBuffer contains bytes to write
* Output : None
* Return : None
*******************************************************************************/
void I2C_ByteWrite(uint8_t pBuffer, uint8_t deviceAddress, uint8_t WriteAddr) {
/* Send START condition */
I2C_GenerateSTART(I2Cx, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2Cx, deviceAddress, I2C_Direction_Transmitter);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* Send the EEPROM's internal address to write to : only one byte Address */
I2C_SendData(I2Cx, WriteAddr);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* Send the byte to be written */
I2C_SendData(I2Cx, pBuffer);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* Send STOP condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
}
I call i2c_init(); successfully, the problem arises in the first I2C_ByteWrite inside the call to init_lcd();
This looks as follows:
void init_lcd(void)
{
RESET_RST; //RST = 0, reset
delay(2);
SET_RST; //RST = 1, end reset
delay(20);
I2C_ByteWrite(FUNC_SET_TBL0, LCD_ADDR, 0x00);
delay(10);
I2C_ByteWrite(FUNC_SET_TBL1, LCD_ADDR, 0x00);
delay(10);
I2C_ByteWrite(BIAS, LCD_ADDR, 0x00); // Set BIAS - 1/5
I2C_ByteWrite(CONTRAST, LCD_ADDR, 0x00); // Set contrast low byte
I2C_ByteWrite(BOOSTER, LCD_ADDR, 0x00); // ICON disp on, Booster on, Contrast high byte
I2C_ByteWrite(FOLLOWER, LCD_ADDR, 0x00); // Follower circuit (internal), amp ratio (6)
I2C_ByteWrite(DISPLAY_ON, LCD_ADDR, 0x00); // Display on
I2C_ByteWrite(CLEAR_DISPLAY, LCD_ADDR, 0x00); // Clear display
I2C_ByteWrite(ENTRY_MODE, LCD_ADDR, 0x00); //Entry mode set - increment
delay(10);
}
I would really appreciate any help and suggestions.
Thank you.
#ev6 #stm32l #discovery #i2c