Знакомство с STM32 я начал с платы STM32L-DISСOVERY,купил ее для знакомства с семейством.Но вскоре обнаружил для себя некоторые недостатки.Например почему не установлен внешний кварц ? не установлен отсек для батарейки,хотя место есть...Нет, я конечно могу припаять сам,но зачем например начинающему это делать?Да и LCD на плате отнимал много ног,а хотелось его оставить.Решено было использовать плату для другого проекта.
Короче ,это я к тому ,что купил себе плату STM32F4 DISCOVERY.Первые впечетления очень положительные,куча примеров,на "борту" тоже все довольно солидно.Особенно заинтересовал аудиоЦАП.Да и количество пинов - есть куда розвиваться.
Итак F4,с чего-же начать.Под рукой был LCD st7920 от AVR-ских проектов.Решено было использовать его.К моему удивлению, в интернете не особо много информации по этому поводу.Достойными внимания были два источника : www.coocox.org , radiokot.ru/forum .Обе библиотеки я портировал на STM32F4 .На СоСохе библиотека поддерживает встроенные символы ( 4 строки по 16 символов ) ,ну и иероглыфы.Минимальная графика.На РадиоКоте библиотека "поярче" : свой шрифт ( 8 строк ),побольше чем в предыдущей библиотеке функций .Но все-же, хотелось такого функционала как в библиотеке u8glib (https://code.google.com/p/u8glib/ ),c которой я имел возможность познакомится на AVR-ках.
И тут случайно наткнулся в сети на материал http://blog.bastelhalde.de/?p=759#comment-1567 .Человек портировал STM32F101CBT6 на дисплей SSD1306 под библиотекой u8glib .Взяв за основу эту информацию, решил и я "прикрутить" дисплей st7920 к плате stm32f4 discovery.
Следуя рекомендациям ,по выше приведенной ссылке ,создал два новых файла u8g_arm.c и u8g_arm.h .
/* u8g_arm.h */
#ifndef _U8G_ARM_H
#define _U8G_ARM_H
#include "u8g.h"
#include "stm32f4xx_conf.h"
#define CS_ON() GPIO_SetBits(GPIOA, GPIO_Pin_6) //Аппаратный CS
#define CS_OFF() GPIO_ResetBits(GPIOA, GPIO_Pin_6)
//*************************************************************************
void Delay_mss (void);
void init_SPI1 (void);
void SPI_Out_LCD12864_Ap (uint8_t Data_LCD12864);
void LCD_OUT (uint8_t Data_LCD, uint8_t Np_LCD);
uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
#endif
/* u8g_arm.c */
По шаблону отсюда - http://blog.bastelhalde.de/?p=759#comment-1567 ,сделал для stm32f4 - SPI1.
uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
switch(msg)
{
case U8G_COM_MSG_STOP:
//STOP THE DEVICE
break;
case U8G_COM_MSG_INIT:
//INIT HARDWARE INTERFACES, TIMERS, GPIOS...
Delay_mss(); //Ждем, пока контроллер LCD включится.
SystemInit(); //Инициализация настроек кварца
init_SPI1() ; //Инициализация SPI1 (stm32f4)
break;
case U8G_COM_MSG_ADDRESS:
//SWITCH FROM DATA TO COMMAND MODE (arg_val == 0 for command mode)
//управляющий байт переключает режим на устройстве и устанавливается здесь
// define cmd (arg_val = 0) or data mode (arg_val = 1)
// cmd - передача команды ,data mode - режим передачи данных
if (arg_val == 0)
{
control = 0xF8;
}
else
{
control = 0xFA;
}
u8g_10MicroDelay();
break;
case U8G_COM_MSG_RESET:
//TOGGLE THE RESET PIN ON THE DISPLAY BY THE VALUE IN arg_val
break;
case U8G_COM_MSG_WRITE_BYTE:
//WRITE BYTE TO DEVICE
//ЗАПИСЬ байта НА УСТРОЙСТВО
LCD_OUT (arg_val, control);
u8g_MicroDelay();
break;
case U8G_COM_MSG_WRITE_SEQ:
case U8G_COM_MSG_WRITE_SEQ_P:
//WRITE A SEQUENCE OF BYTES TO THE DEVICE
//ЗАПИСЬ ПОСЛЕДОВАТЕЛЬНОСТИ БАЙТОВ НА УСТРОЙСТВО
{
register uint8_t *ptr = arg_ptr;
CS_ON(); //Передача начата.
SPI_Out_LCD12864_Ap (control);
while( arg_val > 0 )
{
SPI_Out_LCD12864_Ap( *ptr & 0xF0); //Старшая половина и 4 "0".
SPI_Out_LCD12864_Ap( *ptr << 4); //Младшая и 4 "0".
*ptr++;
arg_val--;
}
CS_OFF();
}
break;
}
return 1;
}
/* main.c */
Функция инициализации LCD :
u8g_InitComFn(&u8g, &u8g_dev_st7920_128x64_hw_spi, u8g_com_hw_spi_fn);
Тестовый поект для Keil - http://radiomanoff.at.ua/load/stm32f4_u8glib_st7920/1-1-0-25