mr_onnik 0 6 ноября, 2007 Опубликовано 6 ноября, 2007 · Жалоба Имеется МК 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? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mdmitry 0 6 ноября, 2007 Опубликовано 6 ноября, 2007 · Жалоба Имеется МК Mega 163, на вход ADC0 (PA0) которого подается изменяющееся напряжение 0...5 В; AVcc и AREF соединен с Vcc, AGND соединен с GND. Не очень хорошая идея соединять AVcc и AREF с Vcc и AGND с GND. Это разные питания и желательно заботится о хорошем AREF. Просадка питания означает изменение опорного напряжения, а при маломощных источниках питания это бывает часто. Аналогично и с землями. При правильном проектировании плат аналоговую и цифровую земли соединяют в ОДНОЙ точке на плате. посмотрите осциллографом, что бегает по земле и какая пульсация на питании. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 (изменено) · Жалоба А это - так задумано? ADMUX=adc_input | 0xff; Согласно даташиту вход АЦП будет всегда подключен к 0. А показания в 0.5 сек - может. стоит проверить, допускает ли функция delay_ms() передачу в качестве аргумента 0. И еще - на Ацпшнике 2.5 В может быть только снаружи. Внутренее проверочное напряжение у него 1.22В Изменено 7 ноября, 2007 пользователем oran-be Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mr_onnik 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 (изменено) · Жалоба А это - так задумано? ADMUX=adc_input | 0xff; На самом деле нет. На сколько я разобрался в мануалах вместо 0xFF нужно указать адрес входа АЦП. А после неудачных попыток решил - пусть проганяет по всем. mdmitry, источник питания дает 500мА. Сейчас мне не важна точность. Просто для начала собрал простенькую обвязку, чтобы увидеть работу АЦП. Когда увижу, буду повышать точность ;) P.S. Может, эта строка неправильная? a = (int)read_adc; Изменено 7 ноября, 2007 пользователем mr_onnik Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeiCh 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба a = (int)read_adc;(int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба (int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си. Ну и почему бы сразу не посоветовать написать правильно? a = (int)read_adc(0); Так ли уж необходимы нравоучения? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Да - кто первый заметит слона? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mr_onnik 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Ну и почему бы сразу не посоветовать написать правильно?a = (int)read_adc(0); Так ли уж необходимы нравоучения? Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeiCh 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Так ли уж необходимы нравоучения?Это совет. Когда написал, тоже подумал, что звучит как нравоучение, но, виноват, все-таки оставил. unsigned int a = 0; ... a = read_adc(0); Не желательно без крайней необходимости приводить типы (в С++ для этого вообще три оператора). Это мое мнение :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность? Поскольку ADMUX=adc_input | 0xff; то мультиплексор подключен к земле и в значении АЦП должен быть 0. Функция delay_ms(a) поддерживает 0? Проверьте. Засандальте туда 0 втупую и посмотрите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeiCh 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность? Странно, что раньше он мигал. Вы выводите в порт 0, вызываете функцию read_adc, пока она выполняется, а выполняется она быстро :), у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mr_onnik 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Поскольку 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с. Ведь, пока не будет выдержана пауза, АЦП не работает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeiCh 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?Беда в том, что время свечения светодиода ровно времени оцифровки сигнала. По документации оно должно быть 13 - 260 мкс, что для человеческого глаза очень мало. Еще нужно настроить прескалер АЦП и разрешить работу АЦП (ADEN в ADCSRA). Ни разу не видел CV, порты и т.п конфигурируются ч/з меню/окошки? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Вот что хорошо в CV, так это мастер нового проекта, он сам и порты настроит если того требуется и АЦП, таймера и прочее сам сконфигурит и разрешит, если надо, то сам сделает вектора прерываний и даже некоторую перифирию может подключить, например символьные ЖКИ, датчики температруры DS18B20, часы DS1307 и 1302 и др., только укажи на каком порту ты их желаешь видеть. Для УАРТа может сам сделать буферизированный прием и/или передачу. Но на этом прелести CV заканчиваются и начинаются суровые глюки, правда в маленьких проектах это не заметно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 7 ноября, 2007 Опубликовано 7 ноября, 2007 · Жалоба Засандалил. Никаких изменений, пока вообще не убрал строку a = read_adc(0); Получается, что на ней МК зависает ( Когда убрал ее, при delay_ms(0) светодиод горит, значит, delay работает. Получается, неправильное преобразование. P.S. А как указать вместо 0xFF адрес ADC0? Зависать в функции контролле может только в одном месте - на цикле while. Типовой таракан, если неправильно скофигурировано железо и не высставляется флаг. Проверьте инициализацию АЦП. З.Ы. В строке ADMUX=adc_input | 0xff; надо убрать операцию | 0xff, после которой, какой бы вы аргумент не передавали в функцию, в ADMUX все равно будет 0xff и мультиплексор будет подключен к земле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться