cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L152 I2C communication with LCD (NHD-C0220BiZ)

camila
Associate II
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
16 REPLIES 16
stm322399
Senior
Posted on February 13, 2014 at 14:53

Try a quick and dirty value ''I2C_SPEED1 / 2'' into the I2C init structure, that should divide by 2 the frequency. Check your scope measurement.

The exact bitrate is derived from what function RCC_GetClocksFreq returns. What is your quartz frequency (assuming you are using one to drive HSE, then PLL) ?

camila
Associate II
Posted on February 13, 2014 at 15:08

OK I divided the I2C clock speed by 2. Now I see the whole clock and data after sending the I2C_Send7BitAddress. Still it gets stuck on the EV6 flag check.

This is the screenshot of the scope.

0690X00000605XTQAY.png

Registers status after sending GenerateStart:

0690X00000605XYQAY.png

Registers status after I2C_Send7BitAddress:

0690X00000605XdQAI.png

stm322399
Senior
Posted on February 13, 2014 at 16:29

Well, I2C_SR1 AF bit and your scope trace show the same thing: your device does not answer. The slave should have force SDA to zero on the 9th clock bit, which does not happen.

Either your slave is lost (I2C slaves may requires manual resync) or the slave address is wrong. Data sheet are not very clear about I2C addresses, try with 0x78, 0x7a, 0x7c and 0x7e.

camila
Associate II
Posted on February 16, 2014 at 09:29

I tried the 4 possibilities you suggested for the value of the slave address but none of them work, all give the same result. It is still stuck on the EV6 flag. 

How can I do a manual resync of the LCD?

Thanks!

chen
Associate II
Posted on February 17, 2014 at 10:39

''I tried the 4 possibilities you suggested for the value of the slave address but none of them work, all give the same result. It is still stuck on the EV6 flag. 

How can I do a manual resync of the LCD?''

What do you mean by ''re-sync''?

If you mean - get I2C working - your guess is as good as ours right now. Laurent spotted the I2C freq was wrong - great work there!

The device you are using does not comply with I2C!

You can try sending a stop bit to end comms.

You can try resetting the LCD device (if you have the LCD reset under STM32 control).

drek-mu
Associate II
Posted on February 23, 2014 at 07:09

stm32f4discovery ,how to launch lcd display by fsmc ?are there any interference by leds which are embedded on board to same pins for lcd?

hi guys,it's my first visit in the group, can you help me ,i have recently bought stm32f4discovery board and learning arm controllers ,before i used avr risc 8bit controllers and have more skills in it ,but to do big projects in avr is impossible ,however now i'm using stm32 and i would like to work with embedded lcd display (in my board used st8377).i have motherboard for stm32f4discovery and there is possibility to connect lcd by motherboard to stm32f4discovery ,i think you know it .But i cann't launch lcd ,exactly it's running with white screen but in program i would like to change colors ,red green .....,can you help me if i post my program ?

chen
Associate II
Posted on February 24, 2014 at 16:05

Hi ulugbek

Start a new post/thread.