АЦП в режиме Auto Triggering

Обсуждаем контроллеры компании Atmel.
Ответить
KAS2024
Родился
Сообщения: 7
Зарегистрирован: Вс янв 07, 2024 12:31:51

АЦП в режиме Auto Triggering

Сообщение KAS2024 »

Уважаемые форумчане, всех с праздниками!
Пытаюсь использовать АЦП AVR в режиме периодического автозапуска от таймера.
Код пытается работать, опрос АЦП осуществляется, но почему-то ровно 2 раза, а не до бесконечности, как планировалось.
После этого код висит в вечном цикле (проверял, тестовый код в вечном цикле корректно выполняется), а прерывание АЦП не вызывается более 2 раз.

Тестирую на ATmega16, тактовая частота 4МГц, на входе потенциометр, результат наблюдаю в программе-читалке COM-порта.
По задумке должно возникать событие Compare Match B таймера 1 с частотой 2Гц (проверял, возникает c нужной частотой),
которое автотриггерит АЦП, запуская прерывание АЦП по окончанию преобразования (запускается, но ровно 2 раза, если жать на Reset, то снова 2 раза и дальше тишина до Reset),
в прерывании АЦП результат отправляю по UART (результат корректный, по UART доходит)
Использую Microchip Studio 7.0, оптимизация отключена.

