понеділок, 25 березня 2019 р.

STM32: Бібліотека для роботи з LCD дисплеєм з контролером ST7735

update 10.03.2021: Замінив в файлі бібліотеки st7735.c дефайни з маніпулюванням регістрами GPIO на HAL функції. Для сумісності з будь яким чипом. Додав відео-підтримку до статті.

Передмова

Бібліотека призначена для роботи з LCD дисплеєм з контролером ST7735(S) по SPI шині. Для розмірів 128X160, 128X128 та 160X80. Дисплей можна придбати деінде, наприклад: ebay, aliexpress, тощо.

Я в проекті використовую:

Схема з'єднання

Схема з'єднання
Клацайте по зображенню, щоб збільшити. На деяких дисплеях, як на моєму, шпильки MOSI та SCK позначені як SDA та SCL. Та помилково на платі надруковано роздільна здатність як 128Х120, насправді роздільна здатність дисплею 128X160 точок.
Приклад дисплею ST7735S

Створюємо проект в CubeMX

Запускаємо CubeMX, обираємо свій мікроконтролер, або дошку. Та налаштовуємо проект:
Налаштування периферії
  1. Тиснемо RCC -> High Speed Clock (HSE) -> Crystal/Ceramic Resonator, та SYS -> Debug -> Serial Wire.
  2. Тиснемо SPI1.
  3. Обираємо Mode -> Transmit Only Master, та Hardware NSS Signal -> Disable, все інше без змін.
  4. Обираємо шпильки для сигналів BL (підсвітка), CS (вибір чипу), DC (дані/команда), RES (скидання). Шпильки називаємо так як на малюнку: ST7735_BL, ST7735_CS, ST7735_DC, ST7735_RES.
  5. Генеруємо проект: вказуємо шлях, даємо назву проекту "STM32F103C8T6_ST7735_SPI", обираємо свій засіб розробки. В мене це "Atolic Truestudio". Тиснемо "OK".

Демонстраційний код

Відкриваємо свій засіб розробки та експортуємо згенерований, CubeMX, проект. Файли st7735.h, st7735_cfg.h, fonts.h, testimg.h копіюємо до теки "inc" проекту, а файли st7735.c та fonts.c до теки "src" проекту.
Відкриваємо файл st7735_cfg.h та налаштовуємо бібліотеку.
Вказуємо до якого саме SPI під'єднано дисплей. В прикладі до SPI1, та якщо використовуєте DMA для передачі даних по SPI, то розкоментуйте рядок з "USE_SPI_DMA". Але хочу зауважити, що в режимі SPI з DMA екран дисплею промальовується повільніше ніж без DMA.
#define ST7735_SPI_PORT hspi1 //hspi1, hspi2, hspi3...
//#define USE_SPI_DMA   //if used DMA for SPI bus
Вказуємо тип дисплею. В прикладі це ST7735S.
//#define ST7735_1_8_DEFAULT_ORIENTATION // AliExpress/eBay 1.8" display, default orientation
#define ST7735S_1_8_DEFAULT_ORIENTATION  // WaveShare ST7735S-based 1.8" display, default orientation
//#define ST7735_1_44_DEFAULT_ORIENTATION  // 1.44" display, default orientation
//#define ST7735_MINI_DEFAULT_ORIENTATION  // mini 160x80 display (it's unlikely you want the default orientation)
Та якщо ви не дали назви шпилькам в CubeMX, то потрібно самому назначити порт і шпильку до відповідних назв:
//Port and pin connected signal 'RES' (reset) ST7735 display
#ifndef ST7735_RES_Pin
#define ST7735_RES_Pin   GPIO_PIN_12
#endif
#ifndef ST7735_RES_GPIO_Port
#define ST7735_RES_GPIO_Port  GPIOB
#endif
//Port and pin connected signal 'DC' (data or command) ST7735 display
#ifndef ST7735_DC_Pin
#define ST7735_DC_Pin   GPIO_PIN_13
#endif
#ifndef ST7735_DC_GPIO_Port
#define ST7735_DC_GPIO_Port  GPIOB
#endif
//Port and pin connected signal 'CS' (chip select) ST7735 display
#ifndef ST7735_CS_Pin
#define ST7735_CS_Pin   GPIO_PIN_14
#endif
#ifndef ST7735_CS_GPIO_Port
#define ST7735_CS_GPIO_Port  GPIOB
#endif
//Port and pin connected signal 'BL' (back light) ST7735 display
#ifndef ST7735_BL_Pin
#define ST7735_BL_Pin  GPIO_PIN_15
#endif
#ifndef ST7735_BL_GPIO_Port
#define ST7735_BL_GPIO_Port  GPIOB
#endif
Якщо ви вже дали назви шпилькам в програмі CubeMX, то про це вже не потрібно турбуватись. З налаштуванням бібліотеки це все.

