Страница 1 из 2

ацп или преобразование в 10 форму

Добавлено: Ср июл 16, 2008 12:53:42
сергей111
Подскажите пожалуйста как после АЦП (AtMega64), полученное значение перевести в 10-ое. Т.е. меняем входное напряжение и в результате должны увидеть это значение на индикаторе (главное получить это значение-а вывести на индикатор я могу).
Исходные данные: величина опорного напряжение - 5В, АЦП 10 разрядный.
Пока никак не получается, читал что нужно сперва умножить на 5, затем разделить полученное число на 10, что-то в этом роде, но у меня никак не получается.
Буду рад если выложите кусок кода и он будет на асме, но можно и на C.
Очень надо.

Добавлено: Ср июл 16, 2008 14:01:30
asd
сергей, тебе надо двоично- двоичнодесятичный преобразователь

Добавлено: Ср июл 16, 2008 14:22:50
ARV
надо всего-навсего прочитать в даташите формулу вычисления реального напряжения по показаниям АЦП...

ADC = (U*1024)/Uref отсюда легко найти U, зная ADC и Uref

Добавлено: Ср июл 16, 2008 14:24:06
сергей111
собственно говоря, цап аппаратный мне не нужен, а именно нужен программный. Двоично-двоично десятичное преобразование у меня есть (нормально работает), но как известно формула ADC=1024Uип/Uref, где Uref=5В. Голова просто уже не соображает.
Как раз затруднение в преобразовании полученного значения, т.е. вычисления по формуле Uип.
Ага умножить на 5 получилось, ADC*5=1024*Uип, теперь осталось разделить на 1024. Уф, пойду подышу свежим воздухом.

Добавлено: Ср июл 16, 2008 16:07:48
Пухич
А в чем проблема то? Сдвинул на 10 вправо, вот тебе и деление на 1024.

Добавлено: Ср июл 16, 2008 16:29:52
сергей111
А в чем проблема то? Сдвинул на 10 вправо, вот тебе и деление на 1024.
---------------------------------------------------------------
Вот это как раз и не получается, у меня есть пробелы в самообразовании, я понимаю, что вроде сложного нет, но не получается. Напишите пожалуйста код.

Добавлено: Ср июл 16, 2008 18:11:41
Aheir
Если Вы о делении, то, видимо вот так:

Код: Выделить всё

A = A >> 10;
В результате переменная А будет поделена на 1024. Ежели пишете на Си, так можно в явном виде арифметические действия писать:

Код: Выделить всё

А = А / 1024;

Добавлено: Чт июл 17, 2008 10:32:06
сергей111
А насколько точный расчет получается? Вот к примеру возьмем Uпит=2500/1024=2,4414...
Если сдвинут вправо 10 раз и убрать лишние 4 бита, т.е. было 0111 0001 0000 0010 стало 0001 0000 0010 это равно 258, т.е. 2,58 если я правильно понимаю. Это что, такая погрешность будет? Или может есть какой-нибудь способ от нее избавиться?

Добавлено: Чт июл 17, 2008 11:39:30
Yellow Tiger
сергей111 писал(а):Как раз затруднение в преобразовании полученного значения, т.е. вычисления по формуле Uип.
Если ресурсов м/к хватит, просто запиши форматированный вывод sprintf() в строковый буфер и выводи эту строку куда потребуется.
А погрешность большая, только если сдвигаемые вправо биты нигде не сохранять и никак не использовать, то есть, при таком раскладе все десять бит канут в лету. Способ избавиться простой - я его уже указал - младшие десять бит не выбрасывать, а выводить как дробную часть результата.

Добавлено: Чт июл 17, 2008 13:14:41
сергей111
Yellow Tiger писал(а):
сергей111 писал(а):Как раз затруднение в преобразовании полученного значения, т.е. вычисления по формуле Uип.
Если ресурсов м/к хватит, просто запиши форматированный вывод sprintf() в строковый буфер и выводи эту строку куда потребуется.
А погрешность большая, только если сдвигаемые вправо биты нигде не сохранять и никак не использовать, то есть, при таком раскладе все десять бит канут в лету. Способ избавиться простой - я его уже указал - младшие десять бит не выбрасывать, а выводить как дробную часть результата.
--------------------------------------------------------
???
Кажется алгоритм я сделал, но время нужно, чтобы его воплотить в ассемблерный код, может у кого есть и кто-нибудь им поделится?
Теперь могу сформулировать задачу немного по-другому: значение напряжения должно быть например 2,14 (или 2,142) - может у кого есть готовая процедура, чтобы свою не писать.

Добавлено: Чт июл 17, 2008 13:20:34
Yellow Tiger
А чем не нравится ассемблерный код на выходе компилятора Си?
Уж как рыбу-то его всяко можно использовать, если такая безраздельная любовь к асму..?

Добавлено: Чт июл 17, 2008 17:40:08
Пухич
сергей111 писал(а):А насколько точный расчет получается? Вот к примеру возьмем Uпит=2500/1024=2,4414...
Если сдвинут вправо 10 раз и убрать лишние 4 бита, т.е. было 0111 0001 0000 0010 стало 0001 0000 0010 это равно 258, т.е. 2,58 если я правильно понимаю. Это что, такая погрешность будет? Или может есть какой-нибудь способ от нее избавиться?
2500 в двоичном виде=1001 1100 0100
если сдвинем это вправо на 10 разрядов то получим 10. Т.е. число 2. При целочисленном делении на 1024 вы получили бы то же самое. Посему разницы нет. Вот если числа дробные, тогда другое дело.

