Кроссплатформенная (AVR/STM8/ARM) библиотека для работы с экраном от Nokia 3310

Введение

Продолжаю заниматься изучением МК (начало тут и тут). Как-то прикупил по случаю пару-тройку дисплейчиков от Nokia 3310 и вот до них дошли руки. Порыл инет на предмет готовых библиотек. Больше всего понравилась вот эта. Не долго думая, запилил платку, прицепил к ней экранчик, собрал и залил прошивку, соединил экран со своей отладкой… Вот собственно и все – все сразу заработало.

Но так не интересно – чересчур легко все получилось. А где же элемент обучения?
Вот тут мой взгляд и упал на уже месяц пылящиеся STM8S-Discovery и STM32VL-Discovery. Я ж де с STM-ками разбираться обещался, а все доселе не собрался.
Решено – будем портировать либу под STM. А что бы было еще интереснее – решаю что на выходе надо получить одни и те же исходники либы, которые можно собрать под все 3 платформы.

STM32


Реализация

Сказано – сделано. Объявил 2 макроса:

#define SET_LCD_PIN(...) SET_LCD_PIN_(__VA_ARGS__) //Устанавливает заданный уровень (0/1) на указаном пине
#define LCD_PIN_CFG(...) LCD_PIN_CFG_(__VA_ARGS__) //Конфигурирует пин на выход


и реализовал их под каждую платформу:

#ifdef STM8

#include "iostm8.h"

#define SET_LCD_PIN_(PORT, PIN, VAL) P ## PORT ## _ODR_ODR ## PIN = (VAL)
#define LCD_PIN_CFG_(PORT, PIN) P ## PORT ## _DDR_DDR ## PIN = 1; \
                                P ## PORT ## _CR1_C1 ## PIN = 1;  \
                                P ## PORT ## _CR2_C2 ## PIN = 1

#elif defined(ARM)

#include "stm32f10x.h"

#define SET_LCD_PIN_(PORT, PIN, VAL) GPIO ## PORT ## ->BSRR = 1 << (PIN + !(VAL) * 16)
#define LCD_PIN_CFG_(PORT, PIN) *((uint32_t*)GPIO ## PORT ## + 1 * (PIN > 7)) = *((uint32_t*)GPIO ## PORT ## + 1 * (PIN > 7)) & ~(0xC << (PIN % 8 * 4)) | (0x3 << (PIN % 8 * 4))

#elif defined(AVR)

#include "avr/io.h"
#include "avr/pgmspace.h"

typedef struct
{
  unsigned char b0  : 1;
  unsigned char b1  : 1;
  unsigned char b2  : 1;
  unsigned char b3  : 1;
  unsigned char b4  : 1;
  unsigned char b5  : 1;
  unsigned char b6  : 1;
  unsigned char b7  : 1;
} __BYTE_BITS;

typedef union   
{                                        
	unsigned char BYTE;                     
	__BYTE_BITS bits;                
} BYTE_BITS;

#define SET_LCD_PIN_(PORTNAME, PIN, VAL) ((volatile BYTE_BITS*)&PORT ## PORTNAME)->bits.b##PIN = (VAL);
#define LCD_PIN_CFG_(PORT, PIN) DDR ## PORT |= 1 << PIN

#else 

#error "The platform is not defined"

#endif


Вся работа с оборудованием осуществляется посредством этих 2-х макросов.
Внимание! Единственное отступление от этого правила — включение тактирования шины GPIO (APB2 для STM32F100) в случае STM32 реализовано прямо в коде функции LcdInit:


#ifdef ARM
    // Включаем тактирование шины APB2
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
#endif    


Под другие линейки эту строчку скорее всего придется заменить.
Поскольку у AVR разные подходы при работе с данными в памяти и во флеше, для STM, у которых единое адресное пространство, добавлены следующие дефинишины:

#ifndef PROGMEM
	#define PROGMEM
#endif

#ifndef pgm_read_byte
	#define pgm_read_byte(x) *x
#endif

#ifndef AVR
	#define memcpy_P(...) memcpy(__VA_ARGS__)
