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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Вывод на ЖКИ значения напряжения
andrei89
сообщение Oct 1 2010, 13:03
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



АЦП встроенный в контроллер (ADuC812) оцифровывает аналоговый сигнал, в результате имеем два регистра с результатом оцифровки - ADCDATAH и ADCDATAL. Каким образом можно преобразовать значения в этих регистрах в напряжение и выдать на дисплей? Функция вывода на дисплей строки работает. Если можно то примером кода, пожалуйста. Заранее спасибо.

Сообщение отредактировал andrei89 - Oct 1 2010, 13:03
Go to the top of the page
 
+Quote Post
Savrik
сообщение Oct 1 2010, 14:13
Сообщение #2


наблюдаю..
***

Группа: Свой
Сообщений: 291
Регистрация: 11-12-06
Из: Украина
Пользователь №: 23 369



(знач_АЦП*опорное_напр)\разрядность_АЦП
Что за дисплей, контроллер? Телепаты в отпуске...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 1 2010, 14:28
Сообщение #3


Гуру
******

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



Код
unsigned int ADCresult;
ADCresult=ADCDATAH<<8;
ADCresult+=ADCDATAL;

Ну или наоборот в зависимости от требуемого порядка чтения регистров
Код
unsigned int ADCresult;
ADCresult=ADCDATAL;
ADCresult+=ADCDATAH<<8;


Затем вычисление напряжения
Код
unsigned int Voltage;
Voltage=(ADCresult*2500U)>>12;

Результат получается в миллиВольтах.
Go to the top of the page
 
+Quote Post
andrei89
сообщение Oct 1 2010, 14:32
Сообщение #4





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



Контроллер ADuC812, дисплей МТ16s2d (на контроллере HD77480). Собственно я так и делаю, но только почему то на дисплее значения постоянно прыгают. АЦП выполняет однократное преобразование, опорное напряжение 2.5 В, разрядность АЦП - 12.

Вот функция обработки прерывания от АЦП:



void display_voltage(void) interrupt 6 {

unsigned char lcd_buffer[6];
float ADCValue;
ADCValue = ((ADCDATAL + (ADCDATAH&0x0F))<<8);
ADCValue=ADCValue*2500/4096;
ADCValue=ADCValue/1000;
sprintf (lcd_buffer,"U=%1.3f V", ADCValue);
send_lcd(set_first_line, lcd_buffer);
}
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 1 2010, 14:44
Сообщение #5


Гуру
******

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



А float-то зачем тут? blink.gif
Какой сигнал измеряете? Паузы >=300мс между выводом значений на индикатор делаете?
Go to the top of the page
 
+Quote Post
andrei89
сообщение Oct 2 2010, 07:18
Сообщение #6





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



Ну значение с плавающей точкой же должно быть? Паузы не делаю так как значение выводится только один раз. Измеряю постоянный сигнал с батарейки ~1.5В.
Go to the top of the page
 
+Quote Post
Herz
сообщение Oct 2 2010, 14:26
Сообщение #7


Гуру
******

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



Цитата(andrei89 @ Oct 2 2010, 09:18) *
Ну значение с плавающей точкой же должно быть? Паузы не делаю так как значение выводится только один раз. Измеряю постоянный сигнал с батарейки ~1.5В.

Подсказка: точку поставите на индикаторе, не в переменной.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 2 2010, 19:33
Сообщение #8


Гуру
******

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



Цитата(andrei89 @ Oct 2 2010, 13:18) *
Ну значение с плавающей точкой же должно быть?
Это ко мне вопрос? Откуда я знаю, в каком формате вам нужно выводить laughing.gif Я бы на вашем месте избавился от вычислений во float по двум причинам. 1) Для вычислений float линкуется отдельная библиотека, которая занимает доп. объем Flash. 2) Для работы printf с числами float требуется до 1,5кБайт стековой памяти (ОЗУ). Следует это учитывать, чтобы не напороться на ошибки, связанные с наползанием стека на сегмент статических данных, - ошибки частые и очень трудно вылавливаемые. Для вывода значения напряжения в Вольтах, вам достаточно разделить число на целую и дробную часть, между которыми выводить символ точки. То бишь, например, для вывода числа в виде 1,798В, которое у вас имеется как 1798мВ, выводите
- значение целочисленного деления 1798/1000,
- символ ","
- остаток 1798-1798/1000*1000.
на экране получите то же самое, как и при выводе float-овского числа. Только все это будет быстрее и экономнее по размеру памяти.
Цитата(andrei89 @ Oct 2 2010, 13:18) *
Паузы не делаю так как значение выводится только один раз. Измеряю постоянный сигнал с батарейки ~1.5В.
Если напряжение на входе постоянное и выводите один раз, то что за "прыгающие значения"?
Go to the top of the page
 
