Featured image of post stm32とI2C接続の有機ELディスプレイSO2002AでHello worldした。

stm32とI2C接続の有機ELディスプレイSO2002AでHello worldした。

stm32 nucleo board(NUCLEO-F302R8)で「有機ELキャラクタディスプレイモジュール 20×2行 黄色」にHello Worldを表示してみました。

最終更新 2020/10/15 00:00 JST

stm32 nucleo board(NUCLEO-F302R8)で「有機ELキャラクタディスプレイモジュール 20×2行 黄色」にHello Worldを表示してみました。

今回は20文字2行のディスプレイSO2002Aを使うが, 同じシリーズに16文字2行のディスプレイSO1602Aがある。

確認していないがSO1602Aでもピンの差し替えで同じように使えると思う。

用意する物

  • STM32 Nucleo-64 development board with STM32F302R8 MCU
    NUCLEO-F302R8 - STMicroelectronics
  • 有機ELキャラクタディスプレイモジュール 20×2行 黄色 SO2002AWYB-UC-WB-U
    akizukidenshi.com/catalog/g/gP-08279/
    P-08279 秋月電子通商
  • ブレッドボードとワイヤ

接続

stm32と有機ELキャラクタディスプレイモジュールのインターフェースはI2Cで接続するので、 NUCLEO-F302R8のarduinoコネクタにあるハードウェアI2Cピン1と有機ELキャラクタディスプレイモジュールのピンをこのように接続する。

I2Cバス SCLとSDA には 適当な値の抵抗でプルアップしておく事。ここでは手元にあった抵抗器 2.7kでプルアップした。

NUCLEO-F302R8機能SO2002A
GND (CN6)-1 VSS
3V3 (CN6)-2 VDD
GND (CN6)-3 /CS
3V3 (CN6)-4 SA0
--5 NC
--6 NC
D15 (CN5)I2C1_SCL7 SCL
D14 (CN5)I2C1_SDA8 SDA_in
D14 (CN5)I2C1_SDA9 SDA_out
--10-14 NC

接続

src/main.rs

今回はI2Cを400kHzで動かしてみた。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#![no_main]
#![no_std]

#[allow(unused_extern_crates)]
extern crate panic_halt;

extern crate cortex_m;
extern crate cortex_m_rt;
extern crate cortex_m_semihosting;

extern crate embedded_hal;
extern crate stm32f30x_hal as hal;

use hal::delay::Delay;
use hal::i2c::I2c;
use hal::prelude::*;
use hal::stm32f30x;

use cortex_m_rt::entry;

// 0 1 1 1 1 0 SA0 (SA0 pin is default Hi)
// 0 1 1 1 1 0 1
// 011 1101 = (2+1)*16 + (8+4+1)*1 = 0x3d
const OLED_ADDR: u8 = 0x3d;