#endif

#ifndef PSTR
	#define PSTR(x) x
#endif


Да, так как это мой первый проект под STM вообще (и для IAR в частности), еще я заменил использование аппаратного SPI програмной реализацией. За компанию это позволило цеплять любой пин экрана на любой пин любого порта контроллера.

Использование

Для использования библиотеки нужно не много:

1. Указать желаемые пины в виде <имя порта>, <номер пина>:

#define LCD_DC_PIN                 B, 1
#define LCD_CE_PIN                 В, 2
#define LCD_RST_PIN                C, 3
#define LCD_SDIN_PIN               С, 4 
#define LCD_SCLK_PIN               D, 5 



2. И определить целевую платформу. Либо в настройках препроцессора, либо прямо в коде:

#define AVR
//#define STM8
//#define ARM



Результаты

AVR
AVR

STM8
STM8

STM32
STM32

Вложения

В архиве плата, библиотека, проекты для AVR (AVR Studio 5), STM8 (IAR 6.1.6), STM32 (IAR 6.30) и модель Proteus для AVR (в папке с моделью находится библиотека Proteus для экранчика).

Update: По совету evsi убрал конфигурацию периферии для STM32 из кода. Вместо этого добавил 2 макроса:

#define LCD_PRE_CFG   //Предварительная конфигурация перифирии (до конфигурации портов)
#define LCD_POST_CFG  //Пост конфигурация перифирии (после конфигурации портов)

Таким образом теперь весь HAL (Hardvare access level) находится в макросах в файле n3310.h

P.S. Посоветуйте, пожалуйста, как лучше организовать подстветку этого экрана. Когда-то видел статью по этому поводу, но че-то никак не могу найти ее.
  • +6
  • 28 апреля 2012, 13:32
  • Victor

Комментарии (17)

RSS свернуть / развернуть
Предпоследняя картинка подписана как AVR, хотя это STM8.

По поводу кода. Глубоко не копал, но настоятельно рекомендую заменить включение периферии в LcdInit на макрос, который на STM32 разворачивается в реальный код, а в остальных будет пустышкой. Иначе не консистентно получается — все архитектурно-зависимые куски, вроде как, вместе, а конкретно этот — прямо в коде. Ну и при портировании еще куда-либо можно легко наступить на грабли, поскольку наличие архитектурной специфики надо искать по всему коду библиотеки.
0
  • avatar
  • evsi
  • 28 апреля 2012, 14:06
Предпоследняя картинка подписана как AVR, хотя это STM8.

Поправил
рекомендую заменить включение периферии в LcdInit на макрос

Согласен. Спасибо! Поправил и перевыложил архив.
0
Пробывал подсвечивать его с боков — получается отвратительно (очень чуствительно к высоте подъема над платой и смещению, засветка экрана не равномерная).
>T---T
 |   |<
 |   |<
>L___J

Пробывал с низу (3 светодиода всетят в скос вдоль экрана) довольно неплохо
T---T
 |   |
 |   |
 L___J
 ^ ^ ^

Где-то видел еще подсветку скоса с задней стороны, но у меня такой способ вышел не очень (вольшая часть света просто проходит преломляясь, получается что на скос ещё отражатель надо или просто закрывать светонепроницаемой краской/пластмассой, и соответственно яркость экрана низкая).
0
да, если ставить снизу не 3 а 4 светика, то получается более равномерная засветка экрана.
0
Спасибо, попробую.
В принципе именно с этого и думал начать — вроде именно так организована подсветка в самом телефоне.
Вобщем буду экспериментировать.
0
От себя предложу по поводу подсветки: закупить (если есть возможность) экранов от Nokia 1202/1203/1280… При стоимости в 29 рублей (на момент покупки мною, сейчас чутка подорожали) они себя прекрасно ведут. Подсветка у них уже встроенная, ровная и красивая, на 3,3 вольта. Управляются аналогично экрану от 3310.
Если сильно напрягает паять шлейф такой (паяется он не сложно, говорю как человек с очень слабыми навыками пайки), можно посмотреть в сторону экранов Nokia 1100, стоят чуть дороже. Брать обязательно с подложкой (они есть еще и отдельно, но тогда подсветку фиг сделаешь). Подложку можно укоротить как и у 3310. Управляются тоже аналогично. Контакты паяются обычным многожильным кабелем.