Залишилось додати демонстраційний код до файлу main.c. Відкриваємо його і додаємо такі рядки в секцію "USER CODE BEGIN Includes":
/* USER CODE BEGIN Includes */
#include "st7735.h"
#include "fonts.h"
#include "testimg.h"
/* USER CODE END Includes */
В секцію "USER CODE BEGIN PV" оголошуємо глобальну змінну:
/* USER CODE BEGIN PV */
uint8_t r = 0;
/* USER CODE END PV */
В секцію "USER CODE BEGIN 0" додаємо функцію демонстрації можливостей бібліотеки:
/* USER CODE BEGIN 0 */
void demoTFT(void)
{
 ST7735_SetRotation(r);

 ST7735_FillScreen(ST7735_BLACK);

 for(int x = 0; x < ST7735_GetWidth(); x++)
 {
   ST7735_DrawPixel(x, 0, ST7735_WHITE);
   ST7735_DrawPixel(x, ST7735_GetHeight() - 1, ST7735_WHITE);
 }

 for(int y = 0; y < ST7735_GetHeight(); y++)
 {
   ST7735_DrawPixel(0, y, ST7735_WHITE);
   ST7735_DrawPixel(ST7735_GetWidth() - 1, y, ST7735_WHITE);
 }

 ST7735_DrawLine(0, 0, ST7735_GetWidth(), ST7735_GetHeight(), ST7735_WHITE);
 ST7735_DrawLine(ST7735_GetWidth(), 0, 0, ST7735_GetHeight(), ST7735_WHITE);

 HAL_Delay(2000);

 ST7735_FillScreen(ST7735_BLACK);

 for (int i = 0; i < ST7735_GetHeight(); i += 4)
 {
  ST7735_DrawFastHLine(0, i, ST7735_GetWidth() - 1, ST7735_WHITE);
 }

 for (int i = 0; i < ST7735_GetWidth(); i += 4)
 {
  ST7735_DrawFastVLine(i, 0, ST7735_GetHeight() - 1, ST7735_WHITE);
 }

 HAL_Delay(2000);

 // Check fonts
 ST7735_FillScreen(ST7735_BLACK);
 ST7735_DrawString(0, 0, "Font_7x10, red on black, lorem ipsum dolor sit amet", Font_7x10, ST7735_RED, ST7735_BLACK);
 ST7735_DrawString(0, 3*10, "Font_11x18, green, lorem ipsum", Font_11x18, ST7735_GREEN, ST7735_BLACK);
 ST7735_DrawString(0, 3*10+3*18, "Font_16x26", Font_16x26, ST7735_BLUE, ST7735_BLACK);
 HAL_Delay(2000);

 // Check colors
 ST7735_FillScreen(ST7735_BLACK);
 ST7735_DrawString(0, 0, "BLACK", Font_11x18, ST7735_WHITE, ST7735_BLACK);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_BLUE);
 ST7735_DrawString(0, 0, "BLUE", Font_11x18, ST7735_BLACK, ST7735_BLUE);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_RED);
 ST7735_DrawString(0, 0, "RED", Font_11x18, ST7735_BLACK, ST7735_RED);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_GREEN);
 ST7735_DrawString(0, 0, "GREEN", Font_11x18, ST7735_BLACK, ST7735_GREEN);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_CYAN);
 ST7735_DrawString(0, 0, "CYAN", Font_11x18, ST7735_BLACK, ST7735_CYAN);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_MAGENTA);
 ST7735_DrawString(0, 0, "MAGENTA", Font_11x18, ST7735_BLACK, ST7735_MAGENTA);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_YELLOW);
 ST7735_DrawString(0, 0, "YELLOW", Font_11x18, ST7735_BLACK, ST7735_YELLOW);
 HAL_Delay(500);

 ST7735_FillScreen(ST7735_WHITE);
 ST7735_DrawString(0, 0, "WHITE", Font_11x18, ST7735_BLACK, ST7735_WHITE);
 HAL_Delay(500);

 // Draw circles
 ST7735_FillScreen(ST7735_BLACK);
 for (int i = 0; i < ST7735_GetHeight() / 2; i += 2)
 {
  ST7735_DrawCircle(ST7735_GetWidth() / 2, ST7735_GetHeight() / 2, i, ST7735_YELLOW);
 }
 HAL_Delay(1000);

 ST7735_FillScreen(ST7735_BLACK);
 ST7735_FillTriangle(0, 0, ST7735_GetWidth() / 2, ST7735_GetHeight(), ST7735_GetWidth(), 0, ST7735_RED);
 HAL_Delay(1000);

 ST7735_FillScreen(ST7735_BLACK);
 ST7735_DrawImage(0, 0, 128, 128, (uint16_t*) test_img_128x128);
 HAL_Delay(3000);

 r++;
}
/* USER CODE END 0 */
Та додаємо код що ініціалізує дисплей, вмикає підсвітку, та по колу запускає демонстрацію:
/* USER CODE BEGIN 2 */
  ST7735_Init();
  ST7735_Backlight_On();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
   demoTFT();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Файли для завантаження

