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

 
 
> Atmega48 запуск АЦП по внешнему сигналу
Oleg_IT
сообщение Jan 5 2015, 13:30
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Есть такой код
CODE
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//#include "PortDefine.h"
#include "avrlibdefs.h"
#include "avrlibtypes.h"

//#define USE_INT0

union {
uint16_t ADC_Data;
uint8_t ADC_Bute[2];
} Data;

#ifdef USE_INT0
ISR (INT0_vect)
{
ADCSRA |= (1 << ADSC);
}
#endif // USE_INT0

ISR (ADC_vect)
{
PORTD |= 1;
Data.ADC_Data = (unsigned short)inb(ADCL) | (unsigned short)(inb(ADCH) << 8);
PORTD &=~ 1;
}

int main( void )
{
// ADC
ADMUX |= (1 << REFS0) | (1 << MUX0) | (1 << MUX2); // ADC5, AVCC
ADCSRA |= (1 << ADEN) | (1 << ADATE) | (1 << ADIE);
ADCSRB |= (1 << ADTS1);
DDRC = 0;
PORTC = 0;


#ifdef USE_INT0
EICRA |= (1 << ISC01) | (1 << ISC00);
EIMSK |= (1 << INT0);
#endif // USE_INT0


DDRD = 0x03;
PORTD = 4;

sei();

ADCSRA |= (1 << ADSC);
while (1)
{
PORTD ^= 2;
}
return 0;
}

По идеи он должен запускать оцифровку по внешнему сигналу, но этого не происходит.
Если я открываю строку //#define USE_INT0 всё работает правильно, но при этом теряется время.
Строку инициализации EICRA убирал из под ифа, не помогает.
Может я чего в инициализации упускаю.

Сообщение отредактировал IgorKossak - Jan 8 2015, 19:35
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
alexeyv
сообщение Jan 6 2015, 09:17
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Я обычно запускаю АЦП от сигнала таймера, но и для внешнего прерывания должно быть аналогично.
1. Настраиваю АЦП, там мои макросы, но надеюсь будет понятно
Код
    adc_enable        ();
    adc_mode_trigger  ();
    adc_set_source    (ADC_SOURCE_TC0_CMPA);
    adc_set_prescaler (ADC_PRESCALE_DIV64); // or 128 ??
    adc_set_reference (ADC_REFERENCE_AVCC);
    adc_left_adjusted ();    // ADLAR = 1
    //    adc_right_adjusted();    // ADLAR = 0
    adc_int_enable    ();
    adc_set_channel   (0x00); // начальный канал

2. настраиваю таймер
Код
    timer0_init        (TIMER0_MODE_CTC,    T0_TICK *TIME_1MS);    // for ADC

3. пишу обрабртчик таймера, если не нужен - то делаем его пустой
Код
ISR(TIMER0_COMPA_vect)
{    timer0_tick    += T0_TICK;
}

4. пишу обработчик АЦП, например так
Код
ISR(ADC_vect)
{     rms.val = ADCH;
    adc_flag = 1;
}


Соответственно с внешним прерыванием аналогично:
1. прерывание ExtINT0 должно быть настроено и включено, иначе откуда будет подаваться сигнал на АЦП?
2. для избежания косяков, необходимо написать обработчик ExtINT0, пусть даже и пустой
3. в этом обработчике НЕ НАДО напускать АЦП, иначе это будет ПЕРЕЗАПУСК, запуск АЦП делает логика МК, которая подключает старт АЦП от внешнего прерывания. А вот само прерывание должно обрабатывать аппаратная логика этого прерывания
4. что за, извиняюсь, гуанокод?
Код
    ADMUX |= (1 << REFS0) | (1 << MUX0) | (1 << MUX2); // ADC5, AVCC
    ADCSRA |= (1 << ADEN) | (1 << ADATE) | (1 << ADIE);
    ADCSRB |= (1 << ADTS1);

Вы же однократно и один раз в начале програмы инициализируете АЦП, зачем там "|=" ? уберите их
Код
ADMUX = (1 << REFS0) | (1 << MUX0) | (1 << MUX2); // ADC5, AVCC
    ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADIE);
    ADCSRB = (1 << ADTS1);

Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 12th August 2025 - 04:47
Рейтинг@Mail.ru


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