Библиотека для перевода двоичных чисел в двоично-десятичные числа и символы

23/06/2013 - 13:26 Павел Бобков

Введение

Иногда при программировании микроконтроллеров требуется выводить на дисплей или терминал какие-то числовые данные. Это могут быть показания АЦП, значение внутренних часов, коды ошибок, состояния автомата и т.п. Процедура вывода числа состоит из следующих шагов, нужно преобразовать двоичное число в двоично-десятичное, перевести двоично-десятичное число в символьное представление и после этого передать полученный результат какой-то функции вывода. Для выполнения этой задачи я написал небольшую библиотеку.

Особенности

- работает с любыми микроконтроллерами и компиляторами,
- быстрый алгоритм без использования операции деления,
- работает с 8, 16 и 32 разрядными двоичными числами,
- есть функции для работы с десятичными числами заданной разрядности,
- может сохранять результат преобразования в виде строки в буфере,
- если определена внешняя функция вывода, может сразу передавать результат ей.

Подключение к проекту

1. Переписываем файлы bcd.h и bcd.c в папку проекта.
2. Подключаем bcd.c к проекту внутри среды разработки.
3. Инклюдим заголовочный файл bcd.h к сишному файлу, в котором будут использоваться функции преобразования.
4. Настраиваем конфигурацию в заголовочном файле bcd.h.
5. Прописываем в код вызов функций библиотеки.

Настройка конфигурации

Настройка конфигурации включает в себя следующие шаги.

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


//подключаю библиотеку для вывода на lcd
#include "lcd_lib.h"

2. Переопределение функции вывода. Если этот функционал не используется макрос нужно оставить пустым.


//вывод не используется оставляем макрос пустым
#define BCD_SendData(data)

//вывод используется, переопределяем функцию
#define BCD_SendData(data) LCD_WriteData(data)

3. Отображение нуля в старших разрядах. Если закомментировать настройку ноль выводиться не будет, вместо него будет сохраняться символ пробела. Если оставить, ноль будет отображаться.


//при такой настройке BCD_Uchar(3) отобразит на экране 003
#define MIRROR_NULL

//если закомментировать BCD_Uchar(3) отобразит на экране 3
//#define MIRROR_NULL

4. Использование буфера.
В зависимости от настроек библиотеки, функции преобразования чисел могут сохранять результат в буфере в виде строки, которую потом можно передать какой-нибудь функции вывода. Если эту настройку закомментировать, то запись в буфер производиться не будет.


#define BCD_BUF_USE

5. Требуемый конечный результат. Библиотека позволяет переводить двоичные числа в двоично-десятичный вид или в символьный. Если данная настройка закомментирована используется двоично-десятичное представление, если нет, то символьное.


#define BCD_SYM

Описание функций

Общие функции для преобразования 8, 16 и 32 разрядных двоичных чисел. 

void BCD_Uchar(uint8_t value) - преобразует числа от 0 до 255
void BCD_Uint(uint16_t value) - преобразует числа от 0 до 65535 
void BCD_Ulong(uint32_t value) - преобразует числа от 0 до 4294967295

Пример


#define F_CPU 9600000UL
...
uint8_t count = 120;
uint16_t adc_value = 1020;
...
BCD_Uchar(count);
BCD_Uint(adc_value);
BCD_Ulong(F_CPU);

Функции для преобразования десятичных чисел заданной разрядности.

void BCD_1(uint8_t value) - преобразует числа от 0 до 9
void BCD_2(uint8_t value) - преобразует числа от 0 до 99
void BCD_3(uint8_t value) - преобразует числа от 0 до 255
void BCD_3Int(uint16_t value) - преобразует числа от 0 до 999
void BCD_4Int(uint16_t value) - преобразует числа от 0 до 9999
void BCD_5Int(uint16_t value) - преобразует числа от 0 до 65535

Пример


#define DATA 23
...
//переменная которая всегда < 10
uint8_t index = 0;

//счетчик до 999
uint8_t count;
...
BCD_1(index);
BCD_2(DATA);
BCD_3Int(count);

//а это неправильно
BCD_1(DATA);
BCD_3(count);

Функция для получения указателя на буфер, в котором сохраняется результат. Если буфер не используется, функция возвращает нулевой указатель.

uint8_t* BCD_GetPointerBuf(void);

Пример

//определяем переменную указатель на буфер
uint8_t* pBuf;

//инициализируем эту переменную 
pBuf = BCD_GetPointerBuf();

//преобразуем число, а затем выводим строку на экран
BCD_3Int(counter);
LCD_SendStr(pBuf);

Файлы

bcd.rar - библиотека для перевода двоичных чисел в двоично-десятичные и символы

Комментарии   

