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

 
 
 
Reply to this topicStart new topic
> ОДнократное преобразование в ATMEGA8
virtuality
сообщение May 18 2006, 14:33
Сообщение #1


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



Вот пример программы:
Код
char lcd_buffer[33];    
int temp=0;

#asm
    .equ __lcd_port=0x18
#endasm
#include<lcd.h>
#include<stdio.h>
#include <90s8535.h>
#include <delay.h>

#define ADC_VREF_TYPE 0x00

interrupt [ADC_INT] void adc_isr(void)
{
temp=ADCW;
delay_ms(20);
ADCSR|=0x40;
     lcd_clear();
     sprintf(lcd_buffer,"%imV",(temp*5-temp/10));
     lcd_puts(lcd_buffer);    
}

void main(void)
{


ADCSR=0x8E;
#asm("sei")
ADMUX=0;

ADCSR|=0x40;
lcd_init(16);
    while (1)
       {
       }
      
}



В принципе все понятно, но как мне сделать однократное преобразование по команде ?
Go to the top of the page
 
+Quote Post
defunct
сообщение May 18 2006, 15:54
Сообщение #2


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



одиночное преобразование можно и без прерываний обойтись:

Код
#define ADC_EN_MASK  (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0)  

int ReadAdc(void)
{
   ADCSRA = ADC_EN_MASK|(1 << ADSC);
   while ( ADCSRA & (1 << ADIF) );
   return ADCW;
}



Цитата
interrupt [ADC_INT] ....
...
delay_ms(20);
...

Задержка внутри обработчика прерывания, тем более не маленькая это если мягко сказать - "не по спортивному". Лучше так никогда не делать.
Go to the top of the page
 
+Quote Post
virtuality
сообщение May 18 2006, 16:20
Сообщение #3


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



А где в вашем коде выбор канала? Или он по умлочанию равен нулю?
Go to the top of the page
 
+Quote Post
Yura_K
сообщение May 18 2006, 16:44
Сообщение #4


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

Группа: Свой
Сообщений: 185
Регистрация: 5-05-06
Из: Ekaterinburg, Russia
Пользователь №: 16 821



Цитата
lcd_clear();
sprintf(lcd_buffer,"%imV",(temp*5-temp/10));
lcd_puts(lcd_buffer);

Лучше все это вынести в while.
Цитата
В принципе все понятно, но как мне сделать однократное преобразование по команде ?

В том же while при появлении команды запускать преобразование АЦП. А какая сложность (или я чего-то не понимаю)?


--------------------
Чудес не бывает - бывает мало знаний и опыта!
Go to the top of the page
 
+Quote Post
virtuality
сообщение May 18 2006, 16:50
Сообщение #5


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



Yura_K,

простите, но я полный лох. Очень понятный и конкретный код привел defunct, но если компилятор отказывается принимать ADEN и ADIF, я ничего не могу поделать, кроме как снова обратиться за разъяснением. Чтение мануалов не помогло. В них все удивительно складно.
Go to the top of the page
 
+Quote Post
WHALE
сообщение May 18 2006, 17:18
Сообщение #6


Знающий
****

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



вы пишите,что работаете с мега8,а подключаете #include <90s8535.h>-очепятка?
а чтобы прошел код defunct,добавьте(лучше в хидер)
#define ADEN 7
#define ADPS0 0
#define ADPS1 1
#define ADPS2 2
#define ADIF 4
Удачи!


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
defunct
сообщение May 18 2006, 17:20
Сообщение #7


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(virtuality @ May 18 2006, 19:20) *
А где в вашем коде выбор канала? Или он по умлочанию равен нулю?

Выбор канала можете разместить там же где он у Вас сейчас (в main).

А насчет ADIF, ADEN и ADSC
не знаю как в CodeVision подключить названия битов (в IAR это делается с помощью General Options -> System -> Enable bit definitions in I/O include files)

Но это не беда даже если в CV этого нет,
можно самостоятельно описать номера бит руководствуясь даташитом (описание регистра ADCSRA)

Код
#define ADEN  7
#define ADSC  6
#define ADATE 5
#define ADIF  4
#define ADIE  3
#define ADPS2 2
#define ADPS1 1
#define ADPS0 0
Go to the top of the page
 
+Quote Post
virtuality
сообщение May 18 2006, 19:42
Сообщение #8


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



Сделал. Компилятор не ругается. Но в ходе отладки установлено, что программа виснет в цикле while ( ADCSRA & (1 << ADIF) );

Стал я дальше ковырять.
Ну вот это мне совсем не понятно...
Залез я в генератор кода в CodeVision. Сгенерировал.
Установил источником опорного напряжения AVCC.
В коде появилась такая строчка : #define ADC_VREF_TYPE 0x40

ОДнако ниже есть еще вот что: ADMUX=ADC_VREF_TYPE;

Что же это получается.... Я думал что ADMUX - это номер канала ADC0,
ADC1... То есть тот пин, куда подается измеряемое напряжение.

Так... надо подучить матчасть. Почитал я все что нашел на эту тему,
некоторые моменты остались непонятны. Если несложно проясните их для меня.


1. Для чего необходима установка частоты АЦП? Правильно ли я думаю, чтоэ
АЦП работает как отдельный блок, помещая результат в регистр, из которого мы читаем впоследсвии?
Или же АЦП спит, а когда мы ставим бит в ADSC он включается, конвертирует, возвращает результат?
ТОгда в этом случает непонятно для чего нужен этот параметр - частота.

2. Источник опорного напряжения. Что надо сделать? Подключить к плюсу AREF и AVCC? И что лучше выбрать потом - AREF или внутренний опорник?


P.S. ПРошу прощения, если кому мои вопросы покажутся глупыми.
Go to the top of the page
 
