Внешний дисплей от Nokia 2760
Давно уже лежит у меня данный дисплей, но до сих пор на него времени всё не хватало. А задача для него то уже придумана и только и ждет воплощения. И вот все прочие дела наконец были отброшены и результат не заставил себя долго ждать.
Сразу отвечу на вопрос: Даташита у меня НЕТ! Все работает и без него.
Характеристики
Как я уже писал, дисплей очень маленький и обладает следующими характеристиками:
- Диагональ: 1 дюйм (20х16мм);
- Разрешение заявленное: 96х68 пикселей (в телефоне заявлено 96х65 пикселей);
- Размер: 24х24х3мм;
- Глубина цвета: монохромный;
- Подсветка: синяя (6-8В с резистором 47-300Ом);
- Интерфейс: 3-х проводной SPI 9 бит;
- Контроллер: ST7507 (Спасибо тов. WildCat);
- Питание цифровой части: 1.8-3.3В;
- Питание аналоговой части: 2.4-3.3В;
Не правда ли красавец? И по очень аппетитной цене.
Исходные данные
Очередной раз моя благодарность отправляется тов. Rossum’у, его поистине великий труд в изучении дисплеев очень помог.
Так же в данных одного из проектов был откопан моноширинный шрифт 5х7 который так же используется в дисплее от Nokia 3310.
Google же на этот раз дополнительной информации принес не много. Даташит так и не был найден. Жалко конечно, но зато есть возможность поковыряться самостоятельно.
Подключение
Распиновку дисплея можно узнать из Service Manual’а или же заглянув в проект NokiaSuperbreakout от Rossum’а:
Разъем такой же как у Nokia 6100 (распиновка не совпадает!), и ответная часть находиться так же.
К своей LPCXpresso я подключил к SPI выводам: SCLK-SCK, MOSI-MOSI, CS-SSEL, RESET-MISO (а почему бы и нет?). Питание на подсветку завел с отдельного преобразователя на MC34063. Хотя на отражение (без подсветки) всё видно наверное даже лучше.
Настраиваем SPI на 9 бит
Инициализация SPI для дисплеев у меня кочует из проекта в проект практически без изменений, а я никак её не помещу в библиотеку (других учу, а сам этого не делаю):
void SPI_init() { // Раздел 13.2 UM10375
LPC_SYSCON->PRESETCTRL &= ~(1<<0);
LPC_SYSCON->PRESETCTRL |= (1<<0);
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);
LPC_SSP->CPSR = 0; // отключим тактирование
// Set P0.9 to SSP MOSI
LPC_IOCON->PIO0_9 &= ~(7<<0);
LPC_IOCON->PIO0_9 |= (1<<0);
LPC_IOCON->PIO0_9 |= IOCON_COMMON_MODE_PULLUP;
// Set 2.11 to SSP SCK (0.6 and 0.10 can also be used)
LPC_IOCON->SCKLOC = 1;
LPC_IOCON->PIO2_11 &= ~(7<<0);
LPC_IOCON->PIO2_11 |= (1<<0);
LPC_IOCON->PIO2_11 |= IOCON_COMMON_MODE_PULLUP;
// Set P0.2/SSEL to GPIO output and high
LPC_IOCON->PIO0_2 &= ~(7<<0);
LPC_IOCON->PIO0_2 |= (1<<0);
LPC_IOCON->PIO0_2 |= IOCON_COMMON_MODE_PULLUP;
LPC_GPIO0->DIR |= 1<<2;
LPC_GPIO0->DATA |= 1<<2;
LPC_SSP->CR0 = ( (8<<0) // Размер данных 1000 - 9 бит
| (0<<4) // Формат фрейма 00 - SPI
| (0<<6) // Полярность 0 - низкий уровень м/у фрейм
| (0<<7) // Фаза 0 - по нарастанию
| (8<<8) // Делитель частоты шины на бит
) ;
LPC_SSP->CPSR = 2; // пердделитель 2-254 (кратно 2)
LPC_SSP->CR1 = (1<<1); // Разрешение работы 1 - разрешено
}
Эх, настроили на 9 бит и 4 МГц. Гм..., в теории должно быть FPS ~500. Что бы максимально приблизиться к этой цифре, передачу данных осуществляется в фоне:
void SPI_send(uint16_t value) {
while ((LPC_SSP->SR & ((1<<1) | (1<<4))) != (1<<1));
LPC_SSP->DR = value;
}
Подробнее что к чему было описано в уроке, не станем задерживаться на этом здесь.
Инициализация дисплея
SPI нам нужен для дисплея, а дисплей перед общением с ним лучше сбросить. Сброс простецкий, но из-за криворукости лишний раз переключим функцию вывода SSEL:
void LCD_reset(void) {
// Настройка для вывода Reset дисплея
LPC_IOCON->PIO0_8 &= ~(7<<0); // сброс текущей функции порта ввода-вывода
LPC_IOCON->PIO0_8 |= IOCON_COMMON_MODE_PULLUP;
LPC_GPIO0->DIR |= 1<<8;
LPC_GPIO0->DATA |= 1<<8;
// Настройка для вывода Select
LPC_IOCON->PIO0_2 &= ~(7<<0); // Временно отключаем спецфункцию вывода выбора SPI
delay_ms(100);
// Сброс дисплея
LPC_GPIO0->DATA &= ~(1<<2); // ncs = 0
LPC_GPIO0->DATA &= ~(1<<8); // nrst = 0
delay_ms(100);
LPC_GPIO0->DATA |= 1<<8; // nrst = 1
LPC_GPIO0->DATA |= 1<<2; // ncs = 1
delay_ms(100);
// Возврат спецфункции
LPC_IOCON->PIO0_2 |= (1<<0); // использовать как вывод SSEL
}
Добавляем сюда инициализацию из NokiaSuperbreakout и получаем следующее:
void LCD_init()
{
SPI_init();
LCD_reset();
SPI_send(0xE2);
delay_ms(10);
SPI_send(0xAF);
SPI_send(0xA4);
SPI_send(0x2F);
SPI_send(0xB0);
SPI_send(0x10);
SPI_send(0x00);
}
После этого спокойно можно последовательно выводить данные на дисплей, как это делается в оригинале.
Вывод текста на дисплей
Вывод идет, так же как и для 3310, построчно столбиками по 8 пикселей, младший бит выводится вверху. Разница только в том, что 2760 инверсный: 0 соответствует черной точке, 1 её отсутствию. Последняя 9-я строка получается неполноценная. От неё доступны только младшие 4 бита.
Ну а раз работает всё так же, то возьмем вывод текста от 3310 для этого дисплея:
#include "font5x8.h"
void LCD_DrawChar(char c) {
int i;
unsigned char *ptr = &font[5*(unsigned int)c];
for(i = 0; i < 5; i++) {
SPI_send(0x100|~ptr[i]);
}
SPI_send(0x1FF); // пробел
}
void LCD_DrawString(const char *c) {
while(*c) LCD_DrawChar(*c++);
}
Теперь весь дисплей можно заполнить символами. Что тоже нам не очень интересно, мы ведь привыкли указывать другим, что им делать. Так что без установки позиции курсора никуда:
void LCD_SetPos(uint8_t x, uint8_t row) {
if(row > 9) row = 0;
if(x > 96) x = 0;
SPI_send(0xB0|(row)); // Номер строки
SPI_send(0x10|(x>>4)); // Старшие 4 бита номера столбца
SPI_send(0x0F&(x)); // Младшие 4 бита номера столбца
}
Конечно, для моноширинного шрифта было бы лучше позиционировать по ширине символа, что впрочем делается простым умножением.
Вот теперь пожалуй всё готово, можно пользоваться:
Заключение
Дисплей оказался настолько простым в подключении, насколько и маленьким в размерах. При всём при этом он обладает довольно хорошим разрешением, что позволяет ему вместить большое количество информации (8 строк по 16 символов). Однако из-за этого мы получаем довольно мелкий текст (раза в 2 меньше 3310). Выход из этой ситуации естественно есть, достаточно просто взять шрифт крупнее.
Скорость вывода меня вполне устраивает, отклик дисплея в районе 0.2с (что по моему субъективному мнению быстрее, чем у 3310).
Потребление не замерял. Заявлено 0.5мА в активном режиме. Если для кого-то это принципиальный вопрос, то можете замерить сами.
Самая потребляющая часть – подсветка - может быть успешно отключена, на отражение видно прекрасно. Но её присутствие только в плюс дисплею в темное время.
В прикрепленном архиве отладочный проект. Вот несколько скринов его выполнения (2-х метровые файлы не поместили, так что только так):
Видео (качество не лучшее получилось).
Файлы: nokia2760.zip, DSC03013.JPG