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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> ATMega16 и АЦП, настройка
mr_onnik
сообщение Nov 6 2007, 20:15
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020



Имеется МК Mega 163, на вход ADC0 (PA0) которого подается изменяющееся напряжение 0...5 В;
AVcc и AREF соединен с Vcc, AGND соединен с GND.

В CodeVisionAVR пишу такой код:
Код
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | 0xff;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSR|=0x40;
// Wait for the AD conversion to complete
while ((ADCSR & 0x10)==0);
ADCSR|=0x10;
return ADCW;
}

//настройки портов

void main(void)
{ int a = 0;

   while(1)
   {
    a = (int)read_adc;
    PORTC.6 = 1;
    delay_ms(a);
    PORTC = 0x00;
    }
}


в результате светодион на шестом выводе порта С постоянно мигает с частотой примерно 0,5с. Наверное, снимается показание с внутреннего источника опорного напряжения, которое составляет примерно половину 5В.

Что неправильно сделано? Как сделать, чтобы частота мигания светодиода менялась в зависимости от подаваемого напряжения на ADC0?
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Nov 6 2007, 21:49
Сообщение #2


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Цитата(mr_onnik @ Nov 6 2007, 23:15) *
Имеется МК Mega 163, на вход ADC0 (PA0) которого подается изменяющееся напряжение 0...5 В;
AVcc и AREF соединен с Vcc, AGND соединен с GND.

Не очень хорошая идея соединять AVcc и AREF с Vcc и AGND с GND. Это разные питания и желательно заботится о хорошем AREF. Просадка питания означает изменение опорного напряжения, а при маломощных источниках питания это бывает часто. Аналогично и с землями. При правильном проектировании плат аналоговую и цифровую земли соединяют в ОДНОЙ точке на плате. посмотрите осциллографом, что бегает по земле и какая пульсация на питании.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
oran-be
сообщение Nov 7 2007, 06:50
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621



А это - так задумано?
Код

ADMUX=adc_input | 0xff;

Согласно даташиту вход АЦП будет всегда подключен к 0. А показания в 0.5 сек - может. стоит проверить, допускает ли функция
delay_ms()
передачу в качестве аргумента 0.
И еще - на Ацпшнике 2.5 В может быть только снаружи. Внутренее проверочное напряжение у него 1.22В

Сообщение отредактировал oran-be - Nov 7 2007, 06:51
Go to the top of the page
 
+Quote Post
mr_onnik
сообщение Nov 7 2007, 08:30
Сообщение #4





Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020



Цитата(oran-be @ Nov 7 2007, 08:50) *
А это - так задумано?
Код

ADMUX=adc_input | 0xff;

На самом деле нет. На сколько я разобрался в мануалах вместо 0xFF нужно указать адрес входа АЦП. А после неудачных попыток решил - пусть проганяет по всем.

mdmitry, источник питания дает 500мА. Сейчас мне не важна точность. Просто для начала собрал простенькую обвязку, чтобы увидеть работу АЦП. Когда увижу, буду повышать точность wink.gif

P.S. Может, эта строка неправильная?
Код
a = (int)read_adc;


