All streams
Search
Write a publication
Pull to refresh
32
0
Андрей @Andy_Big

Пользователь

Send message

Очевидно же, что пишут про задержки наушников, а не внутренностей синтезатора.

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

Ненавижу писать. После 4-5 строк рукописного текста меня начинает чуть ли не трясти от желания закончить побыстрее, скомкать бумагу и пойти напечатать это на нормальной клавиатуре :)

Каждый раз, как вижу ник статью за авторством этого ника, думаю - "Ну может быть хоть в этот раз он хоть какую-то из своих фантазий попробовал реализовать на практике?". Но нет. Мало того, в этот раз он даже не удосужился изучить имеющийся в инете практический опыт реализации некоторых из своих фантазий :)

Будет кто надо. А эти, вероятно, оказались не совсем кем надо.

Мне кажется, что отреагировать на кнопку в прерывании обработкой каких-то данных - это не самая плохая идея.

Угу. По нажатию кнопки отправляем по RS-485 запрос датчику, дожидаемся от него ответ, обрабатываем полученные данные, выводим результат на экран. И за это время пропускаем пять следующих прерываний. Отличный план, что тут может пойти не так? :)

В фоновой программе работает какой-то процесс, и вдруг в прерывании меняется его состояние... сомнительно тоже.

Поэтому в прерывании меняется состояние не процесса, а флага, который фоновая (хотя строго говоря это как раз не фоновая, а активная) программа проверит когда у нее будет для этого возможность.

посмотрите хотя бы как реализован HAL-драйвер в прерываниях таймеров у STM32

Я Вам уже писал: HAL от ST - это далеко не лучший пример для подражания.

На Ардуине не работал, Куб использую только для "конструирования" начальной инициализации периферии, да и то с большой оглядкой. Ардуина - это вообще отдельный разговор. Но тот же IAR, да и Keil вроде тоже, добавят от себя лишь минимальный стартап-код. И насчет "пусть лежит на всякий случай" - линкеры этим уже давно не занимаются даже с минимальным уровнем оптимизации. Если лежит - значит оно где-то используется.

Я бы даже немного сузил рамки интереса - 128-512 КБ ПЗУ и 64-192 КБ ОЗУ.

Меня тоже смущает, поэтому я свое некоторое смущение перевел в свой некоторый стыд :) Но у меня и официально купленного софта много, вы не подумайте :)

Iar (на тот момент хороший компилятор - ужасный редактор кода)

Ну, редактор у него и сейчас все еще не идеал :) А версия 9.30 еще и тормозить начала при переключении между режимами отладки и правки кода :) Но вообще это та среда, на которой я остановился много лет назад и до сих пор не жалею.

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

регулярное сидение на таких "Мега-IDE"(точно так как и дальнейшее сидение после начального вхождения в Arduino-IDE) сводит Ваш дальнейший профессиональный рост в работе с МК, лишь к навыкам работы в конкретной IDE, а не общего понимания специфики процесса программирования МК как класса железяк.

Непонятно. Понимание специфики программирования МК как класса железяк резко пойдет в гору если исходники писать в блокноте, а собирать проект через командную строку с ручным указанием всех ключей компилятора и линкера?

"Я снова сделаю Твиттер свободным и демократичным!" - говорил он...

Электромагнитные волны в зависимости от их длины можно разделить на три основных диапазона: инфракрасный, ультрафиолетовый, а также видимый спектр.

И к какому из этих трех основных диапазонов относится, скажем, длина волн, которые передают на наши радиоприемники музыку?

Ну если с возможностью оценки размера и плотности с допустимой погрешностью я еще могу согласиться, то все остальное - только предположения. Например, по Вашим ссылкам пишут, что расчет температуры "основан на предположении, что планета имеет атмосферу, подобную земной с парниковым эффектом за счет наличия 1 % СО2 и при альбедо 0,3". То есть реальная температура экзопланет на самом деле неизвестна. Состав (а зачастую и само наличие) атмосферы так же неизвестны, можно лишь в редких случаях делать предположения типа "вероятно, она содержит пары воды", да и то не для землеподобных планет. По крайней мере беглое гугление говорит, что на данном этапе технологий мы можем хоть как-то оценивать некоторые характеристики атмосферы лишь для очень больших планет с толстым слоем атмосферы и для молодых планет, которые, по сути, еще и полноценными планетами-то не являются.

Соответственно вся землеподобность сводится к "на ней должна быть похожая гравитация и она получает плюс-минус столько же энергии от своей звезды, сколько и Земля от Солнца" :)

Смотрел и щупал, поэтому не использую его в своих проектах. HAL уже вплотную приблизился к ардуино-стилю :)

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

Я и имел ввиду, что надо передать данные о нажатии кнопки в фоновую программу.

Честно говоря, из текста это совершенно не очевидно, по крайней мере для меня :)

Концепция предполагает удобство программирования без оглядки на ресурсы контроллера.

Речь ведь не о производительности, а о базовых принципах программирования для микроконтроллера. В прерываниях должен быть код, выполняющийся за минимально возможное время, что в 8-битной Ардуине на 8 МГц, что в 32-битном ARM-е на 400 МГц :)

просто посмотрите, как реализованы некоторые библиотеки Arduino. И почитайте статьи по программированию Arduino в интернете.

Это отдельный вид искусства антипрограммирования, согласен. Значит тем более не нужно прививать начинающим эти антипаттерны :)

Если разобрать, как это было сделано тогда - окажется любопытно.

Ну разве что ради любопытства :)

