Параллельные задачи в ATmega8

Обсуждаем контроллеры компании Atmel.
dzzzzzzz
Родился
Сообщения: 10
Зарегистрирован: Пн авг 19, 2019 14:09:55

Параллельные задачи в ATmega8

Сообщение dzzzzzzz »

Здравствуйте, уважаемые форумчане.
Прошу прощения, если эта тема уже рассматривалась и я просто не нашел ее на форуме (если это так, скиньте ссылку).

Задача: реализовать на ATmega8 одновременную работу диода (мигает с частотой 100 Гц) и отправки пакета сигналов по NEC-протоколу раз в 1 секунду. Запрещено использовать прерывания.

Вопрос: как?

Комментарий к задаче: я понимаю, что настоящего параллельного выполнения на ATmega8 не добиться, можно лишь имитировать параллелизм при помощи быстрого опроса флагов. В том-то и проблема, что совсем не получается придумать код для этого опроса.

Комментарий к работе уже готовой программы: пакет данных по NEC-протоколу передается в отдельной функции. Временные промежутки (560 мкс, 1,12 мкс, 2,25 мкс, 9 мс, 4,5 мс, 1 с) отсчитываются при помощи счетчика флага прерывания по совпадению (OCF2): флаг установился, счетчик увеличился на 1, флаг сбросился и так по циклу. Диодом мигать нужно тоже при помощи этого флага.

Код работающей программы:

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

#define F_CPU 2000000UL

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

#define PND4			   (1<<PD4)
#define PND3			   (1<<PD3)
#define PND2			   (1<<PD2)
#define PND1			   (1<<PD1)
#define PND0			   (1<<PD0)

#define OUT			   PB1					//порт вывода данных
#define ERROR                     111					//код ошибки
#define LED		           PB0					//порт, отвечающий за мигание диодом

#define but_0_50_4_9()      !(PIND & PND4)		//кнопка, отвечающая за числа 0, 4, 9, 50
#define but_10_60_3_8()    !(PIND & PND3)		//кнопка, отвечающая за числа 3, 8, 10, 60
#define but_20_70_2_7()    !(PIND & PND2)		//кнопка, отвечающая за числа 2, 7, 20, 70
#define but_30_80_1_6()    !(PIND & PND1)		//кнопка, отвечающая за числа 1, 6, 30, 90
#define but_40_90_0_5()    !(PIND & PND0)		//кнопка, отвечающая за числа 0, 5, 40, 90

#define but_from_0_to_40   0x20					//настраиваем на выход кнопку, покдлюченную к PC5
#define but_from_50_to_90 0x10					//настраиваем на выход кнопку, покдлюченную к PC4
#define but_from_5_to_9     0x08					//настраиваем на выход кнопку, покдлюченную к PC3
#define but_from_0_to_4     0x04					//настраиваем на выход кнопку, покдлюченную к PC2

uint8_t flag = 0;

void timer1_init(void)                          //таймер, настраивающий несущую 36 кГц
{
	TCCR1B |= (1 << WGM12)|(1 << CS10);
	TCCR1A |= (1 << COM1A0);
	OCR1A   = 27;
	TCNT1   = 0;
}

void timer2_init(void)                          //таймер, отсчитывающий отрезки по 560 мкс
{
	TCCR2 = (1 << CS21);
	OCR2  = 140;                           
	TCNT2 = 0;
}

void port_init(void)				//инициализация портов для опроса кнопок и вывода сигнала
{
	DDRB   |= (1 << OUT)|(1 << LED);
	PORTB  |= (1 << OUT);
	DDRD    = 0b00000000;
	PORTD   = 0b00011111;
}

void timer(void)					//счетчик, отсчитывающий отрезки по 560 мкс
{
	if (TIFR & (1 << OCF2))
	{
		TIFR |= (1 << OCF2);
		TCNT2 = 0;
		if (flag) flag--;
	}
}

void on(void)					//функция, выдающая импульсы на выходе (формирует стартовый сигнал, сигнал единицы и сигнал нуля)
{
	TCCR1A |= (1 << COM1A0);
	TCCR1A &= ~(1 << COM1A1);
}

void off(void)					//функция, выдающая паузу на выходе (формирует стартовый сигнал, сигнал единицы и сигнал нуля)
{
	TCCR1A &= ~(1 << COM1A0);
	TCCR1A |= (1 << COM1A1);
}