Відео інструкція


Відео-демонстрація


пʼятницю, 15 березня 2019 р.

Mbed: Знайомство з Mbed Studio та створення тестової програми blinky

Передмова

Нещодавно вийшла "Mbed Studio IDE" для розробки додатків і бібліотек "Mbed OS 5", яка вміщає в собі всі необхідні залежності та інструменти в одному пакеті, що дозволяє створювати, компілювати та налагоджувати програми Mbed на вашому комп'ютері. Це і програмування в стилі Arduino IDE, що допоможе легко стартувати людям, які звикли до Arduino, та хочуть перейти на мікроконтролери STM32. Це і програмування за допомоги HAL бібліотек, для тих, хто вже знайомий з сімейством STM32, та віддає перевагу цим бібліотекам. В цій статті розглянемо встановлення "Mbed Studio IDE", та створення не простого мікроконтролерного "Hello, world!", яким не тільки поблимаємо вбудованим світлодіодом. А щоб переконатись в легкості і доступності розробки на всі смаки, зробімо так - ініціалізуємо і поблимаємо вбудованим світлодіодом на PA_5 за допомоги mbedOS, ініціалізуємо і поблимаємо зовнішнім світлодіодом на PA_9 (який треба приєднати до плати самотужки) за допомоги HAL драйверів. Та не просто поблимаємо ними по черзі з "delay" в основному циклі, а за допомоги переривань з різною частотою. Плюс в основному циклі будемо передавати по UART2 (цей UART2 також надсилає данні і на USB_COM_PORT) лічильник секунд. Піддослідною платою буде STM32F103 Nucleo.

Встановлення Mbed Studio IDE

Завантажте та запустіть інсталяційний файл з "Mbed Studio IDE". Встановлення стандартне без якихось особливостей. Слідуйте вказівкам інсталяційної програми. Після встановлення запустіть Mbed Studio IDE. Та підключіть свою плату Nucleo до USB роз'єму.

