|
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 и мультиплексор будет подключен к земле.
|
|
|
|
|
Nov 7 2007, 19:41
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(mr_onnik @ Nov 6 2007, 23:15)  ....................... Господа(товарисчи... кому как больше нравится...), хватит измываться над автором темы... Автор, полную схему со ВСЕМИ параметрами, полностью софт, и подробное описание того что Вы хотели получить, в студию... Тогда точно найдутся желающие Вам подсказать...
|
|
|
|
|
Nov 8 2007, 21:22
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020

|
Цитата(singlskv @ Nov 7 2007, 21:41)  Автор, полную схему со ВСЕМИ параметрами, полностью софт, и подробное описание того что Вы хотели получить, в студию...
Код /***************************************************** This program was produced by the CodeWizardAVR V1.25.7a Evaluation Automatic Program Generator © Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com
Project : Version : Date : 02.11.2007 Author : Freeware, for evaluation and non-commercial use only Company : Comments:
Chip type : ATmega163 Program type : Application Clock frequency : 4,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 *****************************************************/
#include <mega163.h> #include <stdio.h> #include <stdlib.h> #include <io.h> #include <stdint.h> #include <delay.h>
#define F_CPU 4000000UL
// Read the AD conversion result unsigned int read_adc(unsigned char adc_input) { ADMUX=adc_input; // 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; }
// ADC initialization // ADC Clock frequency: 115,200 kHz // ADC Voltage Reference: Int., cap. on AREF
void init_avr(void) {
PORTA=0x00; DDRA=0x00;
PORTB=0x00; DDRB=0x00;
PORTC = 0x00; DDRC = 0xF0;/* set port C pins 7-4 as outputs, 3-0 as inputs */
PORTD=0x00; DDRD=0x0F;
// Global enable interrupts #asm("sei")
}
// Declare your global variables here
void main(void) { unsigned int a = 0; PORTD = 0x00; PORTC = 0x00; // Declare your local variables here
init_avr();
while (1) { a = read_adc(0); PORTC.6 = 1; delay_ms(a); PORTC = 0x00; delay_ms(a); }; } Программа CodeVisionAVR. Требуется сделать так, чтобы частота мигания светодиода прямопропорционально зависела от напряжения, подаваемого на ADC0.
|
|
|
|
|
Nov 8 2007, 23:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(mr_onnik @ Nov 9 2007, 00:22)  Код // ADC initialization // ADC Clock frequency: 115,200 kHz // ADC Voltage Reference: Int., cap. on AREF А где код инициализации ADC ? Вы там случаем битик ADEN выставить не забыли ?
|
|
|
|
|
Nov 22 2007, 21:28
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-11-07
Пользователь №: 32 020

|
Цитата(singlskv @ Nov 9 2007, 01:53)  А где код инициализации ADC ?
Вы там случаем битик ADEN выставить не забыли ? Скажу сразу: я не профи в этом деле, поэтому с инициализацией у меня прблемы  imho, ADEN выставляется в регистре ADCSR?
|
|
|
|
|
Nov 23 2007, 04:45
|
Местный
  
Группа: Свой
Сообщений: 283
Регистрация: 13-06-07
Из: Челябинск
Пользователь №: 28 391

|
Цитата while (1) { a = read_adc(0); PORTC.6 = 1; delay_ms(a); PORTC = 0x00; delay_ms(a); }; Почитал посты, тут как я понял мало кто использует CV, добавлю свою каплю, так как в CV работал около 1 года. Так вот зацитированная выше мною часть ИМХО должна выглядеть так: Цитата while (1) { read_adc(0); //Запуск преобразования АЦП a = ADCW; //Считывание преобразованного значения PORTC.6 = 1; //Установили вывод delay_ms(a); //Пауза PORTC.6 = 0; //Сбросили вывод delay_ms(a); //Пауза }; Если бы удосужились почитать Help на CV, то поняли бы что строка: Цитата a = read_adc(0); Представляет собой - чушь Правильность конфигурирования выводов и АЦП не проверяю, Wizard для этого есть
Сообщение отредактировал mrKirill - Nov 23 2007, 04:48
|
|
|
|
|
Nov 23 2007, 10:25
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(mrKirill @ Nov 23 2007, 06:45)  Если бы удосужились почитать Help на CV, то поняли бы что строка: Представляет собой - чушь А если бы удосужились посмотреть приведенный исходник, то поняли бы, что это вовсе не функция из библиотеки CV. Цитата(mrKirill @ Nov 23 2007, 06:45)  Правильность конфигурирования выводов и АЦП не проверяю, Wizard для этого есть "Программирование мышкой"? Ну-ну. Цитата(mr_onnik @ Nov 22 2007, 23:28)  Скажу сразу: я не профи в этом деле, поэтому с инициализацией у меня прблемы  Ее у вас просто нет  Возьмите описание АЦП, раздел регистры, выпишите все три описанных там регистра, далее читая описание на каждый из битов регистра решите, какое значение вам нужно записать в этот бит, чтобы АЦП сделало то, что вы хотите. И поставьте запись этих битов в эти регистры в функцию инициализации перед разрешением прерываний.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 23 2007, 11:11
|
Местный
  
Группа: Свой
Сообщений: 283
Регистрация: 13-06-07
Из: Челябинск
Пользователь №: 28 391

|
Цитата(Сергей Борщ @ Nov 23 2007, 16:25)  А если бы удосужились посмотреть приведенный исходник, то поняли бы, что это вовсе не функция из библиотеки CV. Если бы удосужились более внимательно прочитать пост #17, который я цитировал, то наверное заметили бы, что там внизу текста приведена фраза "Программа CodeVisionAVR.", вот и привел правильный кусок программы для CV. Цитата "Программирование мышкой"? Ну-ну. Насколько я понял в деле программирования и конфигурирования он не силен, потому пусть тыкается в Визарде, потом может научится все правильно конфигурировать Лично сам пишу работаю в AVR Studio (для asm), CodeVision и IAR (для С), потому "программирование мышкой" - не ко мне. Офф-топ закончен.
|
|
|
|
|
Nov 23 2007, 11:26
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(mrKirill @ Nov 23 2007, 13:11)  Если бы удосужились более внимательно прочитать пост #17, который я цитировал, то наверное заметили бы, что там внизу текста приведена фраза "Программа CodeVisionAVR.", Удосужился. CodeVisionAVR - это компилятор. Использовать или нет идущие в его комплекте библиотеки - личное дело программиста. В процитированном вами посте #17 библиотеки не используются. Вывод - ссылка на help по библиотекам неуместна. Цитата(mrKirill @ Nov 23 2007, 13:11)  вот и привел правильный кусок программы для CV. Использование библиотек не является ни необходимым, ни тем более достаточным условием правильности программы. Короче - в посте #22 вы вместо ответа на цитируемый пост #17 написали ответ на какие-то свои мысли, да еще с претензией. На что я вам и указал. И это как раз не оффтоп.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 23 2007, 15:14
|

Знающий
   
Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768

|
defunct,в CV это не пройдет.Почему-то у него нет хидера ioavrxxx.h или как он там в яре называется. Соответственно,компилятор не поймет атмеловские название битов регистров. Надо или напрямую в байтах загружать или один раз руками прописать и добавить в библиотеку(или содрать иаровский  .
--------------------
"Hello, word!" - 17 errors 56 warnings
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|