void start_func(void)				//формирование стартовой функции
{
	flag = 17;
	on();
	while (flag) timer();
	
	flag = 8;
	off();
	while (flag) timer();
}

void one_func(void)				//формирование сигнала единицы
{
	flag = 1;
	on();
	while (flag) timer();
	
	flag = 3;
	off();
	while (flag) timer();
}

void null_func(void)				//формирование сигнала нуля
{
	flag = 1;
	on();
	while (flag) timer();
	
	flag = 1;
	off();
	while (flag) timer();
}

void signal_out(char command)		//вывод сигнала
{
	start_func();	                             //отправляем стартовый сигнал
	for(char i=0; i<8; i++)                    //посылаем отдельно каждый бит
	{
		timer();
		if (command & (1<<i)) one_func();
		else                  null_func();    //если i-ый бит равен 1, отправляем 1, если 0, отправляем 0
	}
		
	for(char i=0; i<8; i++)                   //посылаем отдельно каждый бит
	{
		timer();
		if (command & (1<<i)) null_func();
		else                  one_func();   //если i-ый бит равен 1, отправляем 1, если 0, отправляем 0
	}
	one_func();
}

uint16_t button_handler (void)		//обработка нажатых кнопок
{
	uint16_t command1 = ERROR;			//значение кнопок, отвечающих за десятки, в состоянии по умолчанию
	uint16_t command2 = ERROR;		        //значение кнопок, отвечающих за единицы, в состоянии по умолчанию
	uint16_t command  = 0;
	
	DDRC = but_from_0_to_40;
	_delay_us(1.1);
	if (but_0_50_4_9())	command1=0;
	if (but_10_60_3_8())	command1=10;
	if (but_20_70_2_7())	command1=20;
	if (but_30_80_1_6())	command1=30;
	if (but_40_90_0_5())	command1=40;
	
	DDRC = but_from_50_to_90;
	_delay_us(1.1);
	if (but_0_50_4_9())	command1=50;
	if (but_10_60_3_8())	command1=60;
	if (but_20_70_2_7())	command1=70;
	if (but_30_80_1_6())	command1=80;
	if (but_40_90_0_5())	command1=90;
	
	
	DDRC = but_from_5_to_9;
	_delay_us(1.1);
	if (but_0_50_4_9())	command2=9;
	if (but_10_60_3_8())	command2=8;
	if (but_20_70_2_7())	command2=7;
	if (but_30_80_1_6())	command2=6;
	if (but_40_90_0_5())	command2=5;
		
	DDRC = but_from_0_to_4;
	_delay_us(1.1);
	if (but_0_50_4_9())	command2=4;
	if (but_10_60_3_8())	command2=3;
	if (but_20_70_2_7())	command2=2;
	if (but_30_80_1_6())	command2=1;
	if (but_40_90_0_5())	command2=0;
	
	command=command1+command2;		//вычисление номера этажа
	if (command >= 100)	command=ERROR;	//условие выдачи ошибки
	
	return command;
}

int main(void)
{
	port_init();
	timer1_init();
	timer2_init();
	sei();
    while (1)
	{	
		signal_out(button_handler());		
	}
}
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

и чо? что это вообще должно означать?
имхо, все это бред.
для IR дистанционного управления допускаются достаточно большие отступления в длительности посылок (точно не скажу, но процентов до 5-10, пожалуй), что позволяет использовать прерывания. и в итоге задача из проблемы превращается в пшик.

Добавлено after 46 seconds:
я уж молчу про отправку битов "вручную", а не циклом по команде... это за гранью разумного, имхо.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
ЭлектроKOT
Вымогатель припоя
Сообщения: 550
Зарегистрирован: Вс июл 07, 2019 16:12:46

Re: Параллельные задачи в ATmega8

Сообщение ЭлектроKOT »

[uquote="ARV",url="/forum/viewtopic.php?p=3686378#p3686378"]это за гранью разумного, имхо.[/uquote]Изобретения собственных велосипедов неизбежны, как и падения бутербродов маслом вниз :twisted:

dzzzzzzzИзображение
RTFM
Делай то, что тебе нравится и ты никогда не будешь работать
dzzzzzzz
Родился
Сообщения: 10
Зарегистрирован: Пн авг 19, 2019 14:09:55

