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

 
 
> АЦП и прерывания ATmega48, помогите начинающему...
NikitoS-86
сообщение Sep 22 2008, 10:29
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380



Добрый день. Я занялся изучением AVR, использую AVRStudio в связке с WinAVR.
И у меня появились затруднения определённого плана. Я имею представление о том, что есть прерывание, что есть стек, указатель команд и вообще имею хорошее знание касательно теории... Но дошло дело до практики... И попытался я написать простейший код... Итак ситуация: в качестве входа АЦП использоваться ADC7, надо будет на 3 выхода (PB0..2) выдавать адрес на мультиплексер, который будет переключать свои входы, на входв АДС7 будет как раз приходить сигнал с демультеплексора, АЦП должен оцифровать и записать эти данные в массив...
Вот примерный код:

Цитата
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

void port_B_settings (void);
void ADC_settings (void);
void port_C_settings (void);


int help_reg=0;

ISR (ADC_vect)
{
help_reg = 1;
}

void main (void)
{
int Ubat[4];
int Tbat[4];
int Icur;

port_B_settings();
ADC_settings();


for (int i=0;i<3;i++)
{
ADCSRA = 0xC8;
sei();

while (!help_reg)
{}

Ubat[i] = help_reg;
}
}

void port_B_settings (void)
{
DDRB = 0x07; //PB0..1 - outputs
}

void ADC_settings (void)
{
ADMUX = 0x07; //ADC7
ADCSRA = 0x88; //ADEN=1 | ADIE = 1
}



В нём правда ещё не выдаётся адрес никуда и т.д. Не суть... А суть в том, что у меня по-левому работает прерывание.
Я хочу, чтобы после начала прерывания шло ожидание прерывания, после чего его обработка и после чего запись..., а у меня выходит всякая ересь и в симуляторе вконце концов вообще после первого "прохода" получается бесконечный цикл....=/
Что я делаю неправильно?
Вопрос касательно языка С - можно ли обрабатывать прерывание не по этому макросу, а что называется ручками... Просто я не знаю как мне в такой обработчик прерывания отправить например указатель на мой массив, чтобы прям в обработчике осуществлять запись в массив, а не вводить для этого пресловутый help_reg=/

И ещё вопрос: я перед запуском АЦП настраиваю только его вход в ADMUX, а надо ли настраивать ещё первые байты, которые отвечают за настройку напряжения если не ошибаюсь... Вообще если можно, то посвятите немного о том, как настраивать и запускать АЦП, поскольку из даташита к сожалению не всё понял на английском, например мне не понятно немного что такое некий "непрерывный режим работы" АЦП, который настраивается через запись бита ADATA в регистре ADCSRA...

Ах да, последнее: речь идёт о ATmega48

Заранее огромное спасибо ответившим, просто уже 2 дня мучаюсь с этим АЦП=/

Сообщение отредактировал NikitoS-86 - Sep 22 2008, 10:31
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
SasaVitebsk
сообщение Sep 22 2008, 12:18
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Давайте по-порядку.
1) Для начала очень даже неплохо. smile.gif
2) Использовать 1 вход АЦП и 3 выхода для демультиплексирования. Может сразу использовать 8 входов? Если ног не хватает микруху взять другую?
3) При вашей инициализации АЦП выдаст прерывание 1 раз. У вас установлен запуск прерывания. Для того чтобы АЦП опять замерило сигнал, надо опять сделать старт измерения (в прерывании после чтения предыдущего значения). ADATE указывает что надо непрерывно измерять сигнал. То есть не требуется перезапуска. Период измерения задаётся в других регистрах. Здесь надо учесть, что у вас не связаны измерение сигнала и смена канала. Следовательно в этом режиме вам придётся отбрасывать одно показание с момента переключения канала.
4) Вы можете перевести АЦП в "автоматический" режим (ADATE). Применить прерывание по таймеру. Настроить таймер так, чтобы Ттаймера > 3*Tацп. Прерывание от АЦП не обрабатывать, а значение читать в прерывании от таймера (после этого сменять канал).
5) Естественно целесообразно прямо из прерывания заполнять массив. Не требуется никаких макросов. Такой как вы указали я не знаю. Для этого Вам надо объявить массив глобальным. Тоесть он должен быть объявлен там где вы объявили help_reg. В этом случае, он будет виден и в прерывании ив голове.
Если вы хотите чтобы переменная была видна только в прерывании и в тоже время сохраняла своё значение м/у входами в прерывание (например текущий номер канала), то необходимо объявить её в прерывании с квалификатором static.



