Библиотека HT1621B

Пытаюсь портировать библиотеку на ArduinoIDE. ATMEGA328P.
Работает только тестовый режим, (включение всех сегментов) и очистка экрана. При попытке вывести что-то вразумительное - на экране мусор.
В файле Display.cpp при объявлении массива PROGMEM заменил на const, так как намекал компилятор.
В папке Display то, что я пытаюсь превратить в библиотеку.
В папке LCD_Mercury_130K_Zlodey_v20200503 оригинальный проект AVR Studio
https://www.mediafire.com/file/y5qfxbt79d0cbfz/Display.zip/file

#include "Display.h"
#include "Serial_Bus.h"
#include "Strings.h"

void setup() {
 Serial_Bus_Init();
 Display_Init();
  delay (1000);
  Display_Clear();
    Display_Sym(0,SYM_MINUS);
    Display_Sym(1,2);
    Display_Sym(2,3);
    Display_Sym(3,SYM_DEGREE);
    Display_Sym(6,2);
    Display_Sym(7,3);
    Display_Sym(8,SYM_MINUS);
    Display_Sym(9,5);
    Display_Sym(10,9);
    Display_Update();
    delay(2000);
}

void loop() {

}

Ссылка она оригинальную статью и библиотеку автора:


Может кто нибудь помочь довести это до ума?

Это платный заказ? - если да, то стоит перенести в специальный раздел форума.

Если же нет, то необходимо выложить все используемые библиотеки в виде кода непосредственно на форум, заставлять людей скачивать архив файлопомойки трактуется как неуважение к участникам

Если оригинальный проект от того же @Zlodey, что и у нас тут есть, попробуйте к нему напрямую обратиться, типа в личку или ещё как.

Хорошо.
Display.cpp

#include "Display.h"