Створення демонстраційного проекту

  1. File -> New Program -> Select Example Code "empty Mbed OS program" -> Program name "my_test_blinky" 
    Створення проекту
  2. Відкрийте файл main.cpp, клацнувши по назві файлу в дереві проекту. Зітріть весь текст в полі для коду і вставте цей демонстраційний код (код добре прокоментований додаткових пояснень не потребує):
    #include "mbed.h"
    
    RawSerial pc(USBTX, USBRX);     // tx, rx ініціалізація UART2 для передачі/прийому даних по USB COM PORT
    
    DigitalOut  ledGreen(LED2);     // ініціалізація вбудованого на платі Nucleo світлодіода як цифровий віхід
    
    Ticker flipper1;                // створення ticker з назвою flipper1
    Ticker flipper2;                // створення ticker з назвою flipper2
    
    //--Оголошення прототипів функцій----
    static void flip1(void);        // функція перекидання стану світлодіода PA_5 за допомоги MbedOS
    static void flip2(void);        // функція перекидання стану світлодіода PA_9 за допомоги HAL
    static void ledWhiteInit(void); // функція ініціалізації ніжки PA_9 за допомоги HAL драйверу
    //-----------------------------------
    
    // main() runs in its own thread in the OS
    int main()
    {   
        ledWhiteInit();                // викликаємо функцію ініциалізації ніжки PA_9 за допомоги HAL драйверу
        int counter = 0;               // ініціалізуємо змінну для лічильника секунд
        flipper1.attach(&flip1, 0.5);  // закріплюємо за flipper1 виклик функції flip1 з частотою два рази на секунду
        flipper2.attach(&flip2, 1.5);  // закріплюємо за flipper2 виклик функції flip2 з частотою раз на півтори секунди
        pc.baud(115200);               // встановлюємо швидкість обміну даними по UART2 як 115200
        pc.printf("Hello UART!\n\r");  // надсилаємо привітання в usb_com_port
    
        while (true)
        {
            pc.printf("counter sec = %d\n\r", counter++);   // надсилаємо в usb_com_port значення лічильника
            wait(1.0);                                      // чекаємо 1 секунду
        }
    }
    
    //--функція ініціалізації ніжки PA_9 за допомоги HAL драйверу--
    static void ledWhiteInit(void)
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();                           // викликаємо тактування порту А
        
        GPIO_InitTypeDef GPIO_InitStruct;                       // створюємо структуру для налаштування
    
        GPIO_InitStruct.Pin = GPIO_PIN_9;                       // ніжка 9
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;             // режим вихід
        GPIO_InitStruct.Pull = GPIO_NOPULL;                     
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;           
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);                 // ініціалізуємо
    
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);   // встановлюємо початковий стан "вимкнено"
    }
    //-------------------------------------------------------------
    
    //--функція зміни стану світлодіода на PA_5--------------------
    static void flip1(void)
    {    
        ledGreen = !ledGreen;
    }
    //-------------------------------------------------------------
    
    //--функція зміни стану світлодіода на PA_9--------------------
    static void flip2(void)
    {    
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9);
    }
    //-------------------------------------------------------------
    
  3. Натисніть кнопку "Build program". Перший раз будуватись програма буде довго (декілька хвилин). Будуть завантажуватись всі бібліотеки, залежності і драйвери, які входять до MbedOS. По завершенню компіляції натисніть кнопку "Run program". Ваша програма заллється до пам'яті мікроконтролеру і автоматично запуститься.
  4. З різною частотою заблимають світлодіоди. А запустивши якусь термінальну програму і налаштував її на COM port, до якого під'єднано ваш Nucleo, та швидкість 115200 побачите там лічильник секунд:
    Термінал

Короткий огляд інтерфейсу Mbed Studio IDE

Інтерфейс Mbed Studio IDE
  1. Яка зараз активна програма для розробки;
  2. Яка плата під'єднана для розробки;
  3. Який профіль розробки: debug, develop, release;
  4. Компілювання програми;
  5. Заливка і запуск програми на мікроконтролері;
  6. Поле для редагування коду;
  7. Дерево проекту.

пʼятницю, 1 березня 2019 р.

STM32: Бібліотека для роботи з LCD WH1602(4) або іншим сумісним дисплеєм з контролером HD44780 по I2C шині, або по 4-х бітній шині


Update 11.05.2019: Виправив невиличку помилку, та додав підтримку дисплею LCD2004. Для використання дисплею 2004 в файлі "stm32_device.h" розкоментувати рядок з "#define USE_LCD2004".