Re: Параллельные задачи в ATmega8

Сообщение dzzzzzzz »

[uquote="ARV",url="/forum/viewtopic.php?p=3686378#p3686378"]и чо? что это вообще должно означать?
имхо, все это бред.[/uquote]

согласитесь, вопрос был немного другим: как реализовать задачу параллельной работы (псевдопараллельной) в сложившихся условиях без использования прерывания

я учусь в освоении AVR, не все идеально, но я и не претендую на звание "гуру м/к"

если ваших способностей не хватает, чтобы помочь в решении задачи, так может и не стоит стучать по клавиатуре и набирать такие бессмысленные сообщения?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

dzzzzzzz писал(а):вопрос был немного другим
вопрос был другим, это факт. но от того, какой вопрос вы ставите, зависит результат. если бы люди хотели достать Луну с неба для изучения, они до сих пор бы не знали о том, что она летает вокруг Земли. люди поставили другие вопросы - и нашли решения без необходимости доставать Луну.

советую и вам вместо взращивания гонора сосредоточиться на правильном анализе проблемы и поиске наиболее простого её решения.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15556
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Параллельные задачи в ATmega8

Сообщение BOB51 »

Есть такая штука - ДИСПЕТЧЕР ЗАДАЧ.
:wink:
Только в АВРке не использовать аппаратную начинку
для создания псевдопараллельности в простейших проектах....
Ежли только это не для учебного изврата...
:dont_know:
Реклама
dzzzzzzz
Родился
Сообщения: 10
Зарегистрирован: Пн авг 19, 2019 14:09:55

Re: Параллельные задачи в ATmega8

Сообщение dzzzzzzz »

[uquote="ARV",url="/forum/viewtopic.php?p=3686402#p3686402"]советую и вам вместо взращивания гонора сосредоточиться на правильном анализе проблемы и поиске наиболее простого её решения.[/uquote]

советую вам подбирать выражения при общении с людьми, даже если это происходит на форуме
стандартные правила приличия никто не отменял
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Параллельные задачи в ATmega8

Сообщение Ivanoff-iv »

IF (обоснованно объяснишь необходимость отказа от прерываний) {встану; буду аплодировать; помогу сделать;} else {делай по уму - на прерываниях;};
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Параллельные задачи в ATmega8

Сообщение ПростоНуб »

dzzzzzzz, прерывания в данном случае нужны, а вот обработчик прерывания может быть примитивен. Мультизадачность реализуется тупейшим способом. Выполняется остановка процессора (команда SLEEP), а после нее проверяется, по какому прерыванию проснулись. В зависимости от этого вызывается соответствующая функция, после нее проверяем наличии необработанных событий (произошедших за это время прерываний). Если таковые есть - команда SLEEP пропускается. Если нет - засыпаем снова.
В более сложном случае реализуем кольцевой буфер, сообщения в который добавляются из обработчиков прерываний, а считываются и удаляются сообщения из него в том же бесконечном цикле с SLEEP.
Я, обычно, оперирую сообщениями длиной от 1 до 4 байт. Длина определяется старшими двумя битами кода сообщения в первом байте. Младшие шесть бит рассматриваются как индекс в массиве указателей на функцию обработчика события. Остальные байты, если они есть, передаются вызываемой функции через параметры (uint8_t, uint16_t или uint16_t плюс uint8_t)
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

2 ПростоНуб :facepalm: :facepalm: :facepalm:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Параллельные задачи в ATmega8

Сообщение ПростоНуб »

ARV, а каков Ваш метод реализации мультизадачности на восьмибитных МК? Реализовывать полноценную RTOS, захламляя стек данными прерванных задач и обеспечивая реентерабельность всех функций? Или Ваше решение оффтопик - на вопрос о реализации мультизадачности ответить, что она не нужна ТС?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

да тот самый, который всегда и был: фоновые задачи по прерываниям, остальное тупо в главном цикле.
сомневаюсь, что до уровня реализации TCP/IP своими силами или иных сетевых протоколов, требуются на самом деле "мультизадачные" методы из "большого" программирования.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15556
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Параллельные задачи в ATmega8

Сообщение BOB51 »

Ну для ассемблера можно добавить еще условный возврат из прерывания на разные задачи, закрепленные зе данным прерыванием.
:roll:
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Параллельные задачи в ATmega8