Помогите, товарищи! Сломал всю голову, скурил весь даташит, ничего не понимаю! Возможно, глаз замылился, но не настолько же! Четвертые сутки бьюсь с простеньким, вроде бы, кодом (

Код ниже:

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>

void init();
void uart_init();
void timer1_init();
void adc_init();
void uart_send( char x );

ISR( ADC_vect )
{
    uart_send( ADCH );
}

int main(void)
{
	init();
		
    while (1){}
}

void init()
{
    uart_init();
	timer1_init();
	adc_init();
	
	sei();
}

void uart_init()
{
    UBRRL = 25; // 9600bod at CLK = 4MHz
    UCSRB = 1 << TXEN;       
}

void timer1_init()
{
	OCR1A   = 31250;
	OCR1B   = OCR1A;
	TCCR1B  = ( 1 << WGM12 ) | ( 1 << CS11 ) | ( 1 << CS10 ); // /64 2Hz at CLK=4MHz
}

void adc_init()
{
    ADMUX  = ( 1 << REFS0 ) | ( 1 << ADLAR ); // PA0, AVCC, PA0
	SFIOR  = ( 1 << ADTS2 ) | ( 1 << ADTS0 ); // COMPB 
	ADCSRA = ( 1 << ADEN )  | ( 1 << ADSC ) | ( 1 << ADATE ) | ( 1 << ADIE ) | ( 1 << ADPS2 ) | ( 1 << ADPS0 ); //COMPB, ADCclk=125kHz
	
}

void uart_send( char x )                           
{
    while ( !( UCSRA & ( 1 << UDRE ) ) );        
    UDR = x;                                     
}
Вложения
main.c
Исходник в виде файла
(978 байт) 73 скачивания
Реклама
Аватара пользователя
Starichok51
Модератор
Сообщения: 19053
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: АЦП в режиме Auto Triggering

Сообщение Starichok51 »

первый запуск АЦП происходит потому, что ты при инициализации АЦП сразу задал ADSC - старт преобразования.
второй запуск, видимо, происходит по заданному триггеру.
убери (1 << ADSC), должен остаться один запуск.
но почему нет повторов "до бесконечности" я сказать не могу.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
KAS2024
Родился
Сообщения: 7
Зарегистрирован: Вс янв 07, 2024 12:31:51

Re: АЦП в режиме Auto Triggering

Сообщение KAS2024 »

Если убрать (1 << ADSC) при инициализации, то запуск только один, я пробовал. Что тоже странно, ибо, как я понимаю даташит, опрос АЦП стартует только после выставления start conversion (если не брать во внимание энергосберегающие режимы).
Попа какая-то, простите за физиологию.. Уже в errata полез от горя, но не нашел там поддержки(

Добавлено after 4 minutes 31 second:
Пробовал выставлять ADSC <- 1 в main(), после разрешения глобальных прерываний, давал длинные задержки перед этим (даташит говорит, что модули АЦП могут инициализироваться 1 * CLKadc + какое-то там время), результат идентичен

Добавлено after 8 minutes 5 seconds:
Можно, конечно, в прерывании таймера руками выставлять ADSC - режим однократного опроса, так работает, но какого x***, если есть заявленный автотриггер? Понять бы, кто тупой, я, или микрочип?! Начинаю сомневаться .. в микрочипе
Аватара пользователя
Starichok51
Модератор
Сообщения: 19053
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: АЦП в режиме Auto Triggering

Сообщение Starichok51 »

после задания (1 << ADSC) АЦП стартует сразу же, не ожидая запуска по триггеру.
у тебя же старт должен происходить по триггеру, без установки этого бита.
в даташите на АТмега16 я не нашел, чтобы бит ADATE сам сбрасывался. но по поведению похоже, что бит сбрасывается и запуск по триггеру происходит однократно.
но ты можешь попробовать в прерывании от АЦП заново установить этот бит ADATE, и посмотреть, будет ли автостарт повторяться.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Нефертити
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср дек 06, 2023 23:51:29
Откуда: 48

Re: АЦП в режиме Auto Triggering

Сообщение Нефертити »

Флаг OC1B надо вручную сбрасывать, т.к. обработчик отсутствует.
Добавьте

Код: Выделить всё

TIFR |= (1 <<  OCF1B);
в обработчик ADC.
Иначе, OC1B так и продолжает висеть, и новый строб не проходит.
Реклама
KAS2024
Родился
Сообщения: 7
Зарегистрирован: Вс янв 07, 2024 12:31:51

Re: АЦП в режиме Auto Triggering

Сообщение KAS2024 »

[uquote="Нефертити",url="/forum/viewtopic.php?p=4527530#p4527530"]Флаг OC1B надо вручную сбрасывать, т.к. обработчик отсутствует.
Добавьте

Код: Выделить всё

TIFR |= (1 <<  OCF1B);
в обработчик ADC.
Иначе, OC1B так и продолжает висеть, и новый строб не проходит.[/uquote]

Мать моя, женщина, точно, просохатил! Спасибо огромное, заработало! :)

Добавлено after 4 minutes 33 seconds:
[uquote="Starichok51",url="/forum/viewtopic.php?p=4527523#p4527523"]после задания (1 << ADSC) АЦП стартует сразу же, не ожидая запуска по триггеру.
у тебя же старт должен происходить по триггеру, без установки этого бита.
в даташите на АТмега16 я не нашел, чтобы бит ADATE сам сбрасывался. но по поведению похоже, что бит сбрасывается и запуск по триггеру происходит однократно.
но ты можешь попробовать в прерывании от АЦП заново установить этот бит ADATE, и посмотреть, будет ли автостарт повторяться.[/uquote]

И тоже верно, я неправильно прочитал даташит, понял так, что на самое первое преобразование надо ставить ADSC, но нет

Вот верный код, если кого-то заинтересует:

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>

void init();
void uart_init();
void timer1_init();
void adc_init();
void uart_send( char x );

ISR( ADC_vect )
{
    uart_send( ADCH );
	
	TIFR |= (1 <<  OCF1B);
}

int main(void)
{
	init();
		
    while (1){}
}

void init()
{
    uart_init();
	timer1_init();
	adc_init();
	
	sei();
}

void uart_init()
{
    UBRRL = 25; // 9600bod at CLK = 4MHz
    UCSRB = 1 << TXEN;       
}

void timer1_init()
{
	OCR1A   = 31250;
	OCR1B   = OCR1A;
	TCCR1B  = ( 1 << WGM12 ) | ( 1 << CS11 ) | ( 1 << CS10 ); // /64 2Hz at CLK=4MHz
}

void adc_init()
{
    ADMUX  = ( 1 << REFS0 ) | ( 1 << ADLAR ); // PA0, AVCC, PA0
	SFIOR  = ( 1 << ADTS2 ) | ( 1 << ADTS0 ); // COMPB 
	ADCSRA = ( 1 << ADEN )  | ( 1 << ADATE ) | ( 1 << ADIE ) | ( 1 << ADPS2 ) | ( 1 << ADPS0 ); //COMPB, ADCclk=125kHz
	
}

void uart_send( char x )                           
{
    while ( !( UCSRA & ( 1 << UDRE ) ) );        
    UDR = x;                                     
}
Добавлено after 2 minutes 10 seconds:
Спасибо всем огромное !
Да, Старик, прочитал, независимо от автотриггера можно ставить ADSC и будет лишь внеочередной опрос, все так! При автотриггере, действительно, устанавливать ADSC не требуется
Братцы, вы - мозг!
Реклама
Аватара пользователя
Нефертити
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср дек 06, 2023 23:51:29
Откуда: 48

Re: АЦП в режиме Auto Triggering

Сообщение Нефертити »

Не забывайте, что у Вас время оцифровывания всего-лишь 1-го канала 124 микросекунды.
Изображение
Изображение
Это я хочу дополнить, к дальнейшему развитию Вашего проекта.
Ответить

Вернуться в «AVR»