Хорошо.
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