忍者ブログ

覚え書き

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

[PR]
×

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

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



STM32F030F4P6でLCD表示を行いました。
LCDは1602規格のもので、市場に安価に大量に出回っているので、供給についての不安は無用だと思います。

/*
**                     Main.c
**                     LCD1602
**                     EmBitz
**
**                     A1-Input      ボタン
**                     A2-Output    RS
**                     A3-Output    E
**                     A4-Output    D4
**                     A5-Output    D5
**                     A6-Output    D6
**                     A7-Output    D7
**
**  空のprojectを作成し、設定をhexファイルが取得できるように変更して、
**  main.cにこの文章をcopy&pasteして、コンパイルすれば完成です
**
**********************************************************************/
/*
   Last committed:     $Revision:   16 $
   Last changed by:    $Author:     Masaomi.Takahashi.$
   Last changed date:  $Date:       2019-08-09
   ID:                 $Id:         0002$
**********************************************************************/
#include "stm32f0xx.h"

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-Rs
    GPIOA -> MODER |= (1<<6);   // ピン A - 3 を出力モードに lcd-E
    GPIOA -> MODER |= (1<<8);   // ピン A - 4 を出力モードに lcd-D4
    GPIOA -> MODER |= (1<<10);  // ピン A - 5 を出力モードに lcd-D5
    GPIOA -> MODER |= (1<<12);  // ピン A - 6 を出力モードに lcd-D6
    GPIOA -> MODER |= (1<<14);  // ピン A - 7 を出力モードに lcd-D7

    lcd_init();                         // lcd初期設定

    lcd_clear();                        // 全消去
    lcd_put_str("STM32F030F4P6");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("Make By EmBitz");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("Vol.1.03");

    delay_ms(2500);

    lcd_clear();                        // 全消去
    lcd_put_str("ワレワレハシンリャクシャダ ト");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("イッテミル TEST");

    delay_ms(7000);

while(1){

    if(!(GPIOA->IDR & GPIO_IDR_1)){

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("ワレワレテキニハ コノワクセイヲ");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("シハイカニオク ヨテイデアル");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("タダシ イカノ");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("アンゴウ ヲ");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("カイドクデキタラ ");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("カンベンシテヤル");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("1899190119251968");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("1975197919922011");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("20192027");
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("ヒント ハ  - ワクセイ -");

    delay_ms(7500);

    lcd_clear();                        // 全消去
    lcd_put_str("ドウカ・・・");       // "ドウカ・・・"表示
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("セカイガヘイワデスヨウニ");

    delay_ms(7000);

    } else {
    delay_ms(500);

    lcd_clear();                        // 全消去
    lcd_put_str("Hello World!!");       // "Hello World!!"表示
    lcd_position(0,1);                  // カーソル位置 桁0,行1
    lcd_put_str("コンニチハ セカイ!!");

}   }   }

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

//---------- LCD初期化 ----------
void lcd_init()
{
    delay_ms(30);
    lcd_put_4bit(0x30, 1);  //8bit mode set
    delay_ms(5);
    lcd_put_4bit(0x30, 1);  //8bit mode set
    delay_ms(1);
    lcd_put_4bit(0x30, 1);  //8bit mode set
    delay_ms(1);
    lcd_put_4bit(0x20, 1);  //4bit mode set
    delay_ms(1);
    lcd_put_cmd(0x2E);      //DL=0 4bit mode
    lcd_put_cmd(0x08);      //display off C=D=B=0
    lcd_put_cmd(0x0D);      //display on C=D=1 B=0
    lcd_put_cmd(0x06);      //entry I/D=1 S=0
    lcd_put_cmd(0x02);      //cursor home
}

//---------- 表示位置設定 ----------
//      tx:x座標  ty:y座標
void lcd_position(char tx, char ty)
{
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin4をOffにする(コマンドデータ)
    lcd_put_cmd(0x80 | tx | (0x40 * ty));
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする(表示データ)
}

//---------- データ4bit出力 ----------
//      code:DB4~DB7 に与えるデータ
//      flag:0=表示モード 1=コマンドモード
void lcd_put_4bit(char code, int flag)
{
    if(code & 0x80)
        GPIOA ->ODR |= (1<<7);  //GPIOA-Pin7をOnにする
    else
        GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7をOffにする
    if(code & 0x40)
        GPIOA ->ODR |= (1<<6);  //GPIOA-Pin6をOnにする
    else
        GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6をOffにする
    if(code & 0x20)
        GPIOA ->ODR |= (1<<5);  //GPIOA-Pin5をOnにする
    else
        GPIOA ->ODR &= ~(1<<5); //GPIOA-Pin5をOffにする
    if(code & 0x10)
        GPIOA ->ODR |= (1<<4);  //GPIOA-Pin4をOnにする
    else
        GPIOA ->ODR &= ~(1<<4); //GPIOA-Pin4をOffにする
    if (flag == 0)
        GPIOA ->ODR |= (1<<2);  //GPIOA-Pin2をOnにする(表示データ)
    else
        GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする(コマンドデータ)

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

//---------- 1文字出力 ----------
//      ch:出力するデータ
void lcd_put_ch(char ch)
{
    lcd_put_4bit(ch, 0);    //上位4bit出力
    lcd_put_4bit(ch<<4, 0); //下位4bit出力
    delay_us(50);
}


//---------- コマンド出力 ----------
//      cmd:コマンド
void lcd_put_cmd(char cmd)
{
    lcd_put_4bit(cmd, 1);   //上位4bit出力
    lcd_put_4bit(cmd<<4, 1);//下位4bit出力
    delay_ms(2);               //2msec待ち
}

//---------- 全消去 ----------
void lcd_clear()
{
  lcd_put_cmd(0x01);        //初期化コマンド出力
  delay_ms(15);                //15msec待ち
}


        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--;
}   }


以上をEmBitzで新規に作成したProjectのmain.cにまるごとコピペして、コンパイルすれば(ライブラリ等を新たに設定しなくても)動きます。
注意点は、LCDのEとRS端子の間にあるRW端子をGNDに繋げてやらないとダメ、という点です。
これが判らなくて、私は延々とドツボにはまり続けました。

なお、プログラムの主要部分は、

ohkinというブログの、

STM32と Arduino IDE で
液晶ディスプレイに文字表示(その1)
~ライブラリ未使用~

という記事を参考(丸パクリ)にさせていただきました。


なお、delayに関しては、完全に「適当」です。一切計測とかしてません。カンです。動いたから、そのままにしているだけです。他のプログラムにこれを流用して、そのままタイミングをとるとか無茶なことをされても、一切責任は負いません。

あと、割り込みとかしてないので、delay中にボタンを押しても反応しません。ので、次の処理へ移行させるためには、延々とボタンを押し続ける必要があります。

ちなみに、このプログラムによって使用される容量は4.5KBぐらい。
STM32F030F4P6のメモリは16KBだから、メインの処理を他に作って、こちら(ディスプレイ表示)を隠しモードとして潜ませておく、なんて事も可能ではないかと思います。

STM32F030F4P6はものすごく安くて高性能なので、もっと使いこなせるようになりたいです。

拍手[0回]

PR

コメント

コメントを書く