忍者ブログ

覚え書き

パソコン・マイコン関連の、あとで必要になりそうな情報を残しておくための、健忘録てきななにかです。

[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

STM32F030F4P6で5110LCD表示(EmBitz-サンプルプログラム)


またしても、STM32F030F4P6でLCD表示を行う記事です。
今回はNokia5110というグラフィック液晶ディスプレーです。
1602よりも若干高めで、そもそも、供給源が解体された携帯電話からの回収部品であるために、市場からは1602よりも早く駆逐されてしまうと思いますが、決められたキャラクター文字しか表示できない1602よりも、表現力は上で、使い勝手は圧倒的に勝るはずです。

とはいえ、まだ「表示できた」というだけのレベルで、文字や記号を表示するには至っていません。

今回は、「ちゃんと制御できた」ということを検証するためのデモプログラムという事になりますが、ここまでくればあとはどうにでもなるんじゃないかな? と思います。
とにかく、「ここまで来る道のり」が厳しかったです。


/*
**********************************************************************
**
**                     Main.c
**                     SPI-5110
**                     EmBitz
**
**                      A1-Input    (現在は未使用)
**                      A5-Output    RS  (Reset)
**                      A6-Output    CE  (Master In Slave Out:Low=GND)
**                      A7-Output    DC  (Data/Command:Data=High_Command=Low)
**                      A2-Output    DIN (Serial Input:送信Data)
**                      A3-Output    CLK (Serial Clock)
**                      A4-Output    LED (DL)
**
**  空のprojectを作成し、設定をhexファイルが取得できるように変更して、
**  main.cにこの文章をcopy&pasteして、コンパイルすれば完成です
**
**
**********************************************************************/
/*
    Last committed:     $Revision:   27X$
    Last changed by:    $Author:     Masaomi.Takahashi.$
    Last changed date:  $Date:       2019-09-01
    ID:                 $Id:         0025
**********************************************************************/
#include "stm32f0xx.h"

int tt,tx;            //画面更新のタイミング。Belay間隔。tx=実効値。tt=初期値。
int k;                //描写する幅を少しずつ減らしてゆく為の変数。
int main(void)
{
    RCC   ->AHBENR |= (1<<17);  // GPIO-Aの初期化(最初は0クロックで無可動状態)
    GPIOA -> IDR   |= (1<<2);       // ピン A - 1 を入力モードに
    GPIOA -> PUPDR |= (1<<2);   // ピン A - 1 を プルアップ指定

    GPIOA -> MODER |= (1<<4);   // ピン A - 2 を出力モードに lcd-MOSI    送信データ。
    GPIOA -> PUPDR |= (1<<4);   // ピン A - 2 を プルアップ指定
    GPIOA -> MODER |= (1<<6);   // ピン A - 3 を出力モードに lcd-CLK     クロック
    GPIOA -> PUPDR |= (1<<6);   // ピン A - 3 を プルアップ指定
    GPIOA -> MODER |= (1<<8);   // ピン A - 4 を出力モードに lcd-LED     赤=Low/青=Highで点灯
    GPIOA -> PUPDR |= (1<<8);   // ピン A - 4 を プルアップ指定
    GPIOA -> MODER |= (1<<10);  // ピン A - 5 を出力モードに lcd-RS      リセット
    GPIOA -> PUPDR |= (1<<10);  // ピン A - 5 を プルアップ指定
    GPIOA -> MODER |= (1<<12);  // ピン A - 6 を出力モードに lcd-CE      入力データ (Low=GND)
    GPIOA -> PUPDR |= (1<<12);  // ピン A - 6 を プルアップ指定
    GPIOA -> MODER |= (1<<14);  // ピン A - 7 を出力モードに lcd-DC      データ/コマンド
    GPIOA -> PUPDR |= (1<<14);  // ピン A - 7 を プルアップ指定

    GPIOA ->ODR &= ~(1<<2);     //GPIOA-Pin2をOffにする
    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする
    GPIOA ->ODR &= ~(1<<4);     //GPIOA-Pin4をOffにする LEDなので、Onでも可
    GPIOA ->ODR &= ~(1<<5);     //GPIOA-Pin5をOffにする
    GPIOA ->ODR &= ~(1<<6);     //GPIOA-Pin6をOffにする
    GPIOA ->ODR &= ~(1<<7);     //GPIOA-Pin7をOffにする

    delay_us(1);
    lcd_init();

while(1){
tt=850;

while(tt>=0){

    if (tt>=550)
    tx=tt-550;
    else
    tx=0;

    lcd_position(0,0);
    int i=84*6;
    while(i>0){
        lcd_put_ch(0xFF);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x7F);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x3F);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x1F);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x0F);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x07);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x03);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x01);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0x00);
    i--;
    }
    delay_ms(tx);

    lcd_position(0,0);
    i=84*6;
    while(i>0){
        lcd_put_ch(0xFF);
    i--;
    }
    delay_ms(tx);

    k=7;
    while(k>0){
    lcd_position(0,0);
    i=84*6;
    int j=0;
    while(i>0){
    j++;
    if (j>=k){
        lcd_put_ch(0x00);
//        j=0;
    }
    else{
        lcd_put_ch(0xFF);
    }
    if (j>=7){
    j=0;
    }
    i--;
    }
    delay_ms(tx);
    k--;
    }
    tt=tt-25;
    }   }   }


