Портуємо U8x8 на STM32 CMSIS

Для Arduino є доволі популярна бібліотека для монохромних екранів - U8g2. Ця бібліотека має дві незалежні підсистеми: U8g2 — для малювання різних графічних елементів та u8x8 — суто для тексту.

І сьогодні мені потрібно запустити u8x8 на STM32 без Arduino, у чистому CMSIS-проєкті.

У мене є PlatformIO-проєкт, тому першим кроком я додаю в нього залежність від U8g2:

[env:genericSTM32F103C8]
platform = ststm32
board = genericSTM32F103C8
framework = cmsis
upload_protocol = cmsis-dap
debug_tool = cmsis-dap

lib_deps = 
    olikraus/U8g2
lib_compat_mode = off

Параметр lib_compat_mode = off вимикає перевірку сумісності, інакше PlatformIO не додасть бібліотеку до збірки, оскільки вона призначена для фреймворку Arduino.

Наш початковий код — поки що майже порожній, ініціалізуємо лише таймер. Будемо працювати від внутрішнього RC-генератора на частоті 8 МГц.

#include "stm32f1xx.h"

volatile uint32_t ms_ticks = 0;

extern "C" void SysTick_Handler(void) {
    ms_ticks++;
}

void Delay_Ms(uint32_t ms) {
    uint32_t start = ms_ticks;
    while ((ms_ticks - start) < ms);
}

int main() {
    SystemCoreClockUpdate(); 
    SysTick_Config(SystemCoreClock / 1000);
    __enable_irq();
    while(1) {
    }
}

Цей порожній проєкт у мене займає 424 байти, далі подивимося, скільки займе бібліотека:

RAM:   [          ]   0.2% (used 36 bytes from 20480 bytes)
Flash: [          ]   0.6% (used 424 bytes from 65536 bytes)

Пояснення, як використати U8g2 на інших фреймворках та архітектурах, є на цій сторінці: https://github.com/olikraus/u8g2/wiki/Porting-to-new-MCU-platform/. Найпростіший варіант адаптації — це використати «ногодриг» (bit-banging), тобто програмну реалізацію інтерфейсу.

Спробуймо! Потрібно лише перевизначити функцію:

uint8_t u8x8_gpio_and_delay_template(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)

та додати код ініціалізації:

#include "stm32f1xx.h"
#include "clib/u8x8.h"

volatile uint32_t ms_ticks = 0;

extern "C" void SysTick_Handler(void) {
    ms_ticks++;
}

void Delay_Ms(uint32_t ms) {
    uint32_t start = ms_ticks;
    while ((ms_ticks - start) < ms);
}

uint8_t u8x8_gpio_and_delay_stm32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
    switch(msg) {
        case U8X8_MSG_GPIO_AND_DELAY_INIT:
            // використаємо піни PB6, PB7 в open drain режимі
            RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
            GPIOB->CRL &= ~((0xF << 24) | (0xF << 28));
            GPIOB->CRL |= (0x7 << 24) | (0x7 << 28);
            GPIOB->BSRR = (1 << 6) | (1 << 7);
            break;
        case U8X8_MSG_DELAY_MILLI:
            Delay_Ms(arg_int);
            break;
        case U8X8_MSG_DELAY_10MICRO:
            for (volatile uint32_t i = 0; i < (arg_int * 8); i++) { __NOP(); }
            break;
        case U8X8_MSG_DELAY_100NANO:
            __NOP();
            break;

        case U8X8_MSG_GPIO_I2C_CLOCK:
            if (arg_int) {
                GPIOB->BSRR = (1 << 6);
            } else {
                GPIOB->BSRR = (1 << (6 + 16));
            }
            break;

        case U8X8_MSG_GPIO_I2C_DATA:
            if (arg_int) {
                GPIOB->BSRR = (1 << 7);
            } else {
                GPIOB->BSRR = (1 << (7 + 16));
            }
            break;
    }
    return 1;
}

int main() {
    SystemCoreClockUpdate(); 
    SysTick_Config(SystemCoreClock / 1000);
    __enable_irq();
    // ініціалізація u8x8
    u8x8_t u8x8;
    u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32);
    u8x8_InitDisplay(&u8x8);
    u8x8_SetPowerSave(&u8x8, 0);
    u8x8_ClearDisplay(&u8x8);
    u8x8_SetFont(&u8x8, u8x8_font_chroma48medium8_r);
    u8x8_DrawString(&u8x8, 0, 0, "Hello from CMSIS");
    while(1) {
    }
    return 0;
}

Далі підключаємо дисплей до виводів:

  • GND, VCC - живлення

  • SCL - до PB6

  • SDL - до PB7

Компілюємо й зараз побачимо, скільки місця займе бібліотека:

RAM:   [          ]   0.2% (used 36 bytes from 20480 bytes)
Flash: [=         ]   5.1% (used 3324 bytes from 65536 bytes)

Затягнуло 2900 байтів. Тепер можемо запускати та перевіряти що все працює.



Коментарі

Популярні дописи з цього блогу

Огляд DC-DC Step-down Buck перетворювачів

Як додати підтримку CH32V до Platform.IO

ESP8266 модуль з OLED екраном (HW-364A)