# Pashgan 13.07.2013 07:28
Пожалуйста. Надеюсь кому-нибудь пригодится.
Ответить | Ответить с цитатой | Цитировать
# Дмитри 20.11.2013 06:34
Pashgan привет. Спасибо за библиотеку, вчера ее применил в одном проекте. Достойный сайт, на котором много полезной и нужной информации. Ты молодец, так держать. Рассматривал твой код, видно что все хорошо продуманно и видно что есть хороший опыт в программировани и.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 21.11.2013 09:40
Пожалуйста. Опыта у меня меньше, чем хотелось бы.
Ответить | Ответить с цитатой | Цитировать
# Dim 25.12.2013 17:21
не могли бы подробнее рассказать как реализовывается функция "Отображение нуля в старших разрядах" в этой библиотеке, а то не слишком разобрался, хотелось бы перенять немного опыта)
и еще как выводить отрицательные значения?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 27.12.2013 05:22
Если выясняется, что разряд имеет нулевое значение, то ему присваивается символ нуля. В зависимости от настройки #define MIRROR_NULL, это может быть или действительно символ нуля или пустой символ.

Вывод отрицательных чисел там не предусмотрен.
Ответить | Ответить с цитатой | Цитировать
# Dim 28.12.2013 14:56
я имел ввиду на уровне языка Си =)
вроде разобрался
надо еще библиотеку для отрицательных чисел накромсать
Ответить | Ответить с цитатой | Цитировать
# XanderEVG 27.01.2014 09:29
Хотелось бы увидеть сравнение скорости и обьема с itoa и другими вариантами.
хотя бы типовых значений(не рассматривая худший лучший варианты)
Ответить | Ответить с цитатой | Цитировать
# Pashgan 28.01.2014 11:46
Нет времени этим заниматься. Я пробовал три алгоритма - вычитание, деление с остатком и что-то среднее. Для AVR наилучший результат получился в первом случае.
Ответить | Ответить с цитатой | Цитировать
# demiurg 21.04.2014 16:23
Без обид. Искал на си преобразование чисел. Я недавно с асма слез, там-то с преобразованием нет проблем. Наткнулся на твою статью. Поплевался, но работает. Мне проект один нужно было сдать. Потом я наткнулся на другую статью. На основании тех примеров сделал под себя. [url=http://we. easyelectronics .ru/demiurg1978 /preobrazovanie -bezznakovogo-c elogo-chisla-v- stroku-i-obratn o-pervyy-opyt.h tmlссылка
Ответить | Ответить с цитатой | Цитировать
# Pashgan 21.04.2014 17:41
Нет, я пожалуй обижусь.
Ответить | Ответить с цитатой | Цитировать
# demiurg 22.04.2014 10:49
Pashgan, на что обижаться?! Если мы заходим на твой сайт и порой находим ответы на свои вопросы, то, что ищем в сети. Все просто. Я нашел твой пример. Как-то, но работает. Нашел еще лучше вариант. И по тактам и по размеру. Поделился. Так на что обижаться? :)
Ответить | Ответить с цитатой | Цитировать
# Pashgan 22.04.2014 11:22
Шутка это..
Ответить | Ответить с цитатой | Цитировать
# Anderer 27.10.2014 22:43
Доброго времени.
Большое спасибо за эту библиотеку и за все остальные тоже :)
Немного дурацкий вопрос: сюда можно символ запятой прикрутить?
Хотел попробовать перекинуть из старой версии библиотеки, но не получилось разобраться :(
Ответить | Ответить с цитатой | Цитировать
# Mickie 23.07.2015 23:26
Доброго времени суток.
Подскажите че не так... решил прикрутить bcd в нагрузку к lcd_lib . Строки выводятся нормально а вот переменную... как-то не очень. Ошибочки лезут. Вот кусок кода:
Код:
...
#include "lcd_lib.c"
#include <stdint.h>
#include "bcd.h"

int main(void)
{
LCD_Init();
while(1)
{
LCD_Goto(0, 0);
LCD_SendString(" 1 string ");
LCD_Goto(0, 1);
LCD_SendString(" 2 string ");
LCD_Goto(0, 2);
LCD_SendString("3 Third string");
for ( uint8_t count = 10; k; --k)
{
LCD_Goto(6, 3);
uint8_t* pBuf =BCD_GetPointerBuf();
BCD_3(count);
LCD_SendString(pBuf);
_delay_ms(200);
}
}
}

ошибки вот такие:
invalid conversion from uint8_t* {aka unsigned char*} to char*

initializing argument 1 of void LCD_SendString(char*)

Вот, собственно, никак не догоню ... помогите.
Atmel Studio 6.2
Ответить | Ответить с цитатой | Цитировать
# Mickie 25.07.2015 21:41
Pashgan, помогите пожалуйста, делал по примеру выше. Уж больно не хочется использовать printf ... тяжёлый он сильно.
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий

Защитный код
Обновить