【求む、AVR強者】ATmega8 × RustでLCDが文字化けする怪を解決できなかった話
敗北宣言、そして情報提供のお願い
前回のLチカ成功から一転、LCD(1602)の壁に跳ね返されました。 結果としてC言語に回帰して解決はしたのですが、今後の「Rustマイコン道」のためにも、なぜダメだったのかを記録しておきます。もし原因に心当たりがある方がいれば、ぜひ教えてください。
発生した現象
hd44780-driver を使い、4bitモードで接続。
期待した文字列ではなく、常に「■■■■」や謎のカタカナが並ぶ文字化け状態に。
当時のコード(抜粋)
let mut lcd = Hd44780::new_4bit(
pins.d4.into_output(), // RS
pins.d5.into_output(), // E
pins.d0.into_output(), // D4
pins.d1.into_output(), // D5
pins.d2.into_output(), // D6
pins.d3.into_output(), // D7
&mut delay,
);
lcd.reset();
lcd.clear();
lcd.set_display_mode(DisplayMode {
display: Display::On,
cursor: Cursor::Off,
blink: Blink::Off,
});
lcd.write_str("Hello Rust!");
疑っているポイント
1. クロック周波数の不一致
Cargo.toml や環境変数で指定している AVR_CPU_FREQUENCY_HZ と、実際にATmega8が動作しているクロック(内部RC 1MHz / 8MHzなど)が食い違っているせいで、delay の精度が死んでいる可能性。
2. 4bitモードの初期化タイミング
HD44780のデータシートにある「電源投入後の待機時間」や「3回コマンドを送る」シーケンスが、ドライバ側で意図通りに動いていない?
3. 最適化によるタイミング崩れ
opt-level = "z" でビルドした際、必要なウェイト時間がコンパイラに削られてしまっている?
結局、C言語(avr-gcc)では動いた
同じ配線のまま、C言語で _delay_ms() を使いながら丁寧に初期化を書くと、あっさり表示されました。
「Cで動くならハードの問題ではない」ことは確定していますが、Rustでスマートに動かせなかったのが心残りです。