mmote.ru/content/posts/avr-lcd-images/index.md

91 lines
4.3 KiB
Markdown
Raw Permalink Normal View History

2023-01-01 18:21:01 +03:00
---
title: "Вывод иконок на дисплей Nokia 3310/5110 (переходим на avr-gcc)"
categories: ["mcu", "archive"]
date: 2015-08-13T00:00:00+03:00
draft: false
featured_image: miniature.jpg
---
Наконец-то переехал с CVAvr на AVR-GCC. От нечего делать начал собирать барометр. Купил nokia3310, выдрал дисплей. Библиотеку использовал [вот эту](https://github.com/gresolio/N3310Lib). Всё отлично, но библиотека умеет рисовать круги, линии, прямоугольники, выводить полноэкранные изображения, НО. Что должен уметь электронный барометр?
<!--more-->
Правильно, определять погоду по давлению. И выводить картинку с облачком или солнышком. А с полноэкранным изображением это делать не вариант - занимает кучу памяти да и с обновлением дисплея будет беда. Так что, я взялся за дело. Просидев весь вечер, написал программку-рисовалку картинок с конвертацией в массив и функцию-дополнение к библиотеке. Вот так выглядит программа:
![LCDPict|](lcdpict.png)
Прямая ссылка, по традиции, в конце статьи.
Функция выглядит следующим образом:
```c
byte LCDIcon(const byte *pic, byte x, byte y, byte arrayRows, byte arrayColumns, byte progMem) {
byte iterCol;
byte iterRow;
byte iterByte;
byte picX = x;
byte picY = y;
byte symbolChar;
for (iterCol = 0; iterCol < arrayColumns; iterCol++) {
for (iterRow = 0; iterRow < arrayRows; iterRow++) {
if (progMem) {
symbolChar = (byte) pgm_read_byte(&pic[iterCol + iterRow * arrayColumns]);
} else {
symbolChar = pic[iterCol + iterRow * arrayColumns];
}
for (iterByte = 0; iterByte < 8; iterByte++) {
if ((symbolChar >> iterByte) & 1) {
LcdPixel(picX, picY, PIXEL_ON);
}
picY++;
}
}
picY = y;
picX++;
}
UpdateLcd = TRUE;
return OK;
}
```
В качестве первого аргумента скармливаем **указатель на первый элемент массива**, второй и третий - координаты картинки,предпоследние аргументы - размер **массива, не картинки**. Не путать. Последний аргумент определяет откуда читать данные: из памяти МК (атрибут **PROGMEM**) или же из оперативной памяти. Пример:
```c
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "n3310.h"
const byte out[2][24] = {
{0x0, 0x0, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0, 0xc, 0x6, 0x86, 0xc6, 0xec, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x0, 0x0, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0, 0x18, 0x10, 0x10, 0x10, 0x19, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0}
};
int main(void) {
LcdInit();
while (1) {
LcdClear();
LCDIcon(&out[0][0], 0, 0, 2, 24, false);
LcdUpdate();
_delay_ms(5000);
}
}
```
UPD: Только сейчас заметил, что в программе неверно написан тип данных. Вместо **const <span style="text-decoration: underline; color: #993366;">char</span> out** нужно использовать **const <span style="text-decoration: underline; color: #008000;">unsigned char</span> out.** Исходник я давно потерял, поэтому исправить не могу.
**Ссылки:**
[LCDPict](lcdpict.zip)
[Библиотека для дисплея nokia3310](https://github.com/gresolio/N3310Lib)
[Форк библиотеки с программным SPI](https://github.com/MultiMote/N3310Lib)