参考
「Elastic Notes」さんの「u8g2 library usage with STM32 MCU」
「olikraus」さんの「Use U8g2 with STM32 #356」
「olikraus」さんの「Template for the GPIO and Delay callback」
「Elastic Notes」さんの記事がよくできているので、ほとんどそのまま試しました。
プロジェクト
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_u8g2_Test1
実行環境
- Nucleo-F446RE
- STM32CubeMX Version 5.1.0
- System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911
配線図
SSD1306 | Arduino Header | Pin Name | Function | Lavel |
---|---|---|---|---|
D0 | D13 | PA5 | SPI1 | SPI1_SCK |
D1 | D11 | PA7 | SPI1 | SPI1_MOSI |
CS | D10 | PB6 | GPIO | SPI1_CS |
DC | D9 | PC7 | GPIO | OLED_DC |
RES | D8 | PA9 | GPIO | OLED_RES |
一応100uFのOSコンで電源をデカップリングしています。
STM32CubeMXの設定
Clock Configuration
PLL Source Mux: HSE
HCLK (MHz): 180
GPIO-GPIO
GPIO-SPI1
SPI1
SW4STM32でコードを追加
GPIOと遅延と、SPI通信の2つのCallback関数を追加
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr) { switch (msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: HAL_Delay(1); break; case U8X8_MSG_DELAY_MILLI: HAL_Delay(arg_int); break; case U8X8_MSG_DELAY_10MICRO: for (uint16_t n = 0; n < 320; n++) { __NOP(); } break; case U8X8_MSG_DELAY_100NANO: __NOP(); break; case U8X8_MSG_GPIO_CS: HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, arg_int); break; case U8X8_MSG_GPIO_DC: HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int); break; case U8X8_MSG_GPIO_RESET: HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, arg_int); break; } return 1; } uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_BYTE_SEND: HAL_SPI_Transmit(&hspi1, (uint8_t *) arg_ptr, arg_int, 10000); break; case U8X8_MSG_BYTE_INIT: break; case U8X8_MSG_BYTE_SET_DC: HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int); break; case U8X8_MSG_BYTE_START_TRANSFER: HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET); __NOP(); break; case U8X8_MSG_BYTE_END_TRANSFER: __NOP(); HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); break; default: return 0; } return 1; } /* USER CODE END 0 */
「Elastic Notes」さんは、CSピンがないタイプのSSD1306 OLEDを使われていますが、私の手持ちのものはCSピンがあるタイプなので、Callback関数にCSの処理を追加しています。
u8g2ライブラリの準備
u8g2/csrcをプロジェクトのDriverディレクトリに配置、名前をu8g2に変更。
このパスをインクルードに追加。[Project]->[Properties]->[C/C++ Build]->[Setting]->[Includes]で
../Drivers/u8g2を追加。
main.cファイルの先頭にu8g2.hを追加。
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "u8g2.h" /* USER CODE END Includes */
グローバル変数u8g2を配置。
/* USER CODE BEGIN PV */ static u8g2_t u8g2; /* USER CODE END PV */
u8g2をセットアップ。
/* USER CODE BEGIN 2 */ u8g2_Setup_ssd1306_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); /* USER CODE END 2 */
メインループで描画処理
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ u8g2_FirstPage(&u8g2); do { u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr); u8g2_DrawStr(&u8g2, 0, 15, "Hello World!"); u8g2_DrawCircle(&u8g2, 64, 40, 10, U8G2_DRAW_ALL); } while (u8g2_NextPage(&u8g2)); } /* USER CODE END 3 */
Buildすると実行可能ファイルが大きすぎてエラーになるので、未使用のコードとデータを除去するオプションを設定。
実行結果
以上で冒頭の画像の通りOLEDに描画されるのですが、なぜだかSCKにオシロのプローブを当てていないと描画されません。SCKにプローブを当てていれば必ずOKというわけでもなく、たまに描画に失敗します。オシロのプローブもx1モードではだめで、x10モードのときにだけ描画されます。どういうこと?
オシロのプローブの仕様から、入力インピーダンス10MΩ・20pFぐらいでGNDにプルダウンすれば動作するんでしょうか?とりあえず1MΩ以上の抵抗は持ち合わせていないので検証できません。
それにしても、あまりにも厳しい条件です。
Arduinoでは似たような条件で特別なことをしなくても問題なく動作します。
参考「温度・湿度・気圧センサーのBME280をArduino Pro Miniで使う。」
問題はおそらく違うところにあると思うので、しばらく放置して、気が向いたらまたテストしたいと思います。
メモ:
SPI1のSCKに割り当てているPA5(D13)はNucleo Board上でLEDに接続されている。ただし、Arduinoも同様で、Elastic Notesさんの検証でもSCKはPA5。
SPI通信波形
MOSI
ch1:MOSI(D1) ch2:SCK(D0)
RES
ch1:RES ch2:SCK(D0)
RESはReset時にLow。通常はHigh
DC
ch1:DC ch2:SCK(D0)
DCはWrite Command時にLow。Write Data時にHigh。
CS
ch1:CS ch2:SCK(D0)
CSはSlave選択時にLow。
0 件のコメント:
コメントを投稿