2014-02-12 6:07 AM
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));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);
}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);
}2014-02-12 6:20 AM
Hi
''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'' Question : How is the LCD powered?Is it getting it's power off the Discovery board? What does''delay(20);2014-02-13 1:41 AM
Hi,
Yes, the LCD gets its power from the Discovery. delay(20) takes about 0.2ms. I also have a 0.1ms delay in between the call to i2c_init() and lcd_init(). In addition, I don't think this should be a problem because I'm currently stepping on each statement, so this should give enough time for the uC to properly reset the LCD.When I look at the oscilloscope, this is what I see after the call to I2C_Send7bitAddress(I2Cx, deviceAddress, I2C_Direction_Transmitter);Where yellow is the SCLK, blue is SDA and purple is the active low reset of the LCD (in the screenshot high, since this is after the reset).2014-02-13 2:19 AM
Hi
The trace only shows 2 bits being transmitted. not sure what is going on. Try running the code upto ''/* 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));I2C_EVENT_MASTER_BYTE_TRANSMITTED2014-02-13 2:35 AM
I believe that until the while the configuration is correct. Here is a screenshot of the registers.
I2C_EVENT_MASTER_BYTE_TRANSMITTED,
if that's the case it is defined as I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084)Thanks!2014-02-13 2:59 AM
Hi
As I said before I cannot tell what is going on until I see the start bit and address byte being transmitted. The trace only showed 2 bits transmitted - very strange! And then a stop bit. ''is defined as I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084)'' Try #define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */2014-02-13 3:10 AM
What you are suggesting for I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED is what I actually have on the stm32l1xx_i2c.h file.
The screenshot that I sent from the scope is after the I2C_Send7BitAddress...2014-02-13 3:21 AM
''The screenshot that I sent from the scope is after the I2C_Send7BitAddress...''
Then something is very wrong. The trace only shows 2 bits being sent (only 2 SCLK cycles) and then what looks like a stop bit. Try to capture the whole 9 bits of the address byte!2014-02-13 4:22 AM
Is this likely that speed being too high locks the I2C IP ?
The capture shows that freq of SCL is near 700KHz, which is way over the 400 KHz max.2014-02-13 5:31 AM
I'm not sure how to get the entire clock sequence. I switched to ports 8 and 9 (clk and sda respectively), but still the same issue. I also changed the GPIO speed for both of them to 400KHz.Nevertheless, the frequency shown on the scope is still 700KHz, how can I change this?
