JohnDoneth / hd44780-driver

Implementation of the embedded-hal traits for the HD44780.
MIT License
37 stars 40 forks source link

issue working with stm32f1x-hal #43

Closed Njolf closed 1 year ago

Njolf commented 1 year ago

Hello. I'm new to embedded rust, and rust in general so this could be a trivial error. I've adapted the stm32f3x i2c example to run with the stm32f1x-hal (i have an STM32F103C8T6 blue pill board). It compiles without errors, and the semihosting debug messages all print to the open-ocd console. my display lights up, but doesn't show any text. I've run an arduino i2c detector and found the i2c address of my lcd screen to be 39 (decimal)/ 0x27 (hex). I could've made a mistake whilst trying to adapt the example to work with the f1x-hal, but i would expect it to throw errors during compile or runtime if that were the case. I've used 2 lcd screens with identical backpacks, to rule out a faulty lcd as a potential problem. here's the code:

#![no_std]
#![no_main]

use panic_halt as _;

use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use stm32f1xx_hal::{ pac, prelude::*, i2c::{ BlockingI2c, DutyCycle, Mode }, flash::FlashExt };
use hd44780_driver::{ Cursor, CursorBlink, Display, DisplayMode, HD44780 };

#[entry]
fn main() -> ! {
    let device_periph = pac::Peripherals::take().unwrap();

    let mut flash = device_periph.FLASH.constrain();
    let rcc = device_periph.RCC.constrain();
    let mut afio = device_periph.AFIO.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    let mut gpiob = device_periph.GPIOB.split();

    let scl_pin = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl);
    let sda_pin = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl);

    const I2C_ADDRESS: u8 = 0x27;

    let i2c = BlockingI2c::i2c1(
        device_periph.I2C1,
        (scl_pin, sda_pin),
        &mut afio.mapr,
        Mode::Fast {
            frequency: (400).kHz(),
            duty_cycle: DutyCycle::Ratio16to9,
        },
        clocks,
        1000,
        10,
        1000,
        1000
    );

    let mut delay = device_periph.TIM2.delay_us(&clocks);
    let lcd = HD44780::new_i2c(i2c, I2C_ADDRESS, &mut delay);
    let mut lcd = lcd.unwrap();
    hprintln!("lcd unwrapped");
    let _lcd_reset_result = lcd.reset(&mut delay);
    hprintln!("lcd reset");
    let _lcd_clear_result = lcd.clear(&mut delay);
    hprintln!("lcd cleared");
    let _lcd_display_mode_result = lcd.set_display_mode(
        DisplayMode {
            display: Display::On,
            cursor_visibility: Cursor::Visible,
            cursor_blink: CursorBlink::On,
        },
        &mut delay
    );
    hprintln!("lcd display mode set");
    let mut _write_str_result = lcd.write_str("Hello World", &mut delay);
    hprintln!("string written to lcd");
    loop {
    }
}

It throws no errors/warnings when compiling as i said, which is mainly why most of the changes were made. My i2c backpack has a PCF8574T chip on it, not sure if that would be a problem (really only mentioning this because the i2c address was different in the example too). Any help would be greatly appreciated!

Njolf commented 1 year ago

I solved it. my I2C backpack had a physical contrast trimpot, and neither of the screens was tuned properly. playing around with it fixed the issue, string wrote to the lcd properly.