Сообщение ПростоНуб »

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

Например, мой подход для HC-SR04 реально обеспечил точность даже выше заявленной - получилось +-5мм на расстояниях до 1 метра. А версия сына в основном цикле из-за возникающих длинных прерываний гуляла на порядок больше - +-50мм.

Добавлено after 7 minutes 53 seconds:
BOB51, проблема та же, что и в C - расход стека на сохранение контекста прерванных задач. Не забывайте, что так как я фиксирую в сообщениях время возникновения события, то даже если очередной обработчик длился более, чем несколько событий от того же IR приемника, я ничего не потеряю. Просто декодирую посылку чуть позже - таймстэмпы то есть )
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

я поздравляю вас, что вы сумели превзойти своего сына в программировании :)
но я всегда сам придерживался и другим рекомендовал придерживаться принципа "чем проще, тем лучше". задача ТС - мигание светодиода 100 Гц - это период 5 мс. Протокол NEC не содержит интервалов длиннее этих 5 мс (если не считать стартовый импульс 9 мс).
в итоге передачу NEC-кода можно делать в главном цикле даже при помощи _delay_us, а в это время по прерыванию таймера мигать светодиодом. будет ли ваш вариант проще? сомневаюсь.
если паранойя замучает, можно в главном цикле ждать, пока таймер "отмигнет", чтобы посылать очередной бит NEC-команды строго тогда, когда он не будет прерван обработчиком - и все равно это будет крайне просто.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Параллельные задачи в ATmega8

Сообщение ПростоНуб »

ARV, Ваш вариант - отказаться от мультизадачности, то бишь оффтопик )

Ну и Ваш вариант не универсален. Например, на той же ATtiny13A только один таймер и именно его нужно будет использовать для модуляции IR. Для 100Гц уже таймера не останется )
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

мультизадачность - это "одновременное" исполнение нескольких задач. поскольку в моем примере одна задача - мигание выполняется одновременно со второй - отправкой кода, все строго в рамках поставленной задачи. только с прерываниями.
вероятно ТС хотел кооперативную мультизадачность :) но я ему сразу сказал - это бред.
ПростоНуб писал(а):Ну и Ваш вариант не универсален. Например, на той же ATtiny13A только один таймер и именно его нужно будет использовать для модуляции IR. Для 100Гц уже таймера не останется
мда... это вам кто-то подсказал, или вы сами додумались? ;) вот здесь https://simple-devices.ru/prj/9-electr/ ... te-control есть исходник передатчика RC5 - там немного другие принципы, но модуляция и т.п. все то же самое. и как раз attiny13 :))) и, вы не поверите! - там IR-посылка формируется вместе с модуляцией на тупых _delay_us! :))) так шта...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Параллельные задачи в ATmega8

Сообщение ПростоНуб »

ARV, Вы забыли о мигании в 100 Гц. Когда задержки в 18мкс формируются программно, прерывание от таймера раз в 10мс приведет к сбою посылки модулируемого сигнала. А вся посылка длится существенно дольше 10мс.
Иными словами, приведенный Вами в качестве примера код, совершенно не работоспособен при разрешенных прерываниях )
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Параллельные задачи в ATmega8

Сообщение ARV »

ПростоНуб писал(а):приведенный Вами в качестве примера код, совершенно не работоспособен при разрешенных прерываниях
хотите поспорить? ;) я могу доказать.

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

ISR(TIMER0_OVF_vect){
   PINB |= 1;
}
как по-вашему, сколько тактов займет обработчик этого прерывания для мигания светодиодом? не трудитесь, вот листинг:

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

ISR(TIMER0_OVF_vect){
	PINB |= 1;
  32:	b0 9a       	sbi	0x16, 0	; 22
}
  34:	18 95       	reti
то есть сам обработчик 2 такта, плюс 4 на вход-выход, итого 6 тактов. при тактировании от 8 МГц это будет аж 750 наносекунд. вы на самом деле считаете, что при такой погрешности IR-посылки она не будет корректно принята приемником? ;)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15556
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Параллельные задачи в ATmega8

Сообщение BOB51 »

А что это за "мигание" в 100ГЦ???
Чей глаз его узрит-то?
:)))
Там и просто включить можно, и "мигающий" поставить...
Нафига мозг по дурному морочить?
:wink:
Ответить

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