реклама на сайте
подробности

 
 
> Дробная арифметика, Делаю вольтметр
Skaf
сообщение Aug 7 2009, 17:59
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 228
Регистрация: 4-06-09
Пользователь №: 49 940



Делаю цифровой вольтметр на AVR ATmega16. Пишу на Си (WinAVR).

После аналого-цифрового преобразования у меня есть переменная

int ADCD с 10-и битным результатом. Мне надо показать число на экране.

Сначала хочу перевести в вольты.

float data = ADCD * 0.0049;

где 0.0049 получилось от 5 / 1024

Потом надо отобразить на индикаторе. У меня есть функция, которая принимает на вход номер знакоместа на LCD и цифру от 0 до 9.

Пытаюсь отобразить целую часть

DrawLCD((int)data, 1);

А на экране получаю 0. Какой-то косяк с умножением на 0.0049 видимо... Подскажите пожалуйста как решить проблему?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 10)
Vishv
сообщение Aug 7 2009, 18:04
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 310
Регистрация: 11-07-09
Из: Екатеринбург
Пользователь №: 51 154



По моему Вы перемудрили. Я обычно делаю такие операции в целочисленной арифметике - чуть сложнее писать, зато гарантировано, да и выполняется не в пример быстрее.
Go to the top of the page
 
+Quote Post
Skaf
сообщение Aug 7 2009, 18:08
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 228
Регистрация: 4-06-09
Пользователь №: 49 940



Напишите пожалуйста, как вы делаете.
Go to the top of the page
 
+Quote Post
Herz
сообщение Aug 7 2009, 18:46
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Если нужно более-менее точно, то источник опорного напряжения для АЦП нужно взять стабильный, желательно готовый на напряжение, например, 4.096В. Будет удобно. А так можно для простоты результат умножить на 5, затем последовательно делить: на 1000 - получим первую цифру (вольты), остаток - на 100 (десятые доли вольт), остаток - на 10 (десятки милливольт), и остаток - милливольты.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 7 2009, 18:51
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Skaf @ Aug 7 2009, 23:59) *
Потом надо отобразить на индикаторе. У меня есть функция, которая принимает на вход номер знакоместа на LCD и цифру от 0 до 9.

Пытаюсь отобразить целую часть

DrawLCD((int)data, 1);

А на экране получаю 0. Какой-то косяк с умножением на 0.0049 видимо... Подскажите пожалуйста как решить проблему?


Наверное цифра - это '0', '1', '2'...'9'? Тогда надо

DrawLCD((int)data + '0', 1);

ЗЫ. Ну и, на всякий случай - на входе АЦП больше вольта? smile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Vishv
сообщение Aug 7 2009, 18:52
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 310
Регистрация: 11-07-09
Из: Екатеринбург
Пользователь №: 51 154



Если я правильно догадался у вас опорное напряжение 5 В.
В этом случае:
Код
int16_t raschet(void)
{
int16_t b_uff;//выходное значение в милливольтах

    b_uff=((int32_t)ADCD*5000)/1024;
    return b_uff;
}
Ну и далее:
uint8_t mas_ADC [4];//содержит цифры для вывода
void out (int16_t in)
{
uint16_t d;
    d=in&0x7fff;

    mas_ADC[0]=d/1000+0x30;
    d=d%1000;
    mas_ADC[1]=d/100+0x30;
    d=d%100;    
    mas_ADC[2]=d/10+0x30;
    mas_ADC[3]=d%10;
}
Причина редактирования: Оформление цитаты исходника.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 7 2009, 20:36
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Топикстартеру. Как уже выше заметили для вашего случая плавающая арифметика не нужна совсем. Разрешение вашего АЦП хуже 1мВ, поэтому результат измерения можно представлять именно в миллиВольтах с помощью двухбайтового целого числа. Причем деление на 1024 заменяется сдвигом вправо на 10 бит.
Код
unsigned int data = (unsigned int)((unsigned long)ADCD*5000UL)>>10UL); //содержимое data - напряжение в мВ: число от 0мВ до 4995мВ

По второй части вопроса.
Цитата
Потом надо отобразить на индикаторе. У меня есть функция, которая принимает на вход номер знакоместа на LCD и цифру от 0 до 9.
Цифра от 0 до 9 в бинарном виде принимается или в виде ASCII-кода? Если в виде ASCII-кода, то нужно к каждому числу результата BCD-преобразования добавлять ASCII-код нуля '0' = 0x30. Для преобразования в BCD-формат делением (или боже вас упаси! функцией sprintf) пользоваться вовсе не обязательно. Можно последовательно вычитать степени числа десять (т.е. 10000, 1000, 100, 10), считая количество этих вычитаний.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 7 2009, 22:32
Сообщение #8


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Осталось только объяснить, откуда вдруг взялось BCD smile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
xgcyo
сообщение Aug 12 2009, 10:31
Сообщение #9





Группа: Участник
Сообщений: 8
Регистрация: 9-07-09
Из: Рига, Латвия
Пользователь №: 51 080



Флоатами получается очень медленно и громоздко. Для своего вольтметра все делал делением и вычислением остатка на интегерах. Вывод на три 7-сегментных светодиодных индикатора. Могу сурсы дать.
Существует какой-либо быстрый алгоритм разложения 16-битного целого на десятичные составляющие, с шифтами например? На аттини26 делением и остатками при 1МГц у меня эта операция занимает 200мкс. Интересно, подсчетом вычитаний 1000, 100, 10 быстрей будет?
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Aug 12 2009, 11:23
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



в BCD можно конверировать или разложением на степени 10 (отнимать 10000, 1000, 100, 10, 1 и считать количество) или сдвигами+BCD коррекцией :
http://www.avr-asm-tutorial.net/avr_en/calc/CONVERSION.html
http://www.avr-asm-tutorial.net/avr_en/cal...RT.html#bin2bcd
http://www.msclub.ce.cctpu.edu.ru/MCU_MPU/AVR/BINBCD.htm
http://www.msclub.ce.cctpu.edu.ru/MCU_MPU/AVR/BINBCDapp1.htm
http://www.msclub.ce.cctpu.edu.ru/MCU_MPU/AVR/BINBCDapp3.htm
Что будет быстрее - зависит от конвертируемых чисел.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Aug 12 2009, 11:32
Сообщение #11


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
в BCD можно конверировать или разложением на степени 10 (отнимать 10000, 1000, 100, 10, 1 и считать количество) или сдвигами+BCD коррекцией :


Или приведением числа 0000...9999 к формату 0...1 с фиксированной точкой (в 16 бит укладывается дробная часть, а целая равна 0) и домножением на 10 для получения очередной цифры. При наличии аппаратного умножителя так вообще пожалуй наибыстрейший способ.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 00:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01583 секунд с 7
ELECTRONIX ©2004-2016