AnsweredAssumed Answered

LCD1602 + pcf8574 (I2C) + STM32F0

Question asked by Lyubomyr D on Oct 21, 2017
Latest reply on Dec 12, 2017 by shane mattner

Hello.

I have some problem with LCD1602+pcf8574 (I2C) and STM32F0. 

 

I experience the following bugs

1) When I try to display more than three symbols they seem to be ignored

2) If I try to display three symbols, I have to flush the firmware twice(one directly after another) in order to display changes on the LCD1602 screen

 

It seems that there is some overrun(????), but I can't figure out where.

 

What am I doing wrong?

Help me, please.

 

 

main.c

#include "stm32f0xx.h"

 

#include "i2c_lcd.h"

#define I2C1_OWN_ADDRESS (0x27)

int main(void) {

    SystemInit();

 


    gpioInit();
    i2cInit();
    InitDelayTIM6();
    delay_init();
    lcd_Init();
    lcd_PrintC("ABC"); //if I try to print ABCD nothing happends; Another three letter can be displayed

     while(1) { }

}

 

void gpioInit(void) {

 

 

    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;


    GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7)) \
        | (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);

 

 

    GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7;

 

    GPIOB->AFR[0] = (GPIOB ->AFR[0] &~ (GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7))\
        | (1 << (6 * 4)) | (1 << (7 * 4));


}

void i2cInit(void) {
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;

    I2C1->CR1 &= ~(I2C_CR1_PE) ;

/* Timing register value is computed with the AN4235 xls file,
Standard Mode @50kHz with I2CCLK = 48MHz, rise time = 100ns, fall time = 30ns */

    I2C1->TIMINGR = (uint32_t) 0x205078C1; 

    I2C1->CR1 |= I2C_CR1_PE ; 

    I2C1->CR2 |= I2C_CR2_AUTOEND | (1<<16) | (I2C1_OWN_ADDRESS<<1);

}

 

 

i2c_lcd.c

#include "i2c_lcd.h"

#include "stm32f0xx_i2c.h" // this one is not used

uint8_t backlightState = 1;

 

 

 

void lcd_PrintC(const uint8_t *str) {
    uint8_t i;
    while (i = *str++){
        lcd_Data(i);

       TIM6delay_ms(2);
    }
}

void lcd_Init(void) {

 

    TIM6delay_ms(50);
    lcd_FirstCommand();

 

    lcd_Command(0x28);// 4bit 2 lines, 5x8 font. Page 8 Function Set. Page 9 Top.
    lcd_Command(0x08); // display off entirely. Page 6, row 4. Page 8 Display On/Off
    lcd_Command(0x06); //Page 6 Row 3

    lcd_Command(0x01);// Clear display. Page 6, first row. Page 7 Clear Display.

    lcd_Command(0x02); //Return home
    lcd_Command(0x80);
    lcd_Command(0x0E);

    TIM6delay_ms(1000);
}

 

void lcd_Send(uint8_t data) {

    while((I2C2->ISR & I2C_ISR_BUSY) == (I2C_ISR_BUSY));
    while(!((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE))); // Check Tx empty

 

    I2C1->TXDR = data; // Byte to send
    I2C1->CR2 |= I2C_CR2_START; // Go
    

 

 

    while(!((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)));
    while((I2C2->ISR & I2C_ISR_BUSY) == (I2C_ISR_BUSY));

}


void lcd_FirstCommand(void) {
    // I am sending 0x33 followed by 0x32. The delays are from datasheet

    // the data is sent as EN changes from High to Low


    lcd_Send(0x03 |(backlightState & 0x01) << BL);
    lcd_Send(0x03 | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(0x03|((backlightState & 0x01) << BL));

 

    TIM6delay_us(4100);


    lcd_Send(0x03|(backlightState & 0x01) << BL);
    lcd_Send(0x03 | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(0x03|((backlightState & 0x01) << BL));

 

 

    TIM6delay_us(100);

 

    lcd_Send(0x03|((backlightState & 0x01) << BL));
    lcd_Send(0x03 | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(0x03|((backlightState & 0x01) << BL));

 

    lcd_Send(0x02|((backlightState & 0x01) << BL));
    lcd_Send(0x02 | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(0x02|((backlightState & 0x01) << BL));

}

 

 

void lcd_Command(uint8_t com) {

 

    uint8_t data = 0;

    data |= (backlightState & 0x01) << BL;

    data |= (((com & 0x10) >> 4) << DB4);
    data |= (((com & 0x20) >> 5) << DB5);
    data |= (((com & 0x40) >> 6) << DB6);
    data |= (((com & 0x80) >> 7) << DB7);

 

    lcd_Send(data);
    lcd_Send(data | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(data);

 

 


    data = 0;

    data |= (backlightState & 0x01) << BL;

    data |= (((com & 0x01) >> 0) << DB4);
    data |= (((com & 0x02) >> 1) << DB5);
    data |= (((com & 0x04) >> 2) << DB6);
    data |= (((com & 0x08) >> 3) << DB7);

 

 

    lcd_Send(data);
    lcd_Send(data | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(data);
}

 

void lcd_Backlight(uint8_t state) {
    backlightState = (state & 0x01) << BL;
    lcd_Send(backlightState);

}

 

void lcd_Data(uint8_t com) {
    uint8_t data = 0;

 

// this differes "data" from "command" . Data - symbol to be displayed
    data |= (1 << RS);

 

    data |= (backlightState & 0x01) << BL;

    data |= (((com & 0x10) >> 4) << DB4);
    data |= (((com & 0x20) >> 5) << DB5);
    data |= (((com & 0x40) >> 6) << DB6);
    data |= (((com & 0x80) >> 7) << DB7);

    

    lcd_Send(data);
    lcd_Send(data | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(data);

 

 

 


    data = 0;

    data |= (1 << RS);

 

    data |= (backlightState & 0x01) << BL;

    data |= (((com & 0x01) >> 0) << DB4);
    data |= (((com & 0x02) >> 1) << DB5);
    data |= (((com & 0x04) >> 2) << DB6);
    data |= (((com & 0x08) >> 3) << DB7);

 

    lcd_Send(data);
    lcd_Send(data | (1 << EN));
    TIM6delay_us(2);
    lcd_Send(data);

}

 

I am sorry for such a long question. Thank You very much for Your time!

Outcomes