Update 25.04.2022: Додано до бібліотеки підтримку декількох мікроконтролерів: STM32 HAL, PSoC PDL, Arduino framework. 

Передмова

У попередній статті "STM32: Бібліотека для роботи з LCD WH1602(4) або іншим сумісним дисплеєм з контролером HD44780" надано бібліотеку для роботи з дисплеєм, виключно, по 4-х бітовій шині. На прохання моїх читачів, допрацював бібліотеку і для роботи з цими дисплеями по шині I2C. Підключення по шині I2C вигідно економить, як кількість з'єднань, так і ніжки мікроконтролеру. Ця бібліотека по своєму функціоналу повністю сумісна з попередньою. Додано і модифіковано тільки роботу з шиною I2C. В варіанті роботи з шиною I2C додається дві функції які вмикають і вимикають підсвітку дисплея. Обрати роботу по шині I2C чи 4-х бітний варіант можна в файлі налаштувань бібліотеки.

Компоненти проекту

  1. Дошка "Синя пігулка"
  2. ST-Link V2
  3. Дисплей LCD1602
  4. Адаптер I2C шини для дисплею PCF8574A

CubeMXforSTM32

В CubeMX створюємо новий проект. Обираємо свій мікроконтролер, або дошку розробника. 
Налаштування шини I2C
  1. Обираємо шину I2C до якої під'єднано дисплей - I2C1
  2. Режим шини - I2C
  3. Налаштування шини - за замовчуванням, нічого не міняв
  4. Дивимось розташування на шпильках сигналів SDA і SCL
Генеруємо проект. Називаємо його, наприклад "STM32F103C8T6_I2C_LCD1602". По завершенню генерації відкриваємо свій засіб розробки.

STM32CubeIDE

Додаємо до проекту файли бібліотеки. Файли "stm32_device.h" та "hd44780.h" до теки "inc" проекту, а файл "hd44780.c" до теки "src" проекту.
Відкриваємо файл проекту "main.c", та підключаємо до головного файлу заголовний файл бібліотеки "hd44780.h" та файл "stm32_device.h"
/* USER CODE BEGIN Includes */
#include "hd44780.h"
#include "stm32_device.h"
/* USER CODE END Includes */
Далі переходимо до файлу "stm32_device.h":
#include "main.h"

#define USE_I2C_BUS
//#define USE_LCD2004

//-------------------------------
/* SET LCD<->MCU CONNECTIONS */
//-------------------------------
#ifdef USE_I2C_BUS

#define LCD_I2C_PORT  hi2c1
#define LCD_I2C_ADDRESS  0x3F

#define LCD_I2C_ADDRESS_8B (LCD_I2C_ADDRESS << 1)
#define PIN_RS      (1 << 0)
#define PIN_EN      (1 << 2)
#define BACKLIGHT   3

extern I2C_HandleTypeDef LCD_I2C_PORT;

#else
Де визначаємо що будемо використовувати шину I2C "#define USE_I2C_BUS". Як потрібна робота з 4-х бітною шиною, то цей рядок потрібно за коментувати і діяти по інструкції з попередньої статті "STM32: Бібліотека для роботи з LCD WH1602(4) або іншим сумісним дисплеєм з контролером HD44780".
Далі налаштовуємо до якого саме порту під'єднано дисплей і яку адресу має дисплей на шині I2C - це рядки "#define LCD_I2C_PORT hi2c1" та "#define LCD_I2C_ADDRESS 0x3F".
Цього достатньо.
Якщо використовуєте дисплей LCD2004, то розкоментуйте рядок "#define USE_LCD2004" в файлі "stm32_device.h"

Демонстраційна програма

Демонстраційний код візьміть з GIT або з попередньої статті "STM32: Бібліотека для роботи з LCD WH1602(4) або іншим сумісним дисплеєм з контролером HD44780". Та пам'ятайте, що для увімкнення, або вимкнення підсвітки дисплею, в варіанті для шини I2C, є окремі функції в бібліотеці.

Архів з бібліотекою

Фото проекту

LCD1602
LCD2004

Відео посібник