Технические характеристики LCD Nokia3310:
- Напряжение питания 2,7 – 3,3 В- Встроенный контроллер Philips PCD8544
- Интерфейс SPI
- Размер дисплея 38х35 мм
- Размер активной области 30х22 мм
- Разрешение 84х48 пикселей
- Диапазон рабочих температур –27…+70 0С
Схема подключения к микроконтроллеру
Питание схемы 3,3 В. Если понадобится подключать экран к схеме с 5 вольтовым питанием, нужно будет делать схему согласования уровней. Скорее всего, она будет выглядеть так. Сам не проверял, поправьте, если ошибаюсь.
Распиновка LCD Nokia3310
Программная часть
Повозившись пару дней с этим дисплейчиком, я накатал аж целых три проекта. На этот раз не стал изобретать велосипед, а взял готовую библиотеку для микроконтроллера MSP430 и переделал ее под AVR.
Библиотека оказалась очень тяжеловесной, и IAR не захотел ее компилировать для ATMega8535. В программе был организован видео-буфер на 504 байта и компилятор ругался на нехватку ОЗУ. Зачем нужен видео-буфер? Дело в том, что контроллер этого дисплея позволяет записывать данные в свою память, но не позволяет их считывать. Это сильно ограничивает возможности по работе с дисплеем - нельзя, например, наложить одно изображение на другое. Один из путей решения проблемы - буфер в ОЗУ микроконтроллера, хранящий все, что в данный момент отображается на экране. Запись и считывание данных производятся сначала в буфер, и только потом весь буфер выводится на дисплей.
Поскольку ATMega8535 пожалуй самый ходовой микроконтроллер в моих поделках, мне захотелось переделать библиотеку под него. Поэтому я удалил видео-буфер и переписал все функции, где он использовался. Добавил англо-русский шрифт, и получился отличный знакогенератор без всяких наворотов.
Исходник библиотеки.
Тестовый проект.
Описание на контроллер дисплея.
Собственно для работы с дисплеем достаточно трех функций
void LCDInit(void)
Конфигурирует выводы PORTB в режим выхода, настраивает модуль SPI, подает сигнал сброса контроллеру дисплея и последовательность команд для его настройки.
void LCDClear(void)
Полностью очищает дисплей.
void LCDStr(unsigned char x, unsigned char row, unsigned char *dataPtr )
Выводит текстовую строку на дисплей. X – знакоместо. Принимает значения от 0 до 13. Если строка не помещается на дисплее, оставшаяся часть просто не выводится. Row – номер строки. Может принимать значения от 0 до 5. Верхняя строка считается нулевой.
Пример:
LCDStr(0, 2, “lcd Nokia3310” );
Comments
в самой 3310 как я вижу весь текст имеет высоту 8 пикселей, но выводится он с произвольных точек (ордината не обязательно кратна восьми). Интересно, как сделано? надо даташит PCF8814 покурить, может там есть чего.
и еще вопрос - сейчас Data Write именно _присваивает_ текущему байту заданное значение. А нет ли способов вместо присваивания делать, скажем, операции "И", "ИЛИ"? типа операции |= и &=
Всё же смотрю на мобилу, катаюсь по менюшкам и не могу понять - как же происходит вывод текста на экран в точку с координатами, некратными восьми...
И, ИЛИ, Исключающее ИЛИ
Короче говоря, если возиться с дисплеем на низком уровне (ну или писать библиотеку самому с нуля) - то рисовать на нём можно ТОЛЬКО столбиками по 8 бит, затирая то что уже нарисовано под этим столбиком. Других способов рисования драйвер дисплея не предусматривает . Я правильно понял?
Во-первых, разрешение у него 37х84 :o
Во-вторых, столбики не по восемь точек идут, а вот так: 1 столбик на 4 точки, 5 столбов по 6 точек и 1 по 3. И когда я посылаю первую строку байтов, точки выводятся только под действием последних 4-х бит.
Это чё за хрень такая? Так и должно быть или я чё-то не так настроил? :-?
>Дисплей точно от Nokia3310?
Скорее всего. Брал тут http://shop.siriust.ru/product_info.php/products_id/382
microsmaster собака rambler.ru
Какой там чип, как подключаться (хочется по i2c)
http://www.embedds.com/nokia-1100-lcd-and-pic-interface-the-best-combination-that-you-can-think-about/
Но тема все таки все еще актуальна (по ссылке проект с экраном от Nokia 1100, он даже выглядит немного иначе).
а как выводить дополнительные фонты?вопрос снимается, я плохо код посмотрел :-)
добавил дополнительный буферок (само собой 504 байта)...
теперь по извращенному можно выводить любые загруженные спрайты, вывод пикселей...
любая графика выводится сначала в буфер, затем буфер побайтово копируется сразу весь на экран.
Пишу даже
LCDInit();
LCDContrast(0x0 0);
LCDClear();
LCDStr(0, 0, "Курсова робота");
но никаких изменений,?
Вот дисплей: смотрю на него. На экран. Лично у меня он сзади чем-то закрыт: непрозрачный. Если б я мог насквозь видеть, то б эти 8 ног были сверху и рядом с правой (если продолжать смотреть на экран, а не на ноги) был б такой пластмассовый выступ.
Если тема еще не заглохла, подскажите, кому не трудно, как осуществить все это на АТмеге 8? Скачал тестовый проект и пытаюсь в нем разобраться.
Полностью использовать порт B не получится, ибо на нем висит кварец. Хочу перекинуть на порт D. В хидере lcd_nokia3310pi n.h заменил в дефайнах DDRB и PORTB на DDRD и PORTD соответственно. Распаял к ногам МК. Чуда не произошло, ничего не заработало.
Но, при скидывании шлейфа программатора (в режиме RUN, не PROG) появляется горизонтальная полоска на экране.
Подпаял другой дисплей - все заработало.
Огромное спасибо за проект!
может быть ктото придумал что нить дельное с подключением таких дисплеев ? чтобы и не паяться и контакт был надежный?
никто никаких колодок не делал (или может покупал где нить) для подобных дисплеев?
Какую половину символов нужно убрать?
и дополнительно делал токен-печать - это когда по одному коду - печаталось целое слово из словаря.. - если много слов которые повторяются (всякие ON\OFF, SETTINGS, CHANNEL и т.д.) - то можно значительно сократить код..- у меня оптимизация достигла 50%..
коды токенов находились в области маленьких лат. и рус. букв
Взял твои метода по работе с шрифтом(ну и сам шрифт) и впихнул их в свою самоделку на MSP430. Вот такой круговорот кода.
Не подскажешь где брал исходники на MSP430 с буфером?
сами процедуры не сильно отличаются..
Code:
void LCD_pixel (unsigned char x, unsigned char y, unsigned char mode) { // вывод пиксела
if ((x<128)&&(y<64)) {
unsigned char i=y>>3;
unsigned char bt=1<<(y & 0x7);
if (mode!=0) lcd_buff[128*i+x]|=bt;
else lcd_buff[128*i+x]&=(~bt);
}
}
точки я думаю понятно как рисовать..
это для экрана 128 на 64 точки, поставьте свои размеры и вперед..
правда конечно буфер экрана нужен ! без него никак при графике
а для линий смотрите в интернете алгоритм Брезенхейма - он есть для линий и для дуг..
в принципе для линий я и на СИ и на Асме писал - действительно не сложный и быстрый
вот на си
Code:
void LCD_line(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, char mode) { // процедура рисования линии
signed char dx, dy, sx, sy;
unsigned char x, y, mdx, mdy, l;
dx=x2-x1; dy=y2-y1;
if (dx>=0) { mdx=dx; sx=1; } else { mdx=x1-x2; sx=-1; }
if (dy>=0) { mdy=dy; sy=1; } else { mdy=y1-y2; sy=-1; }
x=x1; y=y1;
if (mdx>=mdy) {
l=mdx;
while (l>0) {
if (dy>0) { y=y1+mdy*(x-x1)/mdx; }
else { y=y1-mdy*(x-x1)/mdx; }
LCD_pixel(x,y,mode);
x=x+sx;
l--;
}
} else {
l=mdy;
while (l>0) {
if (dy>0) { x=x1+((mdx*(y-y1))/mdy); }
else { x=x1+((mdx*(y1-y))/mdy); }
LCD_pixel(x,y,mode);
y=y+sy;
l--;
}
}
}
текст тоже можно написать процедуру чтобы выводить с точностью до пиксела.. причем символы не рисовать по точкам, а именно выводить верхнюю\нижнюю часть...
К сожалению код сюда уже не уместился...
Code:
void LCD_char(unsigned char ch, unsigned char mode) { // Вывод символа
const unsigned char *fontpointer;
if (ch<127) { // знакогенератор латиницы
fontpointer=NewFontLAT; ch=ch-32; }
else { // знакогенератор русских букв
fontpointer=NewFontRUS; ch=ch-192;}
if (mode==2) mode=lcd_blink; // если нужно отображать в режиме мерцания - то берем значение инверсии из lcd_blink
unsigned char lcd_YP=7- (lcd_Y & 0x07); // битовая позиция символа в байте
unsigned char lcd_YC=(lcd_Y & 0xF8)/8; // байтовая позиция символа на экране
for (unsigned char x=0; x<6; x++) {
unsigned char temp=pgm_read_byte(fontpointer+ch*6+x);
if (mode!=0) {
temp=~temp;
if (lcd_Y>0) LCD_pixel(lcd_X, lcd_Y-1, 1); // если печать в режиме инверсии - сверху отчертим линию
}
temp&=0x7F;
lcd_buff[lcd_YC*128+lcd_X]=lcd_buff[lcd_YC*128+lcd_X] | (temp<<(7-lcd_YP)); // печать верхней части символа
if (lcd_YP<7) lcd_buff[(lcd_YC+1)*128+lcd_X]=lcd_buff[(lcd_YC+1)*128+lcd_X] | (temp>>(lcd_YP+1)); // печать нижней части символа
lcd_X++;
if (lcd_X>126) return;
}
}
А по поводу 84 бит, это фишка этого дисплея.
Я хотел использовать без обработки формат XBM(который фактически является массивом на Си и его можно просто инклудить), еще его особенность что если длина строки не кратна 8ми то бит добивается нулями.
А тут у экрана 84 бита на строку, а в XBM 88 бит на строку и чтобы вывести все приходится при новой строке явно указывать ее номер. Еще чудес добавляет то, что вывод 1ого байта это вывод колонки из 8ми пикселей. Я с компа привык к нормальной построчной адресации. Тут такого нет. Вот и хочется написать обертку чтобы было. И сделать свою демку с графикой. А если упрусь в возможности контроллера, то возьму покруче, но это уже MSP430-ый офтоп.
Кстати вывод я только что переделал на вертикальную адресацию и там стало все хорошо ибо теперь по длине картинки 48бит.
ПС. Знаю что немного путано(
вот мой код Code:
#include <mega8.h>
Вот что получаю#include "driver_nokia3310.h"
void main( void )
{
unsigned char* counterProg = 0;
LCDInit();
LCDClear();
while(1){
counterProg++;
LCDStr(0, 3,counterProg);
delay_ms(100);
}
}
Вопрос: откуда берется надпись "Pashgan"?
Почему вместо counterProg получаю какую то муть и как увеличить контрастность дисплея?
И можно ли убрать мусор из последних строк?
UPD 2.По поводу контрастности разобрался
Я поступил следующим образом
Функция sprintf стандартной библиотеки stdio.h
sprintf – функция для вывода форматированных данных в строку.
Code:
#include <mega8.h>
#include <stdio.h>
#include "driver_nokia3310.h" // использую lcd от siemens c55
unsigned char array[6];
unsigned char temp;
void main( void )
{
LCDInit();
LCDClear();
LCDContrast(75);
sprintf(array,"t %u",temp);
while(1)
{
LCDClear();
sprintf(array,"t %u",temp);
LCDStr(3, 6, array);
delay_ms(500);
temp++;
}
}
Ну а по поводу мусора я решил проблему повысив разрешение с 84*48 до 101*64 так кат у меня LCD от Siemens C55. В твоем случаи попробуй поставить чуть больше разширение методом тыка.
По-моему сейчас он уже не продается. Вместо него STK600.
RSS feed for comments to this post