Sim's blog

電子工作はじめてみました

ATMega329Pで生LCDを動かしてみました

2009-10-06 23:32:52 | AVR
ATMega329Pメモの続きになります。

ATMega329Pで生LCDの駆動をしてみました。

全桁点灯です。LCDはダイセンLCDP81です。このLCDパネルは1/3dutyなので、LCDのセグメントは3つのグループに分かれていて時分割でダイナミック点灯してやる必要があります。ATMega329Pは1/4duty、25セグメントまで対応しているので、問題なく使えます(LCDP81のセグメントは24本)。

コモン3本とセグメント24本の計27本をつないでいるので、線がもじゃもじゃです。


ストロベリーリナックスのジャンパーワイヤって、黒い部分が太いのでブレッドボードに並べて挿すことができません。そのせいで互い違いになるように挿しています。

LCDP81は千石の2Fで入手しました。以前、のりたんさんも使っておられました(記事)。1年以上も前に入手したものみたいです(記事)。ようやっと点けることができました。

ATMega329Pでの使い方です。ハードの方は1pinに0.47uFより大きいコンデンサをつけます。今回は1uFの電解コンデンサをつけています。後はLCDとの間を配線するだけです。ソフトの方は、4つある制御レジスタを使って初期化した後、LCDDRnというレジスタをビット操作することでセグメントの点灯/消灯を制御できます。

今回は電源電圧3V、内蔵の8MHzクロックで動作させています。

ソースです(<と>が全角になっています)。
#include <avr/io.h>

int main()
{
    // LCD初期設定

    // 安全のために関連ポートは全て0出力にしておく
    PORTA = 0x00; // COM0-3, SEG0-3
    DDRA = 0xff;
    PORTC = 0x00; // SEG5-12
    DDRC = 0xff;
    PORTD = 0x00; // SEG15-22
    DDRD = 0xff;
    PORTG = 0x00; // SEG23(PG4) SEG24(PG3) SEG4(PG2) SEG13(PG1) SEG14(PG0)
    DDRG = 0x1f;
    // LCDで未使用はPB、PE、PF

    // (1) LCDCRB
    // +--------- LCDCS クロック選択 0:システムクロック 1:外部クロック
    // |+-------- LCD2B バイアス選択 0:1/3バイアス 1:1/2バイアス
    // ||++------ LCDMUX1,0 1/3dutyのとき10
    // ||||++++-- LCDPM2-0 LCDポート遮蔽 24のとき0110
    // 00100110
    LCDCRB = 0b01100110;

    // (2) LCDFRR
    //  +++------ LCDPS2-0 N : プリスケール 111: clk/4096
    //  ||| +++-- LCDCD2-0 D : クロック分周選択 000:1分周 111:8分周
    // 01110101
    // f = clk / (K * N * D) = 8MHz / (6*4096*8) = 41Hz
    LCDFRR = 0b01110101;

    // (3) LCDCCR
    // 
    // +++------- LCDDC2-0 111:clkの半分駆動
    // |||+------ LCDMDT 1:最大駆動時間
    // ||||++++-- LCD濃淡制御 1000:3.00V 1110:3.3V
    // 11101000
    LCDCCR = 0b11101000;

    // (4) LCDCRA
    // +--------- LCDEN  1:LCD許可 0:禁止
    // |+-------- LCDAB  1:低電力波形 0:通常波形
    // || +------ LCDIF  割り込み要求フラグ
    // || |+----- LCDIE  1:割り込み許可 0:割り込み禁止
    // || ||+---- LCDBD  0:バッファあり 1:なし(省電力)
    // || |||+--- LCDCCD 0:内部給電 1:外部給電
    // || ||||+-- LCDBL  0:LCD表示  1:LCD無表示
    // 10000000
    LCDCRA = 0b10000000;

    // 全部点灯
    // COM0
    LCDDR00 = 0xff;
    LCDDR01 = 0xff;
    LCDDR02 = 0xff;

    // COM1
    LCDDR05 = 0xff;
    LCDDR06 = 0xff;
    LCDDR07 = 0xff;

    // COM2
    LCDDR10 = 0xff;
    LCDDR11 = 0xff;
    LCDDR12 = 0xff;

    // 無限ループ
    while(1) ;
}

数字を出すのは今後の課題です。