|
ATMega16 и АЦП, настройка |
|
|
|
Nov 6 2007, 20:15
|
Группа: Новичок
Сообщений: 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?
|
|
|
|
|
Nov 7 2007, 06:50
|
Местный
  
Группа: Свой
Сообщений: 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
|
|
|
|
|
Nov 7 2007, 08:30
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020

|
Цитата(oran-be @ Nov 7 2007, 08:50)  А это - так задумано? Код ADMUX=adc_input | 0xff; На самом деле нет. На сколько я разобрался в мануалах вместо 0xFF нужно указать адрес входа АЦП. А после неудачных попыток решил - пусть проганяет по всем. mdmitry, источник питания дает 500мА. Сейчас мне не важна точность. Просто для начала собрал простенькую обвязку, чтобы увидеть работу АЦП. Когда увижу, буду повышать точность  P.S. Может, эта строка неправильная? Код a = (int)read_adc;
Сообщение отредактировал mr_onnik - Nov 7 2007, 08:55
|
|
|
|
|
Nov 7 2007, 09:03
|
Частый гость
 
Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415

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

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

|
Цитата(SergeiCh @ Nov 7 2007, 11:03)  (int)read_adc; - это адрес функции (точка входа в функцию), приведенный к целому типу, а не вызов функции. Почитайте какую-нибудь книжку по Си. Ну и почему бы сразу не посоветовать написать правильно? Код a = (int)read_adc(0); Так ли уж необходимы нравоучения?
|
|
|
|
|
Nov 7 2007, 10:09
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020

|
Цитата(IgorKossak @ Nov 7 2007, 11:33)  Ну и почему бы сразу не посоветовать написать правильно? Код a = (int)read_adc(0); Так ли уж необходимы нравоучения? Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность?
|
|
|
|
|
Nov 7 2007, 10:19
|
Частый гость
 
Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415

|
Цитата(IgorKossak @ Nov 7 2007, 16:33)  Так ли уж необходимы нравоучения? Это совет. Когда написал, тоже подумал, что звучит как нравоучение, но, виноват, все-таки оставил. Код unsigned int a = 0; ... a = read_adc(0); Не желательно без крайней необходимости приводить типы (в С++ для этого вообще три оператора). Это мое мнение
|
|
|
|
|
Nov 7 2007, 10:36
|
Местный
  
Группа: Свой
Сообщений: 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 втупую и посмотрите.
|
|
|
|
|
Nov 7 2007, 10:48
|
Частый гость
 
Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415

|
Цитата(mr_onnik @ Nov 7 2007, 17:09)  Исправил. Светодиод вообще перестал мигать. Что в таком случае может содержаться в переменной read_adc? Бесконечность? Странно, что раньше он мигал. Вы выводите в порт 0, вызываете функцию read_adc, пока она выполняется, а выполняется она быстро  , у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая.
|
|
|
|
|
Nov 7 2007, 10:55
|
Группа: Новичок
Сообщений: 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, пока она выполняется, а выполняется она быстро  , у вас ноль, после опять выводится 1. Т.е. светодиод выключен (другой вывод светодиода не земле?) пока выполняется функция. А где порт настраивается на выход? Или это CV в стартап коде делает? Действительно совет, попробуйте вашу программу погонять в AVR Studio или другом каком симуляторе. Гораздо полезнее разобраться самому. Задача-то простая. Подразумевается, что пауза между миганиями прямо пропорциональна подаваемому напряжению. Скажем, при 5В пауза будет около 1с, при 2,5 - 0,5с. Ведь, пока не будет выдержана пауза, АЦП не работает?
|
|
|
|
|
Nov 7 2007, 11:44
|
Частый гость
 
Группа: Участник
Сообщений: 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, порты и т.п конфигурируются ч/з меню/окошки?
|
|
|
|
|
Nov 7 2007, 12:22
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Вот что хорошо в CV, так это мастер нового проекта, он сам и порты настроит если того требуется и АЦП, таймера и прочее сам сконфигурит и разрешит, если надо, то сам сделает вектора прерываний и даже некоторую перифирию может подключить, например символьные ЖКИ, датчики температруры DS18B20, часы DS1307 и 1302 и др., только укажи на каком порту ты их желаешь видеть. Для УАРТа может сам сделать буферизированный прием и/или передачу. Но на этом прелести CV заканчиваются и начинаются суровые глюки, правда в маленьких проектах это не заметно.
--------------------
|
|
|
|
|
Nov 7 2007, 13:01
|
Местный
  
Группа: Свой
Сообщений: 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 и мультиплексор будет подключен к земле.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|