const USER_CHARACTERS: [[u8; 8]; 7] = [
    // character code 0x00
    [
        0b00000000, // line 1
        0b00000000, // line 2
        0b00000000, // line 3
        0b00000000, // line 4
        0b00000000, // line 5
        0b00000000, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x01
    [
        0b00000000, // line 1
        0b00000000, // line 2
        0b00000000, // line 3
        0b00000000, // line 4
        0b00000000, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x02
    [
        0b00000000, // line 1
        0b00000000, // line 2
        0b00000000, // line 3
        0b00000000, // line 4
        0b00011111, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x03
    [
        0b00000000, // line 1
        0b00000000, // line 2
        0b00000000, // line 3
        0b00011111, // line 4
        0b00011111, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x04
    [
        0b00000000, // line 1
        0b00000000, // line 2
        0b00011111, // line 3
        0b00011111, // line 4
        0b00011111, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x05
    [
        0b00000000, // line 1
        0b00011111, // line 2
        0b00011111, // line 3
        0b00011111, // line 4
        0b00011111, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
    // character code 0x06
    [
        0b00011111, // line 1
        0b00011111, // line 2
        0b00011111, // line 3
        0b00011111, // line 4
        0b00011111, // line 5
        0b00011111, // line 6
        0b00011111, // line 7
        0b00000000, // line 8
    ],
];

#[entry]
fn main() -> ! {
    let cp = cortex_m::Peripherals::take().unwrap();
    let p = stm32f30x::Peripherals::take().unwrap();

    let mut flash = p.FLASH.constrain();
    let mut rcc = p.RCC.constrain();

    let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(&mut flash.acr);

    let mut delay = Delay::new(cp.SYST, clocks);
    let mut gpiob = p.GPIOB.split(&mut rcc.ahb);

    // OLED display I2C interface
    let scl = gpiob.pb8.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb9.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let mut display = I2c::i2c1(p.I2C1, (scl, sda), 400.khz(), clocks, &mut rcc.apb1);

    // Wait 100ms until module control, recommended
    delay.delay_ms(100u8);

    // Set CGRAM
    for (i, ch) in USER_CHARACTERS.iter().enumerate() {
        let code = i as u8;
        display
            .write(OLED_ADDR, &[0x00u8, 0x40u8 | (code << 3) | 0])
            .unwrap();
        delay.delay_ms(1u8);
        for v in ch {
            display.write(OLED_ADDR, &[0x40u8, *v]).unwrap();
            delay.delay_ms(1u8);
        }
    }

    // Clear Display
    display.write(OLED_ADDR, &[0x00u8, 0x01u8]).unwrap();
    delay.delay_ms(20u8);
    // Return Home
    display.write(OLED_ADDR, &[0x00u8, 0x02u8]).unwrap();
    delay.delay_ms(2u8);
    // Display ON, Cursor OFF, Blink OFF
    display.write(OLED_ADDR, &[0x00u8, 0x0Cu8]).unwrap();
    delay.delay_ms(2u8);
    // Clear Display
    display.write(OLED_ADDR, &[0x00u8, 0x01u8]).unwrap();
    delay.delay_ms(20u8);
    // Function Set (N = 2, DH = 0, RE = 1, IS = 0)
    display.write(OLED_ADDR, &[0x00u8, 0x2Au8]).unwrap();
    delay.delay_ms(1u8);
    // OLED Characterization (SD = 1)
    display.write(OLED_ADDR, &[0x00u8, 0x79u8]).unwrap();
    delay.delay_ms(1u8);
    // contrast set
    display.write(OLED_ADDR, &[0x00u8, 0x81u8]).unwrap();
    delay.delay_ms(1u8);
    // Set Contrast Control
    display.write(OLED_ADDR, &[0x00u8, 0xFFu8]).unwrap();
    delay.delay_ms(1u8);
    // OLED Characterization (SD = 0)
    display.write(OLED_ADDR, &[0x00u8, 0x78u8]).unwrap();
    delay.delay_ms(2u8);
    // Function Set (N = 2, DH = 0, RE = 0, IS = 0)
    display.write(OLED_ADDR, &[0x00u8, 0x28u8]).unwrap();
    delay.delay_ms(1u8);
 
    //
    // Print to display.
    //
    let message = b"I2C OLED Yellow 20x2Hello World";

    const BUF_SIZE: usize = 1 + 20 * 02; // 1 byte and 20 chars * 02 lines
    let mut write_buf: [u8; BUF_SIZE] = [b' '; BUF_SIZE]; // clear to whitespace

    // first byte is set to D/C bit Hi
    write_buf[0] = 0x40u8;

    // after first bytes
    write_buf[1..=message.len()].copy_from_slice(message);

    // send to display.
    display.write(OLED_ADDR, &write_buf).unwrap();

    // display progress bar
    let progress_bar: [u8; 8] = [b' ', 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
    write_buf[32..32 + progress_bar.len()].copy_from_slice(&progress_bar);

    // Idle loop
    let mut i = 0;
    loop {
        write_buf[40] = progress_bar[i];
        i = i + 1 & 7;
        // send to display.
        display.write(OLED_ADDR, &write_buf).unwrap();
        delay.delay_ms(100_u16);
    }
}

GitHubリポジトリ

https://github.com/ak1211/hello-nucleo-so2002

ビルドと実行

WSL上のUbuntu CLI上で

1
2
$ cargo build --release  
$ cargo objcopy --release -- -O binary firmware.bin  

を実行してでできた firmware.bin を STM32CubeProgrammer で書き込む。


  1. User manual STM32 Nucleo-64 boards (MB1136) - UM1724 ↩︎

comments powered by Disqus

This website uses cookies to improve your experience.
このサイトは「Googleアナリティクス」を使用しています。
Googleアナリティクスはデータの収集のためにCookieを使用しています。


Built with Hugo
テーマ StackJimmy によって設計されています。