1

I have used this library to write something on my LCD screen. When I try to clear it with my own code, it doesn't work for some reason. Clearing text with library works fine. I'm using screen on 8-bit mode.

I have checked that the pins are configured the same way. I have used debugger to confirm that right bits are toggled in ODR.

main.c

#include "GPIO_Lib.h"
#include "systick_lib.h"
#include "lcd.h"

int main(void) {

    GPIOA_enable_clock();
    GPIOB_enable_clock();

    init_lcd();
    write_data_pins(0x01);

    while (1);
}

lcd.h

#ifndef __LCD_H
#define __LCD_H

#include "GPIO_Lib.h"

pin_type data0;
pin_type data1;
pin_type data2;
pin_type data3;
pin_type data4;
pin_type data5;
pin_type data6;
pin_type data7;
pin_type RS;
pin_type RW;
pin_type E;

pin_type data_pins[8];

void init_lcd(void);
void write_data_pins(uint8_t data);

#endif

lcd.c

#include "lcd.h"
#include "systick_lib.h"

void init_lcd() {

    init_pin(&data0, GPIOA, 5, output, no_PUPD);
    init_pin(&data1, GPIOA, 6, output, no_PUPD);
    init_pin(&data2, GPIOA, 7, output, no_PUPD);
    init_pin(&data3, GPIOB, 6, output, no_PUPD);
    init_pin(&data4, GPIOB, 10, output, no_PUPD);
    init_pin(&data5, GPIOB, 4, output, no_PUPD);
    init_pin(&data6, GPIOB, 5, output, no_PUPD);
    init_pin(&data7, GPIOB, 3, output, no_PUPD);
    init_pin(&RS, GPIOB, 8, output, no_PUPD);
    //init_pin(&RW, GPIOA, 6, output, no_PUPD); // connected to GND
    init_pin(&E, GPIOB, 9, output, no_PUPD);

    data_pins[0] = data0;
    data_pins[1] = data1;
    data_pins[2] = data2;
    data_pins[3] = data3;
    data_pins[4] = data4;
    data_pins[5] = data5;
    data_pins[6] = data6;
    data_pins[7] = data7;


}

void write_data_pins(uint8_t data) {
    write_pin(&RS, LOW);
    write_pin(&E, LOW);

    for (int i = 0; i < 8; i++) {
        write_pin(&(data_pins[i]), (data >> i) & 0x01);
    }

    write_pin(&E, HIGH);
    delay(1);
    write_pin(&E, LOW);
}


GPIO_lib.c

#include "GPIO_Lib.h"

void GPIOA_enable_clock(void) {
    RCC->AHB1ENR |= 0x1u;
}

void GPIOB_enable_clock(void) {
    RCC->AHB1ENR |= 0x2u;
}

void GPIOC_enable_clock(void) {
    RCC->AHB1ENR |= 0x4u;
}

void GPIOD_enable_clock(void) {
    RCC->AHB1ENR |= 0x8u;
}

void GPIOE_enable_clock(void) {
    RCC->AHB1ENR |= 0x10u;
}

void GPIOH_enable_clock(void) {
    RCC->AHB1ENR |= 0x80u;
}

void init_pin(pin_type* pin, GPIO_TypeDef* _gpio, uint32_t _pin_num, uint32_t _mode, uint32_t _PUPD) {
    pin->gpio = _gpio;
    pin->mode = _mode;
    pin->pin_num = _pin_num;
    pin->PUPD = _PUPD;

    pin->gpio->MODER |= pin->mode << ((pin->pin_num * 2));
    pin->gpio->PUPDR |= pin->PUPD << ((pin->pin_num * 2));

    write_pin(pin, LOW);
}

void set_input(pin_type* pin) {
    pin->gpio->MODER &= ~(3u << ((pin->pin_num * 2)));
    
}

void set_output(pin_type* pin) {
    pin->gpio->MODER |= output << ((pin->pin_num * 2));
    
}