//---------- 文字列出力 ----------
//      *str:文字列の先頭ポインタ
void lcd_put_str(char *str)
{
    while(*str != 0){
        lcd_put_ch( *str );
        str++;
    }
}

//---------- LCD初期化 ----------
void lcd_init()
{
    GPIOA ->ODR &= ~(1<<5); //GPIOA-Pin5(RS)をOffにする
    GPIOA ->ODR |= (1<<5);  //GPIOA-Pin5(RS)をOnにする

    delay_ms(2);

    GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする

    lcd_put_cmd(0x21);      //Extended Commands.
    lcd_put_cmd(0xAF);      //Contrast Vop=6.4V
    lcd_put_cmd(0x04);      //Set Temp coefficent.
    lcd_put_cmd(0x13);      //LCD bias mode 1:48.
    lcd_put_cmd(0x20);      //Standard Commands.
    lcd_put_cmd(0x0C);      //Normal mode
    lcd_clear();            //Screen Clear.
}

//---------- 表示位置設定 ----------
//      xx:x座標  yy:y座標
void lcd_position(int xx, int yy)
{
    lcd_put_cmd(0x80 | xx | (0x40 * yy));
}

//---------- データ4bit出力 ----------
void lcd_put_4bit(char code)
{

    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする
    if(code & 0x80)
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする
        else
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする

    GPIOA ->ODR |= (1<<3);      //GPIOA-Pin3をOnにする
    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする
    if(code & 0x40)
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする
        else
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする

    GPIOA ->ODR |= (1<<3);      //GPIOA-Pin3をOnにする
    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする
    if(code & 0x20)
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする
        else
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする

    GPIOA ->ODR |= (1<<3);      //GPIOA-Pin3をOnにする
    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする

    if(code & 0x10)
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする
        else
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする

    GPIOA ->ODR |= (1<<3);      //GPIOA-Pin3をOnにする

}

//---------- 1文字出力 ----------
//      ch:出力するデータ
void lcd_put_ch(char ch)
{

    GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする
    GPIOA ->ODR |= (1<<7);  //GPIOA-Pin7(DC)をOnにする
    lcd_put_4bit(ch);       //上位4bit出力
    lcd_put_4bit(ch<<4);    //下位4bit出力

    GPIOA ->ODR |= (1<<6);  //GPIOA-Pin6(CE)をOnにする

}

//---------- コマンド送信 ----------
void lcd_put_cmd(char cmd)
{

    GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする
    GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7(DC)をOffにする
    lcd_put_4bit(cmd);   //上位4bit出力
    lcd_put_4bit(cmd<<4);//下位4bit出力

    GPIOA ->ODR |= (1<<6);  //GPIOA-Pin6(CE)をOnにする

}

//---------- 塗りつぶし(消去) ----------
void lcd_clear()
{
    lcd_position(0,0);
    int i=84*6;
    while(i>0){
        lcd_put_ch(0x00);
    i--;
}    }

void delay_ms(uint32_t i)
{
    i=i*100;
    while(i>0){
        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");
        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");
        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");
        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");
    i--;
}   }

void delay_us(uint32_t i)
{
    while(i>0){
        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");        asm("NOP");
    i--;
}   }


以上。
恥ずかしくて顔が真っ赤になるような稚拙なプログラムかもしれませんが、所詮は専門的な教育を受けていない素人が、独学で好き勝手やっていることですので、ご理解ください。
(とりあえず、「無駄」とか「美しさ」とかは横に置いておいて、「動けばいい」、というスタンスです)



現在、回路はこんな感じでまとまっています。
消費電力は液晶付きでも10mA未満(簡易計測出来る限界未満)なので、この状況下では不満はないです。




配線はこんな感じ。
基板に落としこむ際に、Youtubeにアップロードした時とPinが随分変更されたのですが、「どうでもいい」話ですね。

この回路だと、USB端子を差しこめば動いてくれるので、ブレッドボードに沢山配線をぶっ刺していた頃と比べて、劇的に検証が楽になっています。

最後に。

この液晶(5110)に対して、STM32は一方的にデータを送信するだけの関係なので、LCDを回路から取り外しても、プログラムの挙動は変わりません。

ですので、ピンに余裕があるのでしたら、LCDはあくまでもシステムを管理する際の補助として使用し、普段はLDCを外して使用する、なんてことが可能です。



プログラムが正常に作動しているかどうかをチェックするだけなら、LCDの代わりにLEDを刺しておいても、ある程度把握できるはずです。

拍手[0回]

PR

コメント

コメントを書く