Сообщение отредактировал mr_onnik - Nov 7 2007, 08:55
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Nov 7 2007, 09:03
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(mr_onnik @ Nov 7 2007, 03:15) *
a = (int)read_adc;
(int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Nov 7 2007, 09:33
Сообщение #6


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(SergeiCh @ Nov 7 2007, 11:03) *
(int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си.

Ну и почему бы сразу не посоветовать написать правильно?
Код
a = (int)read_adc(0);
Так ли уж необходимы нравоучения?
Go to the top of the page
 
+Quote Post
oran-be
сообщение Nov 7 2007, 10:05
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621



lol.gif lol.gif
Да - кто первый заметит слона?
Go to the top of the page
 
+Quote Post
mr_onnik
сообщение Nov 7 2007, 10:09
Сообщение #8





Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020



Цитата(IgorKossak @ Nov 7 2007, 11:33) *
Ну и почему бы сразу не посоветовать написать правильно?
Код
a = (int)read_adc(0);
Так ли уж необходимы нравоучения?


Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Nov 7 2007, 10:19
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(IgorKossak @ Nov 7 2007, 16:33) *
Так ли уж необходимы нравоучения?
Это совет. Когда написал, тоже подумал, что звучит как нравоучение, но, виноват, все-таки оставил.
Код
unsigned int a = 0;
...
a = read_adc(0);
Не желательно без крайней необходимости приводить типы (в С++ для этого вообще три оператора). Это мое мнение smile.gif
Go to the top of the page
 
+Quote Post
oran-be
сообщение Nov 7 2007, 10:36
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621



Цитата(mr_onnik @ Nov 7 2007, 14:09) *
Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?

Поскольку
Код
ADMUX=adc_input | 0xff;

то мультиплексор подключен к земле и в значении АЦП должен быть 0.
Функция delay_ms(a) поддерживает 0? Проверьте. Засандальте туда 0 втупую и посмотрите.
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Nov 7 2007, 10:48
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(mr_onnik @ Nov 7 2007, 17:09) *
Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?
Странно, что раньше он мигал. Вы выводите в порт 0, вызываете функцию read_adc, пока она выполняется, а выполняется она быстро smile.gif, у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая.
Go to the top of the page
 
+Quote Post
mr_onnik
сообщение Nov 7 2007, 10:55
Сообщение #12





Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020



Цитата(oran-be @ Nov 7 2007, 12:36) *
Поскольку
Код
ADMUX=adc_input | 0xff;

то мультиплексор подключен к земле и в значении АЦП должен быть 0.
Функция delay_ms(a) поддерживает 0? Проверьте. Засандальте туда 0 втупую и посмотрите.


Засандалил. Никаких изменений, пока вообще не убрал строку a = read_adc(0);
Получается, что на ней МК зависает ( Когда убрал ее, при delay_ms(0) светодиод горит, значит, delay работает. Получается, неправильное преобразование.

P.S. А как указать вместо 0xFF адрес ADC0?

Цитата(SergeiCh @ Nov 7 2007, 12:48) *
Странно, что раньше он мигал. Вы выводите в порт 0, вызываете функцию read_adc, пока она выполняется, а выполняется она быстро smile.gif, у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая.


Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Nov 7 2007, 11:44
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(mr_onnik @ Nov 7 2007, 17:55) *
Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?
Беда в том, что время свечения светодиода ровно времени оцифровки сигнала. По документации оно должно быть 13 - 260 мкс, что для человеческого глаза очень мало. Еще нужно настроить прескалер АЦП и разрешить работу АЦП (ADEN в ADCSRA). Ни разу не видел CV, порты и т.п конфигурируются ч/з меню/окошки?
Go to the top of the page
 
+Quote Post
GDI
сообщение Nov 7 2007, 12:22
Сообщение #14


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

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Вот что хорошо в CV, так это мастер нового проекта, он сам и порты настроит если того требуется и АЦП, таймера и прочее сам сконфигурит и разрешит, если надо, то сам сделает вектора прерываний и даже некоторую перифирию может подключить, например символьные ЖКИ, датчики температруры DS18B20, часы DS1307 и 1302 и др., только укажи на каком порту ты их желаешь видеть. Для УАРТа может сам сделать буферизированный прием и/или передачу. Но на этом прелести CV заканчиваются и начинаются суровые глюки, правда в маленьких проектах это не заметно.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
oran-be
сообщение Nov 7 2007, 13:01
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621



Цитата(mr_onnik @ Nov 7 2007, 14:55) *
Засандалил. Никаких изменений, пока вообще не убрал строку a = read_adc(0);
Получается, что на ней МК зависает ( Когда убрал ее, при delay_ms(0) светодиод горит, значит, delay работает. Получается, неправильное преобразование.

P.S. А как указать вместо 0xFF адрес ADC0?

Зависать в функции контролле может только в одном месте - на цикле while. Типовой таракан, если неправильно скофигурировано железо и не высставляется флаг. Проверьте инициализацию АЦП.
З.Ы.
В строке
Код
ADMUX=adc_input | 0xff;

надо убрать операцию | 0xff, после которой, какой бы вы аргумент не передавали в функцию, в ADMUX все равно будет 0xff и мультиплексор будет подключен к земле.
Go to the top of the page
 
+Quote Post

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

 


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


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