Добавлено: Чт июл 17, 2008 17:55:09
Yellow Tiger
Вопрос сформулирован, мягко говоря, нечетко. Нужно бы определиться, что за задача у Сергея111. Решения могут быть очень разные, а он ограничился лишь парой невнятностей...

Добавлено: Чт июл 17, 2008 20:34:03
ARV
если у вас программа маленькая, а памяти программ достаточно - сделайте массив в памяти из "показаний индикатора" для каждого из 1024 значений АЦП - и не парьтесь с расчетами. т.е. если вы хотите, чтобы при сигнале с АЦП 234 индикатор поазывал 4017 - так и сделайте: в массиве чисел в 234-й элемент вставьте число 4017.

Расчет массива удобно делать в экселе :)

Добавлено: Пт июл 18, 2008 12:55:27
сергей111
Спасибо ARV за интересный совет, только вот не знаю что будет проще и быстрее: написать самому деление вещественного числа (я надеялся что кто-нибудь поделится процедурой, но похоже увы) или же сделать по совету ARV, наверно по времени написания приблизительно равнозначны.

Добавлено: Пт июл 18, 2008 13:49:29
Yellow Tiger
сергей111 писал(а):я надеялся что кто-нибудь поделится процедурой, но похоже увы
Я надеялся, Сергей, на, хотя бы немного, детальное описание задачи, но, похоже, увы. Раз так, по принципу "каков вопрос, таков ответ" - могу только посоветовать поискать на электрониксе, например, вот это может помочь.

Добавлено: Пт июл 18, 2008 15:29:12
сергей111
Yellow Tiger писал(а):
сергей111 писал(а):я надеялся что кто-нибудь поделится процедурой, но похоже увы
Я надеялся, Сергей, на, хотя бы немного, детальное описание задачи, но, похоже, увы. Раз так, по принципу "каков вопрос, таков ответ" - могу только посоветовать поискать на электрониксе, например, вот это может помочь.
Я надеюсь, Yellow Tiger, не очень на меня обиделся. Могу описать более детальное описание:
изменяем подстроечным резистором напряжение от 0 до 5 В
снимаем показание АЦП (АЦП преобразует значение по формуле ADC = (U*1024)/Uref), где Uref-величина опорного напряжения равная 5В.
Затем значение ADC (хранящееся в регистрах ADCH и ADCL) передается по USART на другую плату (плату управления).
На плате управления результат U=(ADC*5)/1024 надо вывести на 7-ый индикатор, точность либо 2 знака (скорее всего) либо 3, после запятой.
Сложность была (а сперва я как поделить вообще не знал) в делении, чтобы учитывались цифры после запятой.
Сейчас я думаю и сам смогу написать процедуру деления вещественных чисел, т.е. учитывая запятую, но полагаю моя процедура будет достаточно не оптимальной, т.к. я пока еще начинающий, а по этой теме думаю есть много наработок.
И еще, программу я делаю на асме, на C думаю перейти попозже, месяца через 1,5-2. Я знаю C, но для микроконтроллера на нем никогда не писал и не пробовал.

Добавлено: Пт июл 18, 2008 16:18:35
Yellow Tiger
Поскольку времени мало, я сделаю пару предположений о том, что не отражено в условии, и на этом основании предложу один из возможных способов.
Итак, предположим, что процедура не д.б. универсальной, но д.б. как можно проще и занимать как можно меньше места в коде, предположим также, что измеряемое напряжение не будет превышать указанной величины, то есть, что завтра не придется мерять до 7 вольт. Отмечу также, что точность в три знака после запятой с этим АЦПом не получится, значит - только 2 знака, ОК?

Вариант с максимальным упрощением такой:
1. использовать внутренний ИОН с напругой 2.56V, а измеряемое напряжение делить ровно пополам. В этом случае цена деления равна 2.56/1024 = 0.0025 (или 0,005 до входного делителя).
2. Измеренное значение ( ( ADCH << 8 ) | ADCL ) сдвигать на 1 бит вправо - теперь цена одного бита равна точнехонько одной сотой вольта (с учетом того, что напруга на входе в два раза меньше измеряемой - делили же пополам!).
3. Полученное после сдвига 16-битное целое (правда, полезных там только 9 бит) преобразовать в ASCII процедурой itoa, взятой с электроникса или еще откуда-то, и передавать её по USART, на ходу вставляя символ десятичной запятой перед последними двумя символами, ведь мы же подогнали цену младшего бита к одной сотой!

Можно еще взять ИОН на 5,12V, тогда не придется делить измеряемое напряжение пополам перед подачей на АЦП.

Это решение не универсальное, но простое и скорострельное, как в реализации, так и в работе.

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

P.S. Я, кстати, всегда полагал, что неспроста у внутреннего атмеловского ИОНа напруга такая "круглая" - 2,56... 0x100, однако! :lol:

Добавлено: Пт июл 18, 2008 18:23:10
ARV
Yellow Tiger писал(а):P.S. Я, кстати, всегда полагал, что неспроста у внутреннего атмеловского ИОНа напруга такая "круглая" - 2,56... 0x100, однако! :lol:
а у тини13 ИОН совсем не такой удачно-округлый...

Добавлено: Пт июл 18, 2008 19:05:33
Yellow Tiger
ARV писал(а):а у тини13 ИОН совсем не такой удачно-округлый...
А кто говорил о тринадцатой тиньке? Мне запомнилось такое начало ветки:
Сергей111 писал(а):Подскажите пожалуйста как после АЦП (AtMega64), ...