+Quote Post
andrei89
сообщение Oct 4 2010, 09:55
Сообщение #9





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



Ну если смотреть после ресета, то напряжение постоянно скачет. Из - за чего не могу понять. Если выводить вот такую строку sprintf (lcd_buffer,"U=%u V", ADCDATAL), то значение этого регистра постоянно меняется, выводятся числа типа -16896, 18176, 12800. Абракадабра короче говоря.

Переделал в int, дробную часть пока не вывожу. Он сейчас должен хотя бы 1В показывать, а показывает 0. Отчего это может быть? Где тут ошибка?

void display_voltage(void) interrupt 6 {

unsigned char lcd_buffer[6];
int ADCValue;
ADCValue = ((ADCDATAL + (ADCDATAH&0x0F))<<8);
ADCValue=ADCValue*2500/4096;
ADCValue=(ADCValue/1000);
sprintf (lcd_buffer,"U=%i V", ADCValue);
send_lcd(set_first_line, lcd_buffer);
}
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 4 2010, 14:14
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(andrei89 @ Oct 4 2010, 13:55) *
Где тут ошибка?
Вот тут
Цитата(andrei89 @ Oct 4 2010, 13:55) *
ADCValue=ADCValue*2500/4096;
После умножения 16-ти разрядов не всегда достаточно для представления результата. Нужно записать, например, так:
ADCValue= (long)ADCValue*2500/4096;
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 4 2010, 14:46
Сообщение #11


Гуру
******

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



Цитата(Палыч @ Oct 4 2010, 20:14) *
После умножения 16-ти разрядов не всегда достаточно для представления результата. Нужно записать, например, так:
ADCValue= (long)ADCValue*2500/4096;


Кстати, да. Я вот тоже недописал тип константы в примере, надо было хотя бы вот так Voltage=(ADCresult*2500UL)>>12; Или явно к типу long привести.
Go to the top of the page
 
+Quote Post
andrei89
сообщение Oct 4 2010, 14:48
Сообщение #12





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



Все равно выводит только 0. Может еще можно каким нибудь другим способом преобразовать значения регистров в напряжение?

А почему 16 разрядов? МК 8ми разрядный же.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 4 2010, 14:54
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(andrei89 @ Oct 4 2010, 18:48) *
Все равно выводит только 0. Может еще можно каким нибудь другим способом преобразовать значения регистров в напряжение?
Попробуйте выводить значение регистра ADCDATA (ADCValue до его преобразования в милливольты). Какое значение выводиться?
Цитата(andrei89 @ Oct 4 2010, 18:48) *
А почему 16 разрядов? МК 8ми разрядный же.
Для int отводится два байта - 16 бит.
Go to the top of the page
 
+Quote Post
andrei89
сообщение Oct 4 2010, 14:56
Сообщение #14





Группа: Участник
Сообщений: 12
Регистрация: 1-10-10
Пользователь №: 59 865



Сейчас начал цифры показывать вместо нуля, но неверные - то 25, то 15, то 10, то 5.

Сейчас код такой:

void display_voltage(void) interrupt 6 {

unsigned int ADCValue;
unsigned char lcd_buffer[6];
ADCValue = (ADCDATAL + (ADCDATAH&0x0F))<<12;
ADCValue=(long)(ADCValue*2500UL/4096);
ADCValue=(ADCValue/1000);
sprintf (lcd_buffer,"U=%i V", ADCValue);
send_lcd(set_first_line, lcd_buffer);
}
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 4 2010, 15:01
Сообщение #15


Гуру
******

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



Цитата(andrei89 @ Oct 4 2010, 20:56) *
ADCValue = (ADCDATAL + (ADCDATAH&0x0F))<<12;
Почему <<12? Должно быть <<8 . Причем скобки не там стоят.
Код
ADCValue = ADCDATAL + (ADCDATAH&0x0F)<<8;

Цитата(andrei89 @ Oct 4 2010, 20:56) *
ADCValue=(long)(ADCValue*2500UL/4096);

Скобки не там расставлены.
Должно быть
Код
ADCValue=((long)ADCValue*2500UL)>>12;
Go to the top of the page
 
+Quote Post

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

 


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


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