+Quote Post
defunct
сообщение May 18 2006, 20:43
Сообщение #9


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(virtuality @ May 18 2006, 22:42) *
Сделал. Компилятор не ругается. Но в ходе отладки установлено, что программа виснет в цикле while ( ADCSRA & (1 << ADIF) );

Прошу прощения, ошибся:

while ( (ADCSRA & (1 << ADIF))==0 ) ;


Цитата
ОДнако ниже есть еще вот что: ADMUX=ADC_VREF_TYPE;



ADC_VREF_TYPE = 0x0; // ARef
ADC_VREF_TYPE = 0x40; // AVcc
ADC_VREF_TYPE = 0xC0; // internal ref

Вам сгодится последний 0xC0 (при этом Pin ARef нужно оставить неподключенным),
про ADMUX написано на стр. 202-203.

Цитата
1. Для чего необходима установка частоты АЦП?

Для того чтобы обеспечить оптимальное время преобразования взависимости от кварца.
Если установить частоту преобразования сильно низкую, то за время одиночного преобразования сигнал на входе может многократно измениться и результат преобразования получится недостоверным. Если же частоту преобразования поставить сильно высокую, АЦП также даст неверный результат. Необходимо подбирать предделитель, который задается битами ADPS2..0 регистра ADCSRA так, чтобы частота преобразования была в районе 100-150 khz (10-15ksps).
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение May 18 2006, 20:51
Сообщение #10


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

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



Цитата
1. Для чего необходима установка частоты АЦП? Правильно ли я думаю, чтоэ
АЦП работает как отдельный блок, помещая результат в регистр, из которого мы читаем впоследсвии?
Или же АЦП спит, а когда мы ставим бит в ADSC он включается, конвертирует, возвращает результат?
ТОгда в этом случает непонятно для чего нужен этот параметр - частота.


В Мегах(и большинстве других МК) АЦП последовательного приближения - т.е. набираеться код на ЦАП и сравниваеться с входным напряжением с помощью компаратора (схема на странице 193),естественно сразу код подобрать нельзя поэтому он вдвигаеться в хитрый регистр обозначенный на схеме как CONVERSION LOGIC. Для этого нужно некоторое количество тактовых импульсов.Подробнее об том можно почитать в книжках по аналоговой технике.
Частота выбираеться из соображений компромиса между быстордействием и точностью.(Чем больше время тем ближе будет напряжение на входном конденсаторе к истинному напряжению на входе).
Сам АЦП представляет из себя автомат управляемый внутренней логикой т.е срабатывает триггер, АЦП выполняет заданную последовательность операций - выборка - подбор кода - выдача в регистр и устанавливает бит готовности. Если стоит режим Free Running,
каждое новое преобразование начинаеться по завершению предыдущего (как бы генерит прерывание сам для себя).

Насчет VREF - в большинстве случаев достаточно внутреннего источника, т.к. АЦП 10-битный и годиться скорее очень для оценки питающих напряжений, температуры, аналоговых органов упраления, а не для точных измерений. В таких случаюх лучще применять специализированный кристалл.


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
virtuality
сообщение May 19 2006, 03:26
Сообщение #11


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



ОК. Спасибо! Более или менее разобрался. Заменил, как предложил Defunct - программа не виснет. ПРоблема пока только в проверке результатов - вывести некуда ))).

Моя задача - я уже писал в соседней теме -фотореле. От ацп большой точности не требуется - надо лишь отличить 0,05-0,15 В от 1-1,5 вольт. Я вначале решил использовать компаратор. ОДнако, так как конечно устройство собираюсь проектировать на ATTiny13 (сейчас с мега8 ковыряюсь, потому что макетка на нем собрана). При использоваии компаратора необходимо задействовть 2 линии - в тини13 их 6 и мне как раз одной не хватает. Поэтому я решил использовать АЦП.

Контроллер должен зажечь лазер, после этого снять показания через АЦП с фотодиода, и только после этого лазер выключается. Т.Е.
Цитата
то за время одиночного преобразования сигнал на входе может многократно измениться и результат преобразования получится недостоверным
мне не грозит.

Внутренний опорник в случае tiny13 - единственный вариант. Но у него напряжение 2,5 вольт. Не сгорит ли он если на него подать напряжение равное напряжению питания?
Go to the top of the page
 
+Quote Post
WHALE
сообщение May 19 2006, 04:09
Сообщение #12


Знающий
****

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



опорник точно не сгорит,ему все равно,что на входе ацп.и вход ацп не сгорит тоже,Uпитания для него норма.но все,что выше опорного напряжения,вы не увидите,поэтому лучше выберите в качестве опорного напряжения питания и подключите конденсатор на вывод Aref.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
otrog
сообщение May 19 2006, 06:38
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589



Цитата(virtuality @ May 19 2006, 07:26) *
надо лишь отличить 0,05-0,15 В от 1-1,5 вольт.
.......................
Но у него напряжение 2,5 вольт.

У Вас диапазон входного напряжения как раз лежит ниже напряжения внутреннего опорника, так что все будет работать. А если на входе будет напряжение выше Uоп, но ниже Uпит, то на выходе АЦП будет число 1023. Только и всего - ничего не сгорит.

PS Кстати на чем пишите? У меня CodeWizard от CodeVision выдал следующюю заготовку:
[code]#include <mega8.h>

#define ADC_VREF_TYPE 0xC0

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}


// Declare your global variables here

void main(void)
{
// Declare your local variables here
// ..................................................................
// ADC initialization
// ADC Clock frequency: 500,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x81;

Успехов.

Сообщение отредактировал otrog - May 19 2006, 06:50


--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
Go to the top of the page
 
+Quote Post

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

 


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


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