pin_state write_pin(pin_type* pin, pin_state state) {
    if (state == HIGH) {
        pin->gpio->ODR |= (1u << pin->pin_num);
    } else {
        pin->gpio->ODR &= ~(1u << pin->pin_num);
    }

    return state;
}

pin_state read_pin(pin_type* pin) {
    uint8_t state = ( pin->gpio->IDR >> pin->pin_num) & 1u;

    if (state == 1) {
        return HIGH;
    }

    return LOW;
}
pin_state toggle_pin(pin_type* pin) {
    pin->gpio->ODR ^= (1u << pin->pin_num);

    return read_pin(pin);
}

systick_lib.c

#include "systick_lib.h"
#include "systick_registers.h"

void delay(uint32_t ms) {
    systick_reg->LOAD |= 16000u - 1;
    systick_reg->CTRL |= 5u;

    for (int i = 0; i < ms; i++) {
        while (!(systick_reg->CTRL & (1u << 16u)));

    }

    systick_reg->LOAD = 0;
    systick_reg->CTRL = 0;
}

void delay_micros(uint32_t micros) {
    systick_reg->LOAD |= 16u - 1;
    systick_reg->CTRL |= 5u;

    for (int i = 0; i < micros; i++) {
            while (!(systick_reg->CTRL & (1u << 16u)));

    }

    systick_reg->LOAD = 0;
    systick_reg->CTRL = 0;
}

How library clears the display

#define CLEAR_DISPLAY 0x01
#define LCD_COMMAND_REG 0
#define LCD_BYTE 8
#define DELAY(X) HAL_Delay(X)

void Lcd_clear(Lcd_HandleTypeDef * lcd) {
    lcd_write_command(lcd, CLEAR_DISPLAY);
}

void lcd_write_command(Lcd_HandleTypeDef * lcd, uint8_t command)
{
    HAL_GPIO_WritePin(lcd->rs_port, lcd->rs_pin, LCD_COMMAND_REG);      // Write to command register

    if(lcd->mode == LCD_4_BIT_MODE)
    {
        lcd_write(lcd, (command >> 4), LCD_NIB);
        lcd_write(lcd, command & 0x0F, LCD_NIB);
    }
    else
    {
        lcd_write(lcd, command, LCD_BYTE);
    }

}

void lcd_write(Lcd_HandleTypeDef * lcd, uint8_t data, uint8_t len)
{
    for(uint8_t i = 0; i < len; i++)
    {
        HAL_GPIO_WritePin(lcd->data_port[i], lcd->data_pin[i], (data >> i) & 0x01);
    }

    HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, 1);
    DELAY(1);
    HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, 0);        // Data receive on falling edge
}
togen
  • 11
  • 2
  • 1
    Try using scope/logic analyzer to compare the commands you send with your code and library. Obviously, if LCD were to receive your command, it would have performed the action. So something clearly isn't getting delivered. Are you sure your for loop does what it's supposed to do? And nothing is messed up in it? Looks like the weakest link in chain. Does sending just 0x01 work? Is delay between pin toggles &E enough? Maybe put a delay before for loop? – Ilya Nov 13 '21 at 09:27
  • Have you debugged the code? What do the custom libraries do, the gpio and delay implementations may have errors. Show all code. How do you even write something to the display in order to clear it? The code also does not initialize the display, it assumes display is in 8-bit mode. – Justme Nov 13 '21 at 09:43
  • @Justme I have debugged the code and couldn't find any errors. When using library function to clear the display, I removed the initialization function to check if that makes any difference. Display is used in 8-bit mode. I added the missing custom libraries to my post. – togen Nov 13 '21 at 10:06
  • 1
    So how did you debug it? If you single-stepped through that code, you would know that IO pins to the LCD get written and the delay code works, in which case the display would get cleared. Maybe the IO pins to LCD are wired incorrectly? – Justme Nov 13 '21 at 10:34

0 Answers0