---
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)