PS: знаю-знаю, предлагать решение вроде «выкинь эти и купи другие» — не совсем корректно (хотя я выкинуть и не предлагал), ну я на всякий случай, ибо сам прошел этот путь (и с 3310 игрался). В итоге пришел к тому, что 1202 самые что ни на есть :) Ну это конечно личное мнение, оно может не совпадать с общественным :) Так что на будущее можете их прикупить, если попадутся.

PPS: посмотрел ваши «старты» на форуме, очень хорошие старты, скажу я вам! Молодец! И статья хорошая! Основательно!
0
Спасибо.
На самом деле совет не так уж и плох — я к этим дисплейчикам уже присматривался на перспективу.
Единственное что смущает — у них SPI 9бит. При «ногодрыгательстве» это не проблема, но хотелось бы задействовать аппаратный SPI. Вот тут вылезает проблемка — стм (которая на ближайшее время планируется как основная платформа) поддерживает либо 8 либо 16 бит… C другой стороны — можно USART поиспользовать для этих целей, тем более что у STM их много.

Но пока надо использовать 3310 — просто по случаю прикупил уже четыре штуки (правда один оказался не рабочий) по $1/шт.

PPS: посмотрел ваши «старты» на форуме, очень хорошие старты, скажу я вам! Молодец! И статья хорошая! Основательно!
Спасибо!
0
А разве не 9 бит у стмок? Я могу ошибаться, но как раз вроде у стмок можно 9-битный забахать аппаратно. Нет, вру, глянул в ДШ — действительно 8 и 16…
Ну елки, ногодрыг никто не отменял :) Тем более на камне с 48-72 мгц скорости это даже и не заметить будет :)
Ну а если надо 8 бит, то недавно описывали не очень дешевый, но прикольный экранчик с 8 битами и 3,3 вольтовой подсветкой.
0
Ну елки, ногодрыг никто не отменял :)

Да это понятно :) Просто, как по мне, гораздо «красивше» пнуть заливку данных из фрейм буфера через аппаратный SPI посредством DMA и спокойно заниматься чем-то полезным, пока прерывание не прибежит.
Кстати, по идее то же можно получить и через USART. Может даже и лучше, учитвая что их (USARTов) обычно даже больше чем SPIев. Так что будет из чего выбрать при разводке платы. Особенно учитывая ремапы.
Ну и, на худой конец, можно и ногами подрыгать :)

Но то в будущем, а ныне (с) В.Высоцкий — у меня пока 3 3310-х есть. На ближайшее время должно хватить.
0
тогда это будет уже не универсальная бблиотека. Где вы видели ДМА на тини45?
Я благополучно переломал имеющиеся у меня «лишние» 3310, о чём не жалею. Применять их в готовой конструкции — нечто не традиционное.
0
зачем пихать работу с портами и инициализацию периферии в библиотеку?
имхо это лишнее
0
А как использовать эту библиотеку в Keil? STM32F100RB(diskavery). У меня не получается!!!
0
Поясните пожалуйста что делает эта строка? #define CHINA_LCD
Директива define служит для замены часто использующихся констант, я так понимаю переменная CHINA_LCD должна замениться в тексте на что то…
0
#define используется также не только лдля замены, но и в качестве «присутствия определения». Так следующий код
#ifdef SIMPLE_FLAG
// same code
#endif
Будет скомпилирован при наличии перед ним определения
#define SIMPLE_FLAG
Или не будет, при отсутствии данного «определения».
0
Спасибо теперь разобрался, если закомментировать эту строку кусок кода относящийся к клону компилироваться не будет. И соответственно если раскомментировать, то наоборот.
0
Ссылка умерла, поделитесь если у кого осталось
0
Ссылка умерла, поделитесь.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.