// Дисплейный буфер
volatile uint8_t Buffer[16];
// Раскладка сегментов
//
//    AAAA   UP
//   F    B
//   F    B
//   F    B
//    GGGG
//   E    C
//   E    C
//   E    C
//    DDDD   DP
//
// Массив для перекодировки цифры/символа в набор сегментов
uint8_t Get_Segments[]=
{
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(0<<SEG_G),  // 0
	(1<<SEG_B)|(0<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(0<<SEG_G),  // 1
	(1<<SEG_A)|(1<<SEG_B)|(0<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(0<<SEG_F)|(1<<SEG_G),  // 2
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(1<<SEG_G),  // 3
	(1<<SEG_B)|(0<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // 4
	(1<<SEG_A)|(0<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // 5
	(1<<SEG_A)|(0<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // 6
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(0<<SEG_G),  // 7
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // 8
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // 9
	(0<<SEG_A)|(0<<SEG_B)|(0<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(0<<SEG_G),  // пробел (код 10)
	(0<<SEG_A)|(0<<SEG_B)|(0<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(1<<SEG_G),  // - (код 11)
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_F)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(1<<SEG_G),  // градус (код 12)
	(1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G),  // A (код 13)
	(0<<SEG_A)|(0<<SEG_B)|(0<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(0<<SEG_F)|(1<<SEG_G),  // c (код 14)
	(0<<SEG_A)|(0<<SEG_B)|(0<<SEG_C)|(0<<SEG_D)|(1<<SEG_E)|(0<<SEG_F)|(1<<SEG_G)   // r (код 15)
};
// Массив, содержащий адреса дисплейного буфера для включения сегментов
// Данные по сегментам слева направо: A,B,C,D,E,F,G,DP,UP
uint8_t Segment_Addr[]=
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00,   // Первое знакоместо
	0x0E, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0D, 0x0D,
	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B,
	0x0B, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0A, 0x0A,
	0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x09, 0x09, 0x08,
	0x08, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07,
	0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x05,
	0x05, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04,
	0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x00,
	0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00    // Последнее знакоместо
};
// Массив, содержащий битовые маски дисплейного буфера для включения сегментов
// Данные по сегментам слева направо: A,B,C,D,E,F,G,DP,UP
uint8_t Segment_Mask[]=
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,   // Первое знакоместо
	0x02, 0x20, 0x10, 0x04, 0x10, 0x20, 0x01, 0x40, 0x04,
	0x20, 0x02, 0x01, 0x40, 0x01, 0x02, 0x10, 0x04, 0x40,
	0x02, 0x20, 0x10, 0x04, 0x10, 0x20, 0x01, 0x40, 0x04,
	0x20, 0x02, 0x01, 0x40, 0x01, 0x02, 0x10, 0x04, 0x40,
	0x02, 0x20, 0x10, 0x04, 0x10, 0x20, 0x01, 0x40, 0x04,
	0x20, 0x02, 0x01, 0x40, 0x01, 0x02, 0x10, 0x04, 0x40,
	0x02, 0x20, 0x10, 0x04, 0x10, 0x20, 0x01, 0x40, 0x04,
	0x20, 0x02, 0x01, 0x40, 0x01, 0x02, 0x10, 0x04, 0x00,
	0x02, 0x20, 0x10, 0x04, 0x10, 0x20, 0x01, 0x40, 0x00,
	0x20, 0x02, 0x01, 0x40, 0x01, 0x02, 0x10, 0x04, 0x00    // Последнее знакоместо
};


// Инициализирует дисплей
void Display_Init (void)
{
	// Источником тактирования дисплея выбран внутренний RC-генератор
	Display_Write_Cmd (CMD_SYS_CLK_RC_256K);
	// Выбор уровня напряжений и схемы коммутации сегментов
	Display_Write_Cmd (CMD_BIAS_1DIV3_COMMONS_3);
	// Включение тактирования дисплея
	Display_Write_Cmd (CMD_SYS_EN);
	// Очистка дисплейного буфера
	Display_Clear();
	// Отправка буфера на дисплей
	Display_Update();
	// Включение генератора напряжения дисплея
	Display_Write_Cmd (CMD_LCD_ON);
}


// Очистка дисплейного буфера
// После использования функции необходимо отправить буфер на дисплей
void Display_Clear (void)
{
	for (uint8_t i = 0; i < sizeof(Buffer); i++) Buffer[i] = 0;
}


// Тестовый режим
// Засвечивает все сегменты
// После использования функции необходимо отправить буфер на дисплей
void Display_Test (void)
{
	for (uint8_t i = 0; i < sizeof(Buffer); i++) Buffer[i] = 0xFF;
}


// Отправляет команду в дисплей
// Cmd - команда (9 бит)
void Display_Write_Cmd (uint16_t Cmd)
{
	// Выбор чипа, начало обмена данными
	Serial_Bus_Chip_Select();
	// Выбор режима 12 бит, старший бит первый
	Serial_Bus_Mode_Set (12, MSB_First);
	// Отправка префикса и команды
	Serial_Bus_Send_Data ((CMD_WRITE << 9) | Cmd);
	// Окончание обмена данными
	Serial_Bus_Chip_DeSelect();
}


// Отправляет 4 бита данных в дисплей
// Эквивалентно записи одного адреса
// Address - адрес от 0 до 31
// Data - данные (4 младших бита)
void Display_Write_Data_Single (uint8_t Address, uint8_t Data)
{
	// Выбор чипа, начало обмена данными
	Serial_Bus_Chip_Select();
	// Выбор режима 9 бит, старший бит первый
	Serial_Bus_Mode_Set (9, MSB_First);
	// Отправка префикса и адреса
	Serial_Bus_Send_Data ((DAT_WRITE << 6) | Address);
	// Выбор режима 4 бита, младший бит первый
	Serial_Bus_Mode_Set (4, LSB_First);
	// Отправка данных
	Serial_Bus_Send_Data (Data);
	// Окончание обмена данными
	Serial_Bus_Chip_DeSelect();
}


// Отправляет 8 бит данных в дисплей
// Эквивалентно записи двух адресов
// Address - адрес от 0 до 15
// Data - данные (8 бит)
void Display_Write_Data_Double (uint8_t Address, uint8_t Data)
{
	// Выбор чипа, начало обмена данными
	Serial_Bus_Chip_Select();
	// Выбор режима 9 бит, старший бит первый
	Serial_Bus_Mode_Set (9, MSB_First);
	// Отправка префикса и адреса
	Serial_Bus_Send_Data ((DAT_WRITE << 6) | (Address * 2));
	// Выбор режима 8 бит, младший бит первый
	Serial_Bus_Mode_Set (8, LSB_First);
	// Отправка данных
	Serial_Bus_Send_Data (Data);
	// Окончание обмена данными
	Serial_Bus_Chip_DeSelect();
}


// Отправляет 16 байт в ОЗУ дисплея
// Data - указатель на массив с данными (16 байт)
void Display_Write_Data_All (uint8_t* Data)
{
	// Выбор чипа, начало обмена данными
	Serial_Bus_Chip_Select();
	// Выбор режима 9 бит, старший бит первый
	Serial_Bus_Mode_Set (9, MSB_First);
	// Отправка префикса и адреса
	Serial_Bus_Send_Data ((DAT_WRITE << 6) | 0);
	// Выбор режима 8 бит, младший бит первый
	Serial_Bus_Mode_Set (8, LSB_First);
	// Отправка данных из буфера на дисплей
	for (uint8_t i = 0; i < 16; i++)
	{
		Serial_Bus_Send_Data (*(Data+i));
	}
	// Окончание обмена данными
	Serial_Bus_Chip_DeSelect();
}


// Отправка буфера на дисплей
void Display_Update (void)
{
	Display_Write_Data_All (Buffer);
}


// Вывод символа в дисплейный буфер
// pos - позиция 0...10
// c - цифра (0...9) либо код символа (10 и более)
// После использования функции необходимо отправить буфер на дисплей
void Display_Sym (uint8_t pos, uint8_t c)
{
	// Защита от выхода за границы буфера
	if (pos >= POS_TOTAL) return;
	// Переменные для хранения адреса, маски, и номера сегмента
	uint8_t Adr;
	uint8_t Msk;
	uint8_t Seg_Offset;
	// Цикл прохода по всем сегментам
	for (Seg_Offset = SEG_A; Seg_Offset <= SEG_G; Seg_Offset++)
	{
		// Отображение цифры или символа
		if (pgm_read_byte(&Get_Segments[c]) & (1 << Seg_Offset))
		{
			// Вычисление адреса и маски
			Adr = pgm_read_byte(&Segment_Addr[(pos * SEG_TOTAL) + Seg_Offset]);
			Msk = pgm_read_byte(&Segment_Mask[(pos * SEG_TOTAL) + Seg_Offset]);
			// Запись в дисплейный буфер
			Buffer[Adr] |= Msk;
		}
	}
}


// Вывод точки в дисплейный буфер
// pos - позиция 0...10
// up - тип точки: нижняя (0) либо верхняя (1)
// После использования функции необходимо отправить буфер на дисплей
void Display_Point (uint8_t pos, uint8_t up)
{
	// Защита от выхода за границы буфера
	if (pos >= POS_TOTAL) return;
	// Переменные для хранения адреса, маски, и номера сегмента
	uint8_t Adr;
	uint8_t Msk;
	uint8_t Seg_Offset;
	// Выбор типа точки - верхняя или нижняя
	if (up) Seg_Offset = SEG_UP; else Seg_Offset = SEG_DP;
	// Вычисление адреса и маски
	Adr = pgm_read_byte(&Segment_Addr[(pos * SEG_TOTAL) + Seg_Offset]);
	Msk = pgm_read_byte(&Segment_Mask[(pos * SEG_TOTAL) + Seg_Offset]);
	// Запись в дисплейный буфер
	Buffer[Adr] |= Msk;
}


// Вывод числа в дисплейный буфер
// Число беззнаковое 32-битное
// pos - позиция 0...10
// После использования функции необходимо отправить буфер на дисплей
void Display_Num (uint8_t pos, uint32_t n)
{
	// Указатель на строку
	char* Stroka;
	// Конвертируем число в строку, нацеливаем указатель на начало строки
	Stroka = utoa (n);
	// Выводим на дисплей
	while (*Stroka != 0)
	{
		// Конвертация и отображение числа
		Display_Sym (pos, (*Stroka) - '0');
		// Перемещаем указатель на следующий символ
		Stroka++;
		// Перемещаем указатель на следующее знакоместо дисплея
		pos++;
	}
}


// Вывод числа в дисплейный буфер
// Число знаковое 32-битное
// pos - позиция 0...10
// После использования функции необходимо отправить буфер на дисплей
void Display_SNum (uint8_t pos, int32_t n)
{
	// Указатель на строку
	char* Stroka;
	// Конвертируем число в строку, нацеливаем указатель на начало строки
	Stroka = itoa (n);
	// Выводим на дисплей
	while (*Stroka != 0)
	{
		// Конвертация и отображение минуса
		if (*Stroka == '-') Display_Sym (pos, SYM_MINUS);
		// Конвертация и отображение числа
		else Display_Sym (pos, (*Stroka) - '0');
		// Перемещаем указатель на следующий символ
		Stroka++;
		// Перемещаем указатель на следующее знакоместо дисплея
		pos++;
	}
}

Display.h

#ifndef DISPLAY_H  // Блокирую повторное включение этого модуля
#define DISPLAY_H

#include "main.h"

// Write data prefix
// 101
#define DAT_WRITE 0x5

// Write command prefix
// 100
#define CMD_WRITE 0x4

// Turn off both system oscillator and LCD bias generator (default)
// 00000000X
#define CMD_SYS_DIS 0x0

// Turn on system oscillator
// 00000001X
#define CMD_SYS_EN 0x2

// Turn off LCD bias generator (default)
// 00000010X
#define CMD_LCD_OFF 0x4

// Turn on LCD bias generator
// 00000011X
#define CMD_LCD_ON 0x6

// Disable time base output
// 00000100X
#define CMD_TIMER_DIS 0x8

// Enable time base output
// 00000110X
#define CMD_TIMER_EN 0xC

// Clear the contents of time base generator
// 000011XXX
#define CMD_TIMER_CLR 0x18

// Enable WDT time-out flag output
// 00000111X
#define CMD_WDT_EN 0xE

// Disable WDT time-out flag output
// 00000101X
#define CMD_WDT_DIS 0xA

// Clear the contents of WDT stage
// 0000111XX
#define CMD_WDT_CLR 0x1C

// Time base/WDT clock output: 1Hz. The WDT time-out flag after: 4s
// 101XX000X
#define CMD_WDT_1_HZ 0x140

// Time base/WDT clock output: 2Hz. The WDT time-out flag after: 2s
// 101XX001X
#define CMD_WDT_2_HZ 0x142

// Time base/WDT clock output: 4Hz. The WDT time-out flag after: 1s
// 101XX010X
#define CMD_WDT_4_HZ 0x144

// Time base/WDT clock output: 8Hz. The WDT time-out flag after: 1/2s
// 101XX011X
#define CMD_WDT_8_HZ 0x146

// Time base/WDT clock output: 16Hz. The WDT time-out flag after: 1/4s
// 101XX100X
#define CMD_WDT_16_HZ 0x148

// Time base/WDT clock output: 32Hz. The WDT time-out flag after: 1/8s
// 101XX101X
#define CMD_WDT_32_HZ 0x14A

// Time base/WDT clock output: 64Hz. The WDT time-out flag after: 1/16s
// 101XX110X
#define CMD_WDT_64_HZ 0x14C

// Time base/WDT clock output: 128Hz. The WDT time-out flag after: 1/32s (default)
// 101XX111X
#define CMD_WDT_128_HZ 0x14E

// Turn off tone outputs (default)
// 00001000X
#define CMD_TONE_OFF 0x10

// Turn on tone outputs
// 00001001X
#define CMD_TONE_ON 0x12

// Tone frequency, 4kHz
// 010XXXXXX
#define CMD_TONE_4K 0x80

// Tone frequency, 2kHz
// 011XXXXXX
#define CMD_TONE_2K 0xC0

// System clock source, crystal oscillator
// 000101XXX
#define CMD_SYS_CLK_XTAL_32K 0x28

// System clock source, on-chip RC oscillator (default)
// 000110XXX
#define CMD_SYS_CLK_RC_256K 0x30

// System clock source, external clock source
// 000111XXX
#define CMD_SYS_CLK_EXT_256K 0x38

// LCD 1/2 bias, 2 commons
// 001000X0X
#define CMD_BIAS_1DIV2_COMMONS_2 0x40

// LCD 1/2 bias, 3 commons
// 001001X0X
#define CMD_BIAS_1DIV2_COMMONS_3 0x48

// LCD 1/2 bias, 4 commons
// 001010X0X
#define CMD_BIAS_1DIV2_COMMONS_4 0x50

// LCD 1/3 bias, 2 commons
// 001000X1X
#define CMD_BIAS_1DIV3_COMMONS_2 0x42

// LCD 1/3 bias, 3 commons
// 001001X1X
#define CMD_BIAS_1DIV3_COMMONS_3 0x4A

// LCD 1/3 bias, 4 commons
// 001010X1X
#define CMD_BIAS_1DIV3_COMMONS_4 0x52

// Disable IRQ output (default)
// 100X0XXXX
#define CMD_IRQ_DIS 0x100

// Enable IRQ output
// 100X1XXXX
#define CMD_IRQ_EN 0x110

// Test mode, user don't use
// 11100000X
#define CMD_TEST_MODE 0x1C0

// Normal mode (default)
// 11100011X
#define CMD_NORMAL_MODE 0x1C6

// Раскладка сегментов
//
//    AAAA   UP
//   F    B
//   F    B
//   F    B
//    GGGG
//   E    C
//   E    C
//   E    C
//    DDDD   DP
//
// Битовые смещения для сегментов
#define SEG_A   0
#define SEG_B   1
#define SEG_C   2
#define SEG_D   3
#define SEG_E   4
#define SEG_F   5
#define SEG_G   6
#define SEG_DP  7
#define SEG_UP  8

// Общее количество сегментов
#define SEG_TOTAL  9

// Общее количество знакомест
#define POS_TOTAL  11

// Коды букв и символов
#define SYM_BLANK	10	// пробел
#define SYM_MINUS	11	// -
#define SYM_DEGREE	12	// градус
#define SYM_A		13	// A
#define SYM_C		14	// c
#define SYM_R		15	// r

// Прототипы функций
void Display_Init (void);
void Display_Clear (void);
void Display_Test (void);
void Display_Write_Cmd (uint16_t Cmd);
void Display_Write_Data_Single (uint8_t Address, uint8_t Data);
void Display_Write_Data_Double (uint8_t Address, uint8_t Data);
void Display_Write_Data_All (uint8_t* Data);
void Display_Update (void);
void Display_Sym (uint8_t pos, uint8_t c);
void Display_Point (uint8_t pos, uint8_t up);
void Display_Num (uint8_t pos, uint32_t n);
void Display_SNum (uint8_t pos, int32_t n);

#endif

Serial_Bus.cpp

#include "Serial_Bus.h"

// Количество бит в посылке
uint8_t Total_Bits = 8;
// Настройка значащего бита
Serial_Bus_Bit_First_t Bit_First = MSB_First;


// Задержка между битами данных
inline static void Serial_Bus_Delay (void)
{
	_delay_us(5);
}


// Настройка портов шины
void Serial_Bus_Init (void)
{
	SERIAL_BUS_DDR |= (1 << SERIAL_BUS_CS) | (1 << SERIAL_BUS_DAT) | (1 << SERIAL_BUS_WR) | (1 << SERIAL_BUS_RD);
	SERIAL_BUS_PORT |= (1 << SERIAL_BUS_CS) | (1 << SERIAL_BUS_DAT) | (1 << SERIAL_BUS_WR) | (1 << SERIAL_BUS_RD);
}


// Выбор режима работы шины
// Можно настроить количество бит (от 1 до 16), а также порядок бит
void Serial_Bus_Mode_Set (uint8_t totalbits, Serial_Bus_Bit_First_t bitfirst)
{
	if ((totalbits == 0) || (totalbits > 16)) return;
	Total_Bits = totalbits;
	Bit_First = bitfirst;
}


// Выбор устройства на шине для обмена данными
void Serial_Bus_Chip_Select (void)
{
	SERIAL_BUS_PORT &= ~(1 << SERIAL_BUS_CS);
	Serial_Bus_Delay();
}


// Завершение обмена данными с устройством
void Serial_Bus_Chip_DeSelect (void)
{
	SERIAL_BUS_PORT |= (1 << SERIAL_BUS_CS);
	Serial_Bus_Delay();
}


// Передача данных
void Serial_Bus_Send_Data (uint16_t Data)
{
	// Маска для выделения одного бита
	uint16_t Mask;
	// Счётчик переданных бит
	uint8_t Bit_Count;
	// Режим "старший бит первый"
	if (Bit_First == MSB_First)
	{
		Mask = (1 << (Total_Bits - 1));
		for (Bit_Count = 0; Bit_Count < Total_Bits; Bit_Count++)
		{
			if (Data & Mask) SERIAL_BUS_PORT |= (1 << SERIAL_BUS_DAT);
			else SERIAL_BUS_PORT &= ~(1 << SERIAL_BUS_DAT);
			Serial_Bus_Delay();
			SERIAL_BUS_PORT &= ~(1 << SERIAL_BUS_WR);
			Serial_Bus_Delay();
			SERIAL_BUS_PORT |= (1 << SERIAL_BUS_WR);
			Serial_Bus_Delay();
			Mask = Mask >> 1;
		}
	}
	// Режим "младший бит первый"
	else
	{
		Mask = 0x0001;
		for (Bit_Count = 0; Bit_Count < Total_Bits; Bit_Count++)
		{
			if (Data & Mask) SERIAL_BUS_PORT |= (1 << SERIAL_BUS_DAT);
			else SERIAL_BUS_PORT &= ~(1 << SERIAL_BUS_DAT);
			Serial_Bus_Delay();
			SERIAL_BUS_PORT &= ~(1 << SERIAL_BUS_WR);
			Serial_Bus_Delay();
			SERIAL_BUS_PORT |= (1 << SERIAL_BUS_WR);
			Serial_Bus_Delay();
			Mask = Mask << 1;
		}
	}
}

Serial_Bus.h

#ifndef SERIAL_BUS_H  // Блокирую повторное включение этого модуля
#define SERIAL_BUS_H

#include "main.h"

// Настройка портов
#define SERIAL_BUS_DDR  DDRD
#define SERIAL_BUS_PORT PORTD
#define SERIAL_BUS_PIN  PIND
#define SERIAL_BUS_CS   2
#define SERIAL_BUS_DAT  4
#define SERIAL_BUS_WR   3
// Если пин чтения не используется, то вписать номер пина записи
#define SERIAL_BUS_RD   5

// Перечисление режимов работы
typedef enum
{
	MSB_First = 1,
	LSB_First = 0
} Serial_Bus_Bit_First_t;

// Прототипы функций
void Serial_Bus_Init (void);
void Serial_Bus_Mode_Set (uint8_t totalbits, Serial_Bus_Bit_First_t bitfirst);
void Serial_Bus_Chip_Select (void);
void Serial_Bus_Chip_DeSelect (void);
void Serial_Bus_Send_Data (uint16_t Data);

#endif

Strings.cpp

#include "Strings.h"

// Буфер для хранения строки
char str_buffer[12];


struct divmod10_t
{
    uint32_t quot;
    uint8_t rem;
};


inline static struct divmod10_t divmodu10 (uint32_t n)
{
    struct divmod10_t res;
    // умножаем на 0.8
    res.quot = n >> 1;
    res.quot += res.quot >> 1;
    res.quot += res.quot >> 4;
    res.quot += res.quot >> 8;
    res.quot += res.quot >> 16;
    uint32_t qq = res.quot;
    // делим на 8
    res.quot >>= 3;
    // вычисляем остаток
    res.rem = (uint8_t)(n - ((res.quot << 1) + (qq & ~7ul)));
    // корректируем остаток и частное
    if(res.rem > 9)
    {
        res.rem -= 10;
        res.quot++;
    }
    return res;
}


// Функция преобразует 32-битное беззнаковое число в строку
// Для работы функции необходим буфер (объявлен в начале файла)
// Минимальное число 0, максимальное число 4294967295
// Размер буфера 11 символов: 10 цифр + символ конца строки
char* utoa (uint32_t value)
{
    char* buffer = str_buffer;
    buffer += 11;
    *--buffer = 0;
    do
    {
        struct divmod10_t res = divmodu10 (value);
        *--buffer = res.rem + '0';
        value = res.quot;
    }
    while (value != 0);
    return buffer;
}


// Функция преобразует 32-битное знаковое число в строку
// Для работы функции необходим буфер (объявлен в начале файла)
// Минимальное число -2147483648, максимальное число 2147483647
// Размер буфера 12 символов: 10 цифр + знак минуса + символ конца строки
char* itoa (int32_t value)
{
    char* buffer = str_buffer;
    uint8_t minus = 0;
    if (value < 0)
    {
        value = -value;
        minus = 1;
    }
    buffer += 12;
    *--buffer = 0;
    do
    {
        struct divmod10_t res = divmodu10 (value);
        *--buffer = res.rem + '0';
        value = res.quot;
    }
    while (value != 0);
    if (minus) *--buffer = '-';
    return buffer;
}

Strings.h

#ifndef STRINGS_H  // Блокирую повторное включение этого модуля
#define STRINGS_H

#include "main.h"

// Прототипы функций
char* utoa (uint32_t value);
char* itoa (int32_t value);

#endif

main.h

#ifndef MAIN_H  // Блокируем повторное включение этого модуля
#define MAIN_H

// Тактовая частота микроконтроллера
#define F_CPU 1000000UL

// Подключение стандартных библиотек
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

// Подключение файлов проекта
#include "types.h"
#include "Strings.h"
#include "Serial_Bus.h"
#include "Display.h"

#endif

Я обращался к нему. Он открещивается от ArduinoIDE как от ладана. А AVR Studio для меня пока слишком сложно.
Дисплей весьма интересный, очень контрастный, качественно сделан. Думаю я не единственный у кого он есть, таких кассовиков в кладовках миллион, для любительских самоделок самое то. Было бы не плохо допилить библиотеку, многим было бы интересно.

А в чем собственно проблема, что не работает?
Код для AVRStudio должен запускаться в Ардуино ИДЕ вообще без правок.
Это вот наоборот совместимости нет

У вас с массивами адресов и маски явно что-то не так. Смотрим первую строку обоих массивов:

Обратите внимание, что у всех сегментов, кроме G - одинаковый адрес и одинаковая маска.

Так не может быть.
В результате при выводе в первое знакоместо таких разных символов, как ‘1’ и ‘0’ - в буфер дисплея отправляется одно и то же.

добавка - обратите внимание что у вас эти массивы выше - обычные в оперативной памяти. А читаете вы их коде, как будто они в ПРОГМЕМ:

Возможно в этом проблема, буду читать как исправить.
В оригинале массив объявлялся так:
PROGMEM uint8_t Get_Segments={…
компилятор же сказал, что так не хочет. я попробовал поменять на const

не вижу никакого const в вашем коде

Но это не снимет проблему с тем, что у вас адреса и маски неправильные странные.
Возможно эти массивы не для вашего дисплея

Кстати. сколько знакомест на дисплее физически? Можете показать фото дисплея в тестовом режиме - то есть когда все сегменты включены?

пробую варианты с const, не получается.
С PROGMEM следующая ошибка:
C:\Users\User\OneDrive\���������\Arduino\libraries\Display\Display.cpp:18:30: error: variable ‘Get_Segments’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’
PROGMEM uint8_t Get_Segments=
^
C:\Users\User\OneDrive\���������\Arduino\libraries\Display\Display.cpp:39:30: error: variable ‘Segment_Addr’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’
PROGMEM uint8_t Segment_Addr=
^
C:\Users\User\OneDrive\���������\Arduino\libraries\Display\Display.cpp:55:30: error: variable ‘Segment_Mask’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’
PROGMEM uint8_t Segment_Mask=
^
exit status 1
Ошибка компиляции для платы ATmega328.

вот в упор не вижу, где вы пробуете const

надо было на

const uint8_t PROGMEM Get_Segments[]={…
2 лайка

Заработало!!!
Спасибо.

а… становится яснее
Первый разряд умеет показывать только “минус” для отрицательных чисел, что обьясняет странные маски в массиве.

Тогда поправьте ПРОГМЕМ и может быть и прокатит.
Признавайтесь, ничего другого не меняли в коде?

Менял дефайны типов переменных
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

ну и отлично.

Обращайте внимание в коде, что в левую позицию можно вывести только “минус”, а цифры надо выводить начиная со второго знакоместа.

С подсказки v258 оно заработало . Сейчас буду разбираться корректно ли.

Да да.

а что там может быть некорректно, если цифры верные :slight_smile: Будете проверять, чтобы “2” с “5” не перепутать? :slight_smile: