Перейти к содержанию
    

Имеется МК 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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

AVcc и AREF соединен с Vcc, AGND соединен с GND.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 
ADMUX=adc_input | 0xff;

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

delay_ms()

передачу в качестве аргумента 0.

И еще - на Ацпшнике 2.5 В может быть только снаружи. Внутренее проверочное напряжение у него 1.22В

Изменено пользователем oran-be

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 
ADMUX=adc_input | 0xff;

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

 

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

 

P.S. Может, эта строка неправильная?

a = (int)read_adc;

Изменено пользователем mr_onnik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

a = (int)read_adc;
(int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

(int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си.

Ну и почему бы сразу не посоветовать написать правильно?

a = (int)read_adc(0);

Так ли уж необходимы нравоучения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну и почему бы сразу не посоветовать написать правильно?
a = (int)read_adc(0);

Так ли уж необходимы нравоучения?

 

Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так ли уж необходимы нравоучения?
Это совет. Когда написал, тоже подумал, что звучит как нравоучение, но, виноват, все-таки оставил.

unsigned int a = 0;
...
a = read_adc(0);

Не желательно без крайней необходимости приводить типы (в С++ для этого вообще три оператора). Это мое мнение :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?

Поскольку

ADMUX=adc_input | 0xff;

то мультиплексор подключен к земле и в значении АЦП должен быть 0.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?
Странно, что раньше он мигал. Вы выводите в порт 0, вызываете функцию read_adc, пока она выполняется, а выполняется она быстро :), у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку

ADMUX=adc_input | 0xff;

то мультиплексор подключен к земле и в значении АЦП должен быть 0.

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

 

Засандалил. Никаких изменений, пока вообще не убрал строку a = read_adc(0);

Получается, что на ней МК зависает ( Когда убрал ее, при delay_ms(0) светодиод горит, значит, delay работает. Получается, неправильное преобразование.

 

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

 

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

 

Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?
Беда в том, что время свечения светодиода ровно времени оцифровки сигнала. По документации оно должно быть 13 - 260 мкс, что для человеческого глаза очень мало. Еще нужно настроить прескалер АЦП и разрешить работу АЦП (ADEN в ADCSRA). Ни разу не видел CV, порты и т.п конфигурируются ч/з меню/окошки?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Засандалил. Никаких изменений, пока вообще не убрал строку a = read_adc(0);

Получается, что на ней МК зависает ( Когда убрал ее, при delay_ms(0) светодиод горит, значит, delay работает. Получается, неправильное преобразование.

 

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

Зависать в функции контролле может только в одном месте - на цикле while. Типовой таракан, если неправильно скофигурировано железо и не высставляется флаг. Проверьте инициализацию АЦП.

З.Ы.

В строке

ADMUX=adc_input | 0xff;

надо убрать операцию | 0xff, после которой, какой бы вы аргумент не передавали в функцию, в ADMUX все равно будет 0xff и мультиплексор будет подключен к земле.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...