Вот мелкий пример. Правда компилятор другой, ну и вырвано из контекста по-живому, но в общем то представление сложить удастся.
Код
...
// Из main.h
#define KADMUX            (1<<ADLAR)                // работа от внешнего опорного источника с выравниванием "влево"
//#define KADMUX            0                        // работа от внешнего опорного источника 10 бит
#define KADCSRA            ((1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2))// ADC разрешено, стартовать преобразование, на частоте Fclk/128
//#define KADCSRB            ((1<<ADHSM)                // скоростной режим ADC разрешен
#define KADCSRB            0                        // скоростной режим ADC запрещён
#define VIRTCHAN        0x3                        // "Виртуальный" аварийный канал
...
// Инициализация
// Инициализация АЦП
  ADMUX = KADMUX;                                        // работа от внешнего опорного источника с выравниванием "влево"
  ADCSRA = KADCSRA;                                        // разрешить режим "одиночный" с частотой 125кГц
  ADCSRB = KADCSRB;                                        // запретить режим "high speed"
  DIDR0 = 0xf;                                            // закрыть 4 первых бита канала АЦП
...
// Прерывание
#pragma    vector=TIMER1_COMPA_vect
__interrupt    static void    pvPWWLvl1(void)
{
uint8_t    static    TekChan,InADCChan=1;                // Текущий канал, текущий измеряемый канал АЦП
uint8_t    static    ChngChan;                            // Смена канала АЦП
uint8_t    i;
...
ChngChan++;                                            // увеличить счётчик прерываний
if(ChngChan==5)                                        // На пятый цикл сменить канал и прочитать АЦП
{
   ChngChan=0;                                            // начать сначала
   InpAdc[InADCChan]=(InpAdc[InADCChan]+ADCH)>>1;        // Считать канал и усреднить
   InADCChan++;                                            // Сменить канал
   if(InADCChan==CAN_T_CHAN)
   {
     InADCChan=1;                                        // Переход по кольцу
     InpAdc[MAXADC-1]=InpAdc[VIRTCHAN];                    // Переприсвоить виртуальный канал
   }
   ADMUX=KADMUX | InADCChan;                            // Выбрать канал
   ADCSRA =KADCSRA;                                        // Начать отсчёт заново
}
}
...
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- NikitoS-86   АЦП и прерывания ATmega48, помогите начинающему...   Sep 22 2008, 10:29
- - gormih   Для инииализации АЦП небходимо обязательно инициал...   Sep 22 2008, 11:41
- - NikitoS-86   1) Так я помоему как раз в функции ADC_settings ()...   Sep 22 2008, 11:45
- - NikitoS-86   1) К сожалению выбрать другую микруху - уже нельзя...   Sep 22 2008, 12:43
|- - SasaVitebsk   Цитата(NikitoS-86 @ Sep 22 2008, 15...   Sep 22 2008, 15:48
||- - Цыкетчик   Надо не забыть ещё сделать задержку примерно на 1м...   Sep 23 2008, 10:50
|- - Сергей Борщ   Цитата(NikitoS-86 @ Sep 22 2008, 15...   Sep 23 2008, 18:23
- - Aleksandr Baranov   Для манипуляции битами регистров в библиотеке avr-...   Sep 22 2008, 12:58
|- - NikitoS-86   Цитата(Aleksandr Baranov @ Sep 22 2008, 16...   Sep 22 2008, 13:13
|- - Aleksandr Baranov   Цитата(NikitoS-86 @ Sep 22 2008, 09...   Sep 22 2008, 13:43
- - NikitoS-86   Итак, во-первых, ОГРОМНОЕ спасибо всем откликнувши...   Sep 23 2008, 12:25
- - MrYuran   Цитатаmeasure_Ubat (&Ubat , &channel_numbe...   Sep 23 2008, 12:35
- - NikitoS-86   Да, так и есть по идее, и сначала я пользовал имен...   Sep 23 2008, 13:25
|- - MrYuran   Цитата(NikitoS-86 @ Sep 23 2008, 17...   Sep 23 2008, 13:46
- - SasaVitebsk   Высскажу несколько соображений общего характера. В...   Sep 23 2008, 16:09
- - NikitoS-86   Цитата(SasaVitebsk @ Sep 23 2008, 20:09) ...   Sep 23 2008, 19:25


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

 


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


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