忍者ブログ

覚え書き

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

  • [PR]
    ×

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

  • STM32F030F4P6で7735LCD表示(主文)
    またしても、STM32F030F4P6でLCD表示を行う記事です。

    今回は7735というチップで制御されたカラー液晶ディスプレーです。


    表示能力は、128x128で、色数は18ビットモードと16ビットモードの2種類から選択出来るようです。
    5110より明らかに高性能なのですが、1画面分のデータ量が増える分、速度的には不利になるので、全ての面でNokiaに勝るというわけではありません。
    とはいえ、84x48ドットモノクロのNokiaと128x128ドットフルカラーの7735では、画面の情報量が圧倒的に違いますし、機能も多いので、使い勝手は7735の方が上だと思います。
    ですが、この程度のシステムでも一瞬で画面が書き換わるNokia5110も十分に魅力的です。

    さて。
    この「忍者ブログ」には、1つの記事あたりの文字数に制限があるようで、それに引っかかってしまいました。
    プログラムコードの部分だけなら通ったので、今回は、主文とソースが別れました。

    今回のプログラムを作成するに当たっては、

    ブログサイト「何かの足跡」様のST7735B 1.8" TFT SPI
    という記事や、
    ブログサイト「ネコ技研」様のTFT液晶LCD+AVRマイコンで自作フォントを表示
    という記事が大変参考になりました。

    また、STM32F030F4P6そのものに関しては、
    ブログサイト「おじさん工房」様の実験用マイコン基板 STM-1という記事の意見が参考になりました。
    この場を借りて、お礼を述べさせて頂きます。
    ありがとうございました。

    さて。
    「おじさん工房」の主様は、「20pin-16KBじゃ足りなすぎる」ということで、1ランク上の「STM32F030K6T6(32pin-32KB)」に移行して開発を進めましたが、私はそれを知りつつ、20pin-16KBのSTM32F030F4P6を使い続けております。

    だって。

    安かったから、まとめ買いで100個も買っちゃったんだもの。
    (STM32F030K6T6も幾つか持ってますけどね)


    プログラム的には、Nokia5110のものをベースに、コマンド周りを中心に変更しています。
    SPI通信に関しては、いわゆる「ソフトウェア式」のため、7735に対しては速度がかなり遅いようです。
    これを、「ハードウェア式」に改めた場合、高速化されるのか、それとも、ほとんど変わらないのか。
    その辺のことは、これから見定めて対応したいと思います。
    (7735のフルカラー画像が一瞬で表示されるような速度が確保できたなら、夢が一気にひろがりまくります)

    拍手[0回]

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





    /*
    **********************************************************************
    **
    **                     Main.c
    **                     SPI-7735(128x128 LCD)
    **                     EmBitz
    **
    **                      旧-現在
    **                      A5-A2-Output    RESRT/RS   (Reset)
    **                      A6-A6-Output    CS/CE      (Master In Slave Out:Low=GND)
    **                      A7-A5-Output    A0/DC
    **                          5110=PCD8544        (Data/Command:Data=High_Command=Low)
    **                          ST7735              (Data/Command:Data=High_Command=Low)
    **                      A2-A7-Output    SDA/DIN    (Serial Input/SDA:送信Data)
    **                      A3-A4-Output    SCK/CLK    (Serial Clock)
    **                      A4-A3-Output    LED        (Back Light)
    **
    **********************************************************************/
    /*
        Last committed:     $Revision:   31$
        Last changed by:    $Author:     Masaomi.Takahashi.$
        Last changed date:  $Date:       2019-09-15
        ID:                 $Id:         02
    **********************************************************************/
    #include "stm32f0xx.h"

    unsigned char w_00[][14]={
        { 23, 21, 22, 30,108, 21, 30,109, 22, 26,110,  0,  0,0xFF},    //  [00]    2019年09月15日
        {124,  2,128,  0, 24, 21,  2,127,  0, 21, 23,  0,  0,0xFF},    //  [01]    VER 30EZ02
        {115,  4,  3,  4,  0,  3, 12,127,  7,  2,107,  0,  0,0xFF},    //  [02]    MOLO LIZWE!
        {134,117,135,  8,  2,122,  0,136,135,117,  0,  0,  0,0xFF},    //  [03]
        {118,119,  0, 19, 20,  0,  0,  0,  0,  0,  0,  0,  0,0xFF},    //  [04]
        {  9, 12,  5,  4,  0,115,  4,116, 11,  4,107,  0,  0,0xFF},    //  [05]    CIAO MONDO!
        { 13, 14, 15, 16, 53,  0, 19, 20,  0,  0,  0,  0,  0,0xFF},    //  [06]    こんにちは 世界
        {  1,  2,  3,  3,  4,  0,  7,  4,128,  3, 11,107,  0,0xFF},    //  [07]    HELLO WORLD!
        {121,122,115, 24, 23,  6, 21, 24, 21,  6, 25,117, 27,0xFF}     //  [08]    STM32F030F4P6

    };

    unsigned char font[] =  {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   //  Space   0
        0x00, 0xFE, 0x10, 0x10, 0x10, 0x10, 0xFE,   //  H       1
        0x00, 0xFE, 0x92, 0x92, 0x92, 0x92, 0x82,   //  E       2
        0x00, 0xFE, 0x80, 0x80, 0x80, 0x80, 0x80,   //  L       3
        0x00, 0x38, 0x44, 0x82, 0x82, 0x44, 0x38,   //  O       4
        0xC0, 0x30, 0x2C, 0x22, 0x2C, 0x30, 0xC0,   //  A       5
        0x00, 0xFE, 0x12, 0x12, 0x12, 0x12, 0x02,   //  F       6
        0x3E, 0xC0, 0x30, 0x0C, 0x30, 0xC0, 0x3E,   //  W       7
        0x00, 0xFE, 0x92, 0x92, 0x92, 0x92, 0x66,   //  B       8
        0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x44,   //  C       9
        0x00, 0x38, 0x44, 0x82, 0x92, 0x92, 0x74,   //  G       10
        0x00, 0xFE, 0x82, 0x82, 0x82, 0x44, 0x38,   //  D       11
        0x00, 0x00, 0x82, 0xFE, 0x82, 0x00, 0x00,   //  I       12
        0x00, 0x40, 0xA4, 0x84, 0x84, 0x84, 0x80,   //  こ       13
        0x80, 0x60, 0x18, 0x66, 0x80, 0x80, 0x40,   //  ん       14
        0xFE, 0x00, 0x40, 0xA4, 0x84, 0x84, 0x80,   //  に       15
        0x00, 0x04, 0x24, 0x9C, 0x96, 0x94, 0x64,   //  ち       16
        0x48, 0x28, 0xFE, 0x08, 0x84, 0x84, 0x78,   //  わ       17
        0x00, 0x40, 0x80, 0x80, 0x80, 0x80, 0x7E,   //  J        18
        0x04, 0xFF, 0x84, 0xBF, 0xA4, 0xBF, 0x84,   //  世       19
        0x00, 0x5F, 0xF5, 0x3F, 0x1F, 0xF5, 0x5F,   //  界       20
        0x00, 0x7C, 0x82, 0x82, 0x82, 0x82, 0x7C,   //  0        21
        0x00, 0x00, 0x84, 0xFE, 0x80, 0x00, 0x00,   //  1        22
        0x00, 0xC4, 0xA2, 0xA2, 0x92, 0x92, 0x8C,   //  2        23
        0x00, 0x44, 0x82, 0x92, 0x92, 0x92, 0x6C,   //  3        24
        0x00, 0x60, 0x50, 0x48, 0x44, 0xFE, 0x40,   //  4        25
        0x00, 0x5E, 0x8A, 0x8A, 0x8A, 0x8A, 0x72,   //  5        26
        0x00, 0x7C, 0x92, 0x92, 0x92, 0x92, 0x74,   //  6        27
        0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06,   //  7        28
        0x00, 0x6C, 0x92, 0x92, 0x92, 0x92, 0x6C,   //  8        29
        0x00, 0x4C, 0x92, 0x92, 0x92, 0x92, 0x7C,   //  9        30
        0x40, 0xA4, 0xFE, 0x54, 0x34, 0x94, 0x60,   //  あ        31
        0x3C, 0x40, 0x80, 0x40, 0x04, 0x08, 0x30,   //  い        32
        0x00, 0x10, 0x8A, 0x8A, 0x8A, 0x4A, 0x30,   //  う        33
        0x00, 0x80, 0x4A, 0x2A, 0x7A, 0x80, 0x80,   //  え        34
        0x44, 0xA4, 0xFE, 0x14, 0x90, 0x94, 0x68,   //  お        35
        0x88, 0x68, 0x9E, 0x88, 0x70, 0x08, 0x30,   //  か        36
        0x00, 0x54, 0xB4, 0x94, 0x9C, 0xB4, 0x10,   //  き        37
        0x00, 0x10, 0x28, 0x28, 0x44, 0x82, 0x00,   //  く         38
        0x7E, 0x00, 0x08, 0x88, 0x7E, 0x08, 0x08,   //  け         39
        0x00, 0x48, 0xA8, 0x88, 0x8E, 0xB8, 0x08,   //  さ         40
        0x00, 0x00, 0x7E, 0x80, 0x80, 0x80, 0x40,   //  し         41
        0x04, 0x04, 0x14, 0xAC, 0x7E, 0x04, 0x04,   //  す         42
        0x08, 0x08, 0x7E, 0x88, 0xA8, 0xBE, 0x88,   //  せ         43
        0x00, 0x10, 0x12, 0x7A, 0x96, 0x92, 0x10,   //  そ         44
        0x84, 0x74, 0x0E, 0x44, 0xA8, 0x88, 0x88,   //  た         45
        0x08, 0x08, 0x04, 0x44, 0x44, 0x44, 0x38,   //  つ         46
        0x00, 0x04, 0x04, 0x34, 0x4A, 0x86, 0x82,   //  て         47
        0x00, 0x40, 0xAE, 0x90, 0x90, 0x88, 0x88,   //  と         48
        0x24, 0x14, 0x4E, 0xA4, 0xA0, 0x74, 0x48,   //  な         49
        0x60, 0x9C, 0x70, 0xA0, 0x1E, 0xC8, 0xF0,   //  ぬ.        50
        0x48, 0x28, 0xFE, 0x08, 0x44, 0xA4, 0x78,   //  ね         51
        0x30, 0x48, 0x24, 0x9C, 0x84, 0x48, 0x03,   //  の         52
        0xFE, 0x00, 0x48, 0xA8, 0xA8, 0x7E, 0x88,   //  は         53
        0x04, 0x74, 0x8E, 0x80, 0x82, 0x7C, 0x08,   //  ひ         54
        0x80, 0x60, 0x80, 0x9A, 0x64, 0x20, 0xC0,   //  ふ         55
        0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x20,   //  へ         56
        0xFE, 0x00, 0xD4, 0xD4, 0xFC, 0x54, 0x94,   //  ほ         57
        0x00, 0xD4, 0xD4, 0xD4, 0xFE, 0x54, 0x94,   //  ま         58
        0x60, 0x52, 0x32, 0x96, 0x90, 0x78, 0x20,   //  み         59
        0x24, 0x54, 0xFE, 0x84, 0x80, 0x84, 0x48,   //  む         60
        0x60, 0x9C, 0x70, 0xA8, 0x1E, 0x88, 0x70,   //  め         61
        0x00, 0x14, 0x7C, 0x96, 0x94, 0x94, 0x60,   //  も         62
        0x08, 0x0E, 0x38, 0xC4, 0x06, 0x14, 0x08,   //  や         63
        0x3C, 0x08, 0xA4, 0x7E, 0x24, 0x24, 0x18,   //  ゆ         64
        0x00, 0x40, 0xA0, 0xA0, 0x7E, 0x48, 0x88,   //  よ         65
        0x20, 0x14, 0x5C, 0xB6, 0xE4, 0x94, 0x90,   //  を         66
        0x00, 0x10, 0x1C, 0x70, 0x8C, 0x28, 0x10,   //  ゃ         67
        0x00, 0x38, 0x90, 0x7C, 0x48, 0x30, 0x00,   //  ゅ         68
        0x00, 0x40, 0xA0, 0xA0, 0x7C, 0x90, 0x00,   //  ょ         69
        0x00, 0x20, 0x20, 0x90, 0x90, 0x60, 0x00,   //  っ         70
        0x00, 0x40, 0xA8, 0xFC, 0x68, 0x28, 0xC0,   //  ぁ         71
        0x00, 0x78, 0x80, 0x40, 0x08, 0x30, 0x00,   //  ぃ         72
        0x00, 0x20, 0x94, 0x94, 0x54, 0x20, 0x00,   //  ぅ         73
        0x00, 0x90, 0x54, 0x74, 0x94, 0x80, 0x00,   //  ぇ         74
        0x00, 0x48, 0xFC, 0x28, 0xA0, 0x48, 0x00,   //  ぉ         75
        0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,   //  ー         76
        0x88, 0x68, 0x9E, 0x88, 0x72, 0x08, 0x32,   //  が         77
        0x00, 0x54, 0xB4, 0x96, 0x9C, 0xB6, 0x10,   //  ぎ         78
        0x00, 0x10, 0x28, 0x28, 0x44, 0x8A, 0x08,   //  ぐ         79
        0x7E, 0x00, 0x08, 0x88, 0x7E, 0x08, 0x0A,   //  げ         80
        0x00, 0x40, 0xA4, 0x84, 0x86, 0x84, 0x82,   //  ご         81
        0x00, 0x58, 0xA8, 0x88, 0x8E, 0xB8, 0x0A,   //  ざ         82
        0x00, 0x00, 0x7E, 0x80, 0x82, 0x80, 0x42,   //  じ         83
        0x04, 0x04, 0x14, 0xAC, 0x7E, 0x04, 0x06,   //  ず         84
        0x08, 0x08, 0x7E, 0x88, 0xA8, 0xBE, 0x8A,   //  ぜ         85
        0x00, 0x10, 0x12, 0x7A, 0x96, 0x92, 0x14,   //  ぞ         86
        0x84, 0x74, 0x0E, 0x44, 0xAA, 0x88, 0x8A,   //  だ         87
        0x00, 0x04, 0x24, 0x9C, 0x96, 0x94, 0x66,   //  ぢ         88
        0x08, 0x08, 0x04, 0x44, 0x46, 0x44, 0x3A,   //  づ         89
        0x00, 0x04, 0x04, 0x34, 0x4A, 0x86, 0x8A,   //  で         90
        0x00, 0x40, 0xAE, 0x90, 0x92, 0x88, 0x8A,   //  ど         91
        0xFE, 0x00, 0x48, 0xA8, 0xA8, 0x7E, 0x8A,   //  ば         92
        0x04, 0x74, 0x8E, 0x80, 0x82, 0x7C, 0x0C,   //  び         93
        0x80, 0x60, 0x80, 0x9A, 0x64, 0x22, 0xC2,   //  ぶ         94
        0x10, 0x08, 0x04, 0x08, 0x12, 0x20, 0x22,   //  べ         95
        0xFE, 0x00, 0xD4, 0xD4, 0xFE, 0x54, 0x96,   //  ぼ         96
        0xFE, 0x00, 0x48, 0xA8, 0xAC, 0x7A, 0x8C,   //  ぱ         97
        0x04, 0x74, 0x8E, 0x80, 0x86, 0x7A, 0x0C,   //  ぴ         98
        0x80, 0x60, 0x80, 0x9A, 0x64, 0x2A, 0xC4,   //  ぷ         99
        0x10, 0x08, 0x04, 0x08, 0x14, 0x2A, 0x24,   //  ぺ         100
        0xFE, 0x00, 0xD4, 0xD4, 0xFE, 0x54, 0x96,   //  ぽ         101
        0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,   //  、         102
        0x40, 0xA0, 0x40, 0x00, 0x00, 0x00, 0x00,   //  。         103
        0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x02,   //  「         104
        0x80, 0x80, 0x80, 0xFC, 0x00, 0x00, 0x00,   //  」         105
        0x00, 0x04, 0x02, 0xA2, 0x12, 0x12, 0x0C,   //  ?        106
        0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00,   //  !        107
        0x48, 0x76, 0x54, 0xFC, 0x54, 0x54, 0x44,   //  年        108
        0x80, 0x40, 0x3E, 0x2A, 0x2A, 0xAA, 0xFE,   //  月        109
        0x00, 0xFE, 0x92, 0x92, 0x92, 0x92, 0xFE,   //  日        110
        0x7C, 0x54, 0x7C, 0xC4, 0x5E, 0xF4, 0x50,   //  時        111
        0x90, 0x88, 0x56, 0x30, 0x96, 0xF8, 0x10,   //  分        112
        0x6A, 0xFE, 0x10, 0x8C, 0xBE, 0x44, 0x28,   //  秒        113
        0x00, 0xFE, 0x20, 0x10, 0x28, 0x44, 0x82,   //  K         114
        0xFE, 0x04, 0x18, 0x60, 0x18, 0x04, 0xFE,   //  M         115
        0x00, 0xFE, 0x04, 0x08, 0x10, 0x20, 0xFE,   //  N         116
        0x00, 0xFE, 0x12, 0x12, 0x12, 0x12, 0x06,   //  P         117
        0x08, 0xFC, 0x4A, 0x2C, 0xFE, 0x04, 0x6C,   //  ニィ(ハオ)   118
        0x88, 0xB8, 0x6E, 0x58, 0x92, 0xFA, 0x16,   //  好        119
        0x00, 0x38, 0x44, 0x82, 0xA2, 0x44, 0xB8,   //  Q         120
        0x00, 0x4C, 0x92, 0x92, 0x92, 0x92, 0x64,   //  S         121
        0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02,   //  T         122
        0x00, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x7E,   //  U         123
        0x06, 0x18, 0x60, 0x80, 0x60, 0x18, 0x06,   //  V         124
        0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82,   //  X         125
        0x02, 0x04, 0x08, 0xF0, 0x08, 0x04, 0x02,   //  Y         126
        0x00, 0x82, 0xC2, 0xA2, 0x92, 0x8A, 0x86,   //  Z         127
        0x00, 0xFE, 0x12, 0x12, 0x32, 0x52, 0x8C,   //  R         128
        0x30, 0x2A, 0x92, 0x92, 0x94, 0x50, 0x20,   //  ら         129
        0x00, 0x1E, 0x84, 0x82, 0x42, 0x3C, 0x00,   //  り         130
        0x20, 0x52, 0xAA, 0xAE, 0xCA, 0x8A, 0x70,   //  る         131
        0x44, 0x34, 0xFE, 0x08, 0x04, 0xFC, 0x80,   //  れ         132
        0x20, 0x12, 0x9A, 0x96, 0x96, 0x92, 0x60,   //  ろ         133
        0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0xFE,   //  П РИВЕТ МИР   134
        0x00, 0xFE, 0x40, 0x20, 0x20, 0x08, 0xFE,   //  И             135
        0xF0, 0x0E, 0x30, 0xC0, 0x30, 0x0E, 0xF0,   //  М             136


    };

    int main(void)
    {

        RCC   ->AHBENR |= (1<<17);  // GPIO-Aの初期化(最初は0クロックで無可動状態)

        GPIOA -> MODER |= (1<<4);   // ピン A - 2 を出力モードに
        GPIOA -> PUPDR |= (1<<4);   // ピン A - 2 を プルアップ指定
        GPIOA -> MODER |= (1<<6);   // ピン A - 3 を出力モードに
        GPIOA -> PUPDR |= (1<<6);   // ピン A - 3 を プルアップ指定
        GPIOA -> MODER |= (1<<8);   // ピン A - 4 を出力モードに
        GPIOA -> PUPDR |= (1<<8);   // ピン A - 4 を プルアップ指定
        GPIOA -> MODER |= (1<<10);  // ピン A - 5 を出力モードに
        GPIOA -> PUPDR |= (1<<10);  // ピン A - 5 を プルアップ指定
        GPIOA -> MODER |= (1<<12);  // ピン A - 6 を出力モードに
        GPIOA -> PUPDR |= (1<<12);  // ピン A - 6 を プルアップ指定
        GPIOA -> MODER |= (1<<14);  // ピン A - 7 を出力モードに
        GPIOA -> PUPDR |= (1<<14);  // ピン A - 7 を プルアップ指定

        GPIOA ->ODR &= ~(1<<2);     //GPIOA-Pin2をOffにする
    //    GPIOA ->ODR &= ~(1<<3);     //GPIOA-Pin3をOffにする バックライト無し
        GPIOA ->ODR |= (1<<3);      //GPIOA-Pin3をOnにする バックライト有り
        GPIOA ->ODR &= ~(1<<4);     //GPIOA-Pin4をOffにする
        GPIOA ->ODR &= ~(1<<5);     //GPIOA-Pin5をOffにする
        GPIOA ->ODR &= ~(1<<6);     //GPIOA-Pin6をOffにする
        GPIOA ->ODR &= ~(1<<7);     //GPIOA-Pin7をOffにする

        delay_ms(100);
      lcd_init();

    while(1){
        lcd_position(110,118,119,127);

        delay_ms(1500);

        lcd_clear_2();
        lcd_clear_0();
        lcd_clear_2();
        lcd_clear_1();
        lcd_clear_0();

        lcd_put_w2(w_00[6],4);
        lcd_put_w2(w_00[7],5);
        lcd_put_w2(w_00[5],6);
        lcd_put_w2(w_00[4],7);
        lcd_put_w2(w_00[3],8);
        lcd_put_w2(w_00[2],9);
        lcd_put_w2(w_00[1],11);
        lcd_put_w2(w_00[0],12);
        lcd_put_w2(w_00[8],13);

        delay_ms(5000);
        lcd_position(100,108,119,127);

        }
    }

    //---------- 文字出力2 ----------
    //      *sc:文字列の先頭ポインタ
    void lcd_put_w2(char w[],int y) {

        int j=0;
        char *sc;
        while(w[j]<254){
        sc=font+(w[j])*7;

        lcd_position(128-(y*8),128-(y*8-7),(10+j*8),(3+j*8));// Nokia5110のデータを流用するため、こんな奇っ怪な式になった
        lcd_put_cmd(0x36);     //   メモリ制御方法指定(描写方法)    Nokia5110との互換性をある程度維持するため、このような命令が必要になった
            lcd_put_ch(0x70);  //                               Nokia5110との互換性をある程度維持するため、このような命令が必要になった

        lcd_put_cmd(0x2C);

        int i=7;       //データー読み出し量
        while(i>0){
            lcd_ch(*(sc++));

        i--;
        }
        j++;
        }
        lcd_put_cmd(0x36);     //   メモリ制御方法指定(描写方法)
            lcd_put_ch(0xC8);  //

    }

    //---------- データ出力 ----------
    //      ch:出力するデータ
    void lcd_ch(char ch)
    {

        lcd_4bit(ch);       //上位4bit出力
        lcd_4bit(ch<<4);    //下位4bit出力

    }

    //---------- データ4bit処理 ----------
    void lcd_4bit(char code)
    {

        if(code & 0x80){
            lcd_put_ch(0xFF);  //
            lcd_put_ch(0xFF);  //
            }else{
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x00);  //
    }
        if(code & 0x40){
            lcd_put_ch(0xFF);  //
            lcd_put_ch(0xFF);  //
            }else{
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x00);  //
    }
        if(code & 0x20){
            lcd_put_ch(0xFF);  //
            lcd_put_ch(0xFF);  //
            }else{
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x00);  //
    }
        if(code & 0x10){
            lcd_put_ch(0xFF);  //
            lcd_put_ch(0xFF);  //
            }else{
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x00);  //
    }
    }


    //---------- 表示位置設定 ----------
    //      xx:x座標  yy:y座標
    void lcd_position(short x1,short x2,short y1,short y2)
    {
        lcd_put_cmd(0x2A);
            lcd_put_ch(x1 >>8);  //
            lcd_put_ch(x1);      //
            lcd_put_ch(x2 >>8);  //
            lcd_put_ch(x2);      //

        lcd_put_cmd(0x2B);
            lcd_put_ch(y1 >>8);  //
            lcd_put_ch(y1);      //
            lcd_put_ch(y2 >>8);  //
            lcd_put_ch(y2);      //

    }

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

        GPIOA ->ODR &= ~(1<<4);     //GPIOA-Pin4をOffにする
        if(code & 0x80)
            GPIOA ->ODR |= (1<<7);  //GPIOA-Pin7をOnにする
            else
            GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7をOffにする

        GPIOA ->ODR |= (1<<4);      //GPIOA-Pin4をOnにする
        GPIOA ->ODR &= ~(1<<4);     //GPIOA-Pin4をOffにする
        if(code & 0x40)
            GPIOA ->ODR |= (1<<7);  //GPIOA-Pin7をOnにする
            else
            GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7をOffにする

        GPIOA ->ODR |= (1<<4);      //GPIOA-Pin4をOnにする
        GPIOA ->ODR &= ~(1<<4);     //GPIOA-Pin4をOffにする
        if(code & 0x20)
            GPIOA ->ODR |= (1<<7);  //GPIOA-Pin7をOnにする
            else
            GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7をOffにする

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

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

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

    }

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

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

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

    }

    //---------- 塗りつぶし(消去) ----------
    void lcd_clear_0()
    {
        lcd_position(0x02,0x81,0x03,0x82);
        lcd_put_cmd(0x2C);

        int i=128*128*2;
        while(i>0){
            lcd_put_ch(0x00);
        i--;
    }    }

    void lcd_clear_1()
    {
        lcd_position(0x02,0x81,0x03,0x82);
        lcd_put_cmd(0x2C);

        int i=128*128*2;
        while(i>0){
            lcd_put_ch(i*2);
        i--;
    }    }

    void lcd_clear_2()
    {
        lcd_put_cmd(0x2C);

        int i=32*128;
        while(i>0){
            lcd_put_ch(0x88);
            lcd_put_ch(0xE2);
            lcd_put_ch(0x2F);
            lcd_put_ch(0xCC);
            lcd_put_ch(0x70);
            lcd_put_ch(0x15);
            lcd_put_ch(0x55);
            lcd_put_ch(0x55);
        i--;
    }    }

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

        lcd_put_cmd(0x11);     //   スリープ解除
        delay_ms(30);

        lcd_put_cmd(0xB2);     //   パワーセット
            lcd_put_ch(0x01);  //
            lcd_put_ch(0x2C);  //
            lcd_put_ch(0x2D);  //

        lcd_put_cmd(0xB4);      //液晶反転設定
            lcd_put_ch(0x07);  //

        lcd_put_cmd(0xC3);      //電源設定-(8色)
            lcd_put_ch(0x8A);  //
            lcd_put_ch(0x2A);  //

        lcd_put_cmd(0xC5);      //VMCTR1 VCOM control 1
            lcd_put_ch(0x0E);  //

        lcd_put_cmd(0x36);     //   メモリ制御方法指定(描写方法)
            lcd_put_ch(0xC8);  //

        lcd_put_cmd(0xE0);     //   ガンマシーケンス
            lcd_put_ch(0x02);  //
            lcd_put_ch(0x1C);  //
            lcd_put_ch(0x07);  //
            lcd_put_ch(0x12);  //
            lcd_put_ch(0x37);  //
            lcd_put_ch(0x32);  //
            lcd_put_ch(0x29);  //
            lcd_put_ch(0x2D);  //
            lcd_put_ch(0x29);  //
            lcd_put_ch(0x25);  //
            lcd_put_ch(0x2B);  //
            lcd_put_ch(0x39);  //
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x01);  //
            lcd_put_ch(0x03);  //
            lcd_put_ch(0x10);  //
        lcd_put_cmd(0xE1);
            lcd_put_ch(0x03);  //
            lcd_put_ch(0x1D);  //
            lcd_put_ch(0x07);  //
            lcd_put_ch(0x06);  //
            lcd_put_ch(0x2E);  //
            lcd_put_ch(0x2C);  //
            lcd_put_ch(0x29);  //
            lcd_put_ch(0x2D);  //
            lcd_put_ch(0x2E);  //
            lcd_put_ch(0x2E);  //
            lcd_put_ch(0x37);  //
            lcd_put_ch(0x3F);  //
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x00);  //
            lcd_put_ch(0x02);  //
            lcd_put_ch(0x10);  //

        lcd_put_cmd(0x2A);      //列アドレス設定
            lcd_put_ch(0x00);  //上
            lcd_put_ch(0x02);  //下  開始アドレス0002h
            lcd_put_ch(0x00);  //上
            lcd_put_ch(0x81);  //下  開始アドレス0081h=129

        lcd_put_cmd(0x2B);      // リセット行アドレスセット
            lcd_put_ch(0x00);  //上
            lcd_put_ch(0x01);  //下  開始アドレス0003h
            lcd_put_ch(0x00);  //上
            lcd_put_ch(0x82);  //下  開始アドレス0082h=130

        lcd_put_cmd(0x3A);      // RGB転送タイプ/0x05=16ビットモード
            lcd_put_ch(0x05);  //

        lcd_put_cmd(0x29);      // ディスプレイ・表示開始
    }

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

     

    拍手[0回]

  • 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回]

  • STM32F030F4P6で1602LCD表示(その2)
    先日のLCD1602の件なのですが、コードが大量に張り巡らされていて、ちょっとした衝撃で直ぐに動作不良を起こすという大問題がありました。
    そこで、「基板化」を試みました。


    (配線効率を考慮した結果、ピンに割り振っていた役割が変更された箇所が幾つかあります)


    どちらが上でどちらが下かはともかく、一方はこんな感じ。電源はマイクロUSB端子からもらうことにしました。

    もう一方の側から見ると、こう。
    一応、文字表示は行われているので、最低限の目標は達成したという事にしておきましょう。

    左側の抵抗が幾つもくっついているのは、「良い子は絶対に真似をしてはいけません」的な処理です。可変抵抗を組み込んでおいたのですが、それだと正常に作動しなかったので、こういう風に対処したのですが、ショートしてここに5V電流が流れこむと、加熱して最悪出火します。
    うっかりやらかしてしまった私は、触って指の先に水ぶくれが出来ました。

    まぁ、「プロトタイプ以前」のテストタイプという事で、ご了承ください。

    (とはいえ、実際に稼働することも事実なので、こんなものでも、実験機材としては十分に活躍の場面があるような気がします)

    ちなみに、USB端子に差し込んで計測する簡易電流計で測定た所、これ一式の消費電流は10ミリアンペア程度のようです。
    (以前、DigiSparkでこれと同じようなシステムを構築した時は2〜30mAだった気がする。あぁ、でも、あっちは、I2C変換するアダプタを噛ましていたので、消費電力が多くて当然なのか……。ダイソーの500円のモバイルバッテリーが900mAなので、それを使ったら90時間ぐらい動き続ける計算。ただ、消費電力が少ないので、ひと工夫しないと、自動的にOffになる)


    それにしても、STM32F030、解ってくるとかなり楽しいです。
    なにせ、ものすごく安価だし。
    初心者が初心者っぽいことを楽しでいる分には、もてあますぐらい高性能だし。

    拍手[0回]

  • 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回]