Позволю себе несколько замечаний.

  1. Зачем хранить инициализирующие параметры кнопок в структуре в оперативной памяти? Ее как правило не так уж много, а изменения этих параметров в процессе работы программы вроде бы не предполагается.

  2. Структура текущего состояния кнопок мне кажется излишне большой. Ниже приведу свой вариант с пояснениями.

  3. "В обработчике прерывания, вместо вывода в терминал сообщений о нажатии кнопки, вы можете разместить полезный код, который будет реагировать на нажатие кнопки." - ну зачем же учить начинающих плохому? В прерывании код должен быть как можно более коротким. В данном случае - только оценка текущего состояния кнопок и все, никаких реакций на их нажатие, тем более никаких медленных блокирующих выводов в UART. Это очень, очень вредная рекомендация.

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

enum
{
  	KB_FREE,		// отсутствие событий у кнопки
  	KB_WORKED,		// последнее событие кнопки было обработано
	KB_PREPRESSED,	// есть сигнал нажатия, идет выжидание антибребезга
	KB_SPRESSED,	// подтверждено нажатие кнопки после антидребезга
	KB_LPRESSED,	// кнопка остается нажатой длительное время
	KB_SRELEASED,	// кнопка отпущена после короткого времени нажатия
	KB_LRELEASED,	// кнопка отпущена после долгого нажатия
} KBD_STATES;

typedef struct
{
	KBD_STATES state;
	uint8_t	time;
} KEYBOARD;

Структура имеет размер всего 5 байтов, и этого достаточно для обработки короткого и длинного нажатий, а так же отпускания после короткого и длинного нажатий.

Алгоритм обработки каждой кнопки в цикле в прерывании таймера таков:

for (uint8_t kb = 0; kb < keys_count; kb++)
{
  	switch (Keys[kb].state)  	// проверяем текущий статус кнопки
	{
  	  	// если событие кнопки было обработано и сейчас кнопка отпущена,
  	  	// то возвращаем ее статус в свободный
		case KB_WORKED:
  			if (!KeyRead(kb))  	// если на входе нет сигнала нажатой кнопки
			{
				Keys[0].state = KB_FREE;
			}
			break;
  	  	// если кнопка в свободном состоянии, или была отпущена после
  	  	// любого нажатия, и в данный момент есть сигнал ее нажатия,
  	  	// то начинаем обработку антидребезга
		case KB_FREE:
		case KB_SRELEASED:
		case KB_LRELEASED:
			if (KeyRead(kb))
			{
				Keys[kb].state = KB_PREPRESSED;
				Keys[kb].time = 0;  	// обнуляем счетчик времени
			}
			break;
  	  	// если кнопка в состоянии обработки антидребезга и есть сигнал
		// нажатия - инкрементируем счетчик и проверяем не достиг ли он времени
		// проверки антидребезга, если достиг, то присваиваем кнопке статус
		// короткого нажатия.
		// Если сигнала нажатия нет, значит проверка антидребезга не прошла,
		// обнуляем счетчик времени и возвращаем статус кнопки в свободный.
		case KB_PREPRESSED:
			if (KeyRead(kb))
			{
				if (Keys[kb].time > 6)	// время обработки антидребезга вышло
					Keys[kb].state = KB_SPRESSED;
				else
					Keys[kb].time++;
			}
			else
			{
				Keys[kb].state = KB_FREE;
				Keys[kb].time = 0;
			}
			break;
		// если кнопка в состоянии короткого нажатия и есть сигнал нажатия -
		// инкрементируем счетчик времени и проверяем не достиг ли он времени
		// долгого нажатия, если достиг, то переводим статус кнопки в долгое
		// нажатие.
		// Если нет сигнала нажатия - значит кнопка была отпущена, ставим
		// ей статус "отпущена после короткого нажатия".
		case KB_SPRESSED:
			if (KeyRead(kb))
			{
				if (Keys[kb].time > 150)
				{
					Keys[kb].state = KB_LPRESSED;
				}
				else
					Keys[kb].time++;
			}
			else
			{
				Keys[kb].state = KB_SRELEASED;
				Keys[kb].time = 0;
			}
			break;
		// если кнопка в состоянии долгого нажатия и есть сигнал нажатия -
		// инкрементируем счетчик времени (это просто для легкой организации
		// автоповтора нажатий).
		// Если нет сигнала нажатия - значит кнопка была отпущена, ставим
		// ей статус "отпущена после долгого нажатия".
		case KB_LPRESSED:
			if (!KeyRead(kb))
			{
				Keys[kb].state = KB_LRELEASED;
				Keys[kb].time = 0;
			}
			else
				Keys[kb].time++;
			break;
	}

Этот код позволяет достаточно легко организовать и автоповтор нажатия с заданным интервалом - просто проверять значение счетчика времени при статусе кнопки KB_LPRESSED и если он достиг определенного значения - обнулять его и выполнять действия по очередному "нажатию" автоповтора.

Все реакции на события кнопок необходимо размещать в основной программе, а ни в коем случае не в прерывании. Просто в основном цикле (или где это нужно) проверяется текущий статус нужной кнопки и если он не "свободен" (KB_FREE) и не "обработан" (KB_WORKED), то идем выполнять полезный код, связанный с событием кнопки, после чего выставляем кнопке статус "обработан" (KB_WORKED). Этот статус сам сменится на "свободен" при ближайшем очередном вызове прерывания таймера с обработкой состояний кнопок.

По счетчику времени: нет нужды считать в нем миллисекунды или любые другие реальные временные величины. Достаточно считать вызовы прерывания таймера - они все равно следуют с определенным промежутком времени. Поэтому достаточно 1-байтового счетчика, который посчитает, скажем, 5 вызовов (с периодом 20 миллисекунд) вместо 100 миллисекунд для антидребезга. Или 50 вызовов вместо 1000 миллисекунд для долгого нажатия.

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity