- Подскажите как сейчас правильно организовать в микроконтроллере
программные таймеры? Peter_Mfk0(164 знаков, MCU, полностью, 23.10.2020 12:50)
- Подскажу еще один способ замеров интервалов времени. Без inc/dec
счетчиков. Для примера, ST HAL предоставляет время в ms посредством
функции HAL_GetTick(); Единожды запоминаем текущее время: static
uint32_t time_start = HAL_GetTick(); и далее в том месте где надо
проверить не вышло ли время, просто находим разницу между начальным
и текущим временем непосредственно в самом условии: if
(HAL_GetTick() RxTx(130 знаков, 25.10.2020 16:10 - 18:41)
- Вот так делаю. Удобно Tpoeшник(796 знаков, 25.10.2020 08:45 - 10:37)
- Раз уж дело дошло до типов, задам вопрос здесь(в этой ветке): а в
чем смысл писать std::uint32_t вместо просто uint32_t? - Constantin24(26.10.2020 08:05)
- INT16U и INT08U это наверно специально для выноса моска? - Vit(25.10.2020 09:00)
- Еще бы U8 и U16 можно было бы понять - VLLV(25.10.2020 10:41)
- Это для того чтоб не выписываться и чётче видеть важное. Где то
подсмотрел. - Tpoeшник(25.10.2020 10:27)
- Чем stdint.h не устраивает? - VLLV(25.10.2020 10:42)
- Еще компактнее будет сделать mbedder.h с понятиями u8, u16, u32,
u64 и s8, s16, s32 и s64. Для еще большей сестры таланта можно
вместо битовой длины залудить байтовую - u1, u2, u4, u8 и s1, s2,
s4, s8 :)) - MBedder(25.10.2020 10:48)
- Вот я тоже себе сделал u1, u2, u4, u8. Непонятно, кто и зачем
придумал uint32_t ? Ведь всё равно нету uint29_t, uint31_t и т.д.
Зачем тогда в 8 раз умножать? Ale3000(134 знаков, 27.10.2020 04:17)
- У меня global.h в котором: Tpoeшник(742 знаков, 26.10.2020 11:38)
- Вот в фортране как было удобно-то. Если переменная начинается на
"йоклмн" -- то целая, иначе вещественная. - fk0(25.10.2020 13:16)
- После того, как увидел, что компилятор ARM по разному компилирует
самопал и стдинт, больше самопал не использую. Неважно, что оба
варианта работают. - VLLV(25.10.2020 13:03)
- stdint - это ведь тоже самопал, набор typedef и #define. Кто мешает
сделать свое точно так же, а не через алиасы? - MBedder(25.10.2020 13:15 - 13:19)
- Что такое int_fast32_t я знаю будучи пьяным и разбуженным в 4 утра.
Что такое u8 -- не знаю, не уверен, ибо есть нюансы. Для
int_fast32_t есть INT_FAST32_MAX и PRIdFAST32 например, а для u8
что? Для именно u8 или i8 вообще интересно, это char, signed char
или unsigned char (кто не знает -- это ТРИ РАЗНЫХ типа). Можно для
всех библиотечных типов придумать свои алиасы, но читать такую
программу -- невозможно. Потом #define вместо typedef использовать
нельзя, т.к. у него fk0(809 знаков, 25.10.2020 14:58)
- Да никто не мешает, но лучше иметь возвожность свалить вину на
компиляторописателей, а не рвать волосы на ж. Опять таки,
кросс-платформенность уже реализована, меньше думать. - VLLV(25.10.2020 14:04)
- stdint - это Стандарт, заголовок, обязанный быть у каждого
компилятора - lloyd(25.10.2020 13:18)
- Заинтриговал. А какой вариант красивше скомпилировался-то? Может,
самопал надо было брать? - SciFi(25.10.2020 13:12)
- есть системный таймер uint32_t sysTimer_ms который инкрементируется
каждую 1мс. При необходимости можно любой добавить - 100мс, 1с,
1час. Потом для таймера завожу переменную uint32_t timer_n. Ну и
дальше просто: AVF(451 знаков, 25.10.2020 08:17)
- "Программный таймер" - это вырожденный случай оси, предоставляющей
сервис времени. =AK=(276 знаков, 24.10.2020 14:27, ссылка)
- Эх-хе-хе... Помницца, был здесь знатный срач по поводу 100500
канального ШИМ на АВР. - mse homjak(24.10.2020 00:17)
- Ответов много и все верный.. ну как же моих трех копеек ))... POV_(2655 знаков, 23.10.2020 19:43,
)
- Библиотека тут чрезмерна, заводишь несколько декрементных счетчиков
и всё. Счетчик это хорошо накатанная (шаблон, паттерн) конструкция
вида RxTx(362 знаков, 23.10.2020 19:37)
- только так и делаю. Оно ж (через 1 мсек) всё равно щелкает. А какая
там библиотека? Таймеры щелкают в прерывании systick/ - Лaгyнoв(23.10.2020 18:48)
- Как вариант - Evgeny_CD(23.10.2020 18:13, ссылка)
- Генерим прерывания от одного аппаратного таймера каждую
миллисекунду (наименьший общий квант). Делаем N софт-таймеров и
инициализируем их требуемыми значениями периодов в мс - 3, 25, 100,
60000. В 1-мс прерывании декрементируем каждый софт-таймер, и при
достижении нуля переинициализируем его прежним значением и
генерируем event, interrupt или что угодно. Это все - не благодари
:)) - MBedder(23.10.2020 16:29)
- напишу общий комментарий к выложенным примерам. Mahagam(389 знаков, 23.10.2020 16:25)
- Мое решение выглядит следующим образом: evgeniy1294(3490 знаков, 23.10.2020 15:57)
- Нужна очередь с приоритетом (priority queue), реализуется на
двоичной куче... Если таймеров буквально меньше десятка, то просто
односвязный список. В списке хранится абсолютное время
(относительно некой точки отсчёта, не важно какой), после которого
таймер должен сработать. Логика работы такая: fk0(1965 знаков, 23.10.2020 15:43 - 15:51, ссылка)
- Воистину, у погромистов мозги набекрень... ))) Из любой
элементарщины сделают "винду"... - my504(23.10.2020 16:42)
- Как-то сложно для микроконтроллеров. Легче вдуплить все таймеры в
массив, в прерывании отнять 1 от значения каждого софт-таймера и
если ноль вызвать калбек функцию (при её наличии) Boвa(141 знаков, 23.10.2020 15:48)
- Да ничего сложного, у меня на PIC18 работало. Попозже код напишу.
Вот куча (очередь) -- сложно и не знаю как тут проще (если таймеров
100 штук). - fk0(23.10.2020 15:52)
- Да в принципе можно и так как вы пишите, но вместо односвязного
списка - очередь упорядоченная по оставшемуся времени. Сортировка
по времени происходит в момент добавления события. В момент
обработки события событие выбрасывается, и головой очереди
становится следующее. НО если нужно сформировать какую-то циклическую последовательной
действий очень все это не красиво будет. - Boвa(23.10.2020 16:02)
- Проблема линейной очереди -- гигантское время вставки если в
очереди 6144 таймеров, например. Кроме того API прикладного уровня
может иметь, например, функцию остановки/отмены запущенного
таймера. Т.е. нужны операции: 1) вставки в очередь, 2) извлечение
из головы очереди, 3) удаление произвольного элемента. Бинарная
куча выглядит диковато и перетряхивает вообще всю память, но у ней
худшее время понятно. Есть вариант со скип-листами, но там удалить
физически нельзя, только fk0(427 знаков, 23.10.2020 20:49, ссылка)
- Какая еще библиотека? Вы не в состоянии написать инкремент
переменной со сравнением и сбросом? my504(493 знаков, 23.10.2020 13:51)
- Я могу ошибаться в рассуждениях. Peter_M(691 знаков, 23.10.2020 15:22)
- Системы с "тиком" -- не нужны, если это не time triggered
архитектура. См. мой ответ выше. Он даёт таймеры с минимальной
дискретностью (а не с тиками по 50мкс и сверхчастыми прерываниями).
Правильно, незачем вообще что-то инкрементировать. Поэтому вся
арифметика над абсолютным значением времени в будущем, а не над
временными интервалами (т.е. "проснуться когда время >=
13:00", а не "спать 3 часа"). Равно как и незачем за раз
обрабатывать более одного таймера, если их fk0(23 знаков, 23.10.2020 15:49)
- Какая точность нужна для выдержек времени? Обычно программные
таймеры не требуют шести знаков точности. Исходя из потребной
точности/разрешения следует выбрать максимальный интервал
аппаратных прерываний. Если не инкрементировать частные таймеры, то
придется сохранять стартовые значения софтовых таймеров и выполнять
математику сравнения с единым таймером. Оно зачем? Никакой экономии
не будет. Сплошная путаница. А так, назначили пересчет, сбросили
тело таймера в коде (тело my504(109 знаков, 23.10.2020 15:45)
- у меня подобное реализовано на регистрах сравнения таймера, также
можно устанавливать произвольные значения , при установке считываем
текущее значение счетчика , добавляем новое время, грузим в
свободный регистр сравнения, в таблицу кладем указатель на функцию
которую нужно ввызвать по таймауту! все работает аппаратное и не
жрет ресурсов! На 3 аппаратных таймера stm32 выходит 12 независимых
счетчиков - Aleksey_75(23.10.2020 15:36)
- а что за контроллер ? мож использовать регистры сравнения таймера? - Aleksey_75(23.10.2020 13:26)
- Обычно не нужно строго выдерживать период, достаточно "в следующий
раз через N мс или чуть позже". В этом случае удобно вот так: SciFi(424 знаков, 23.10.2020 13:15)
- При наличии полноценного компилятора не при чём (не хуже чем 16 бит). Но как правило с этим проблемы. Для всех кроме AVR у многих до сих пор C89 не в полном объёме... Со стандартной библиотекой (не работающие printf, ага) тоже плохо. Дело конечно fk0(2884 знаков, 28.02.2020 00:09)
- Выводы контроллера всегда управляются в контексте управления каким-либо более крупным аппаратным ресурсом. I2C-шиной, например. Вот в классе, функции, модуле управляющем шиной и не зазорно будет напрямую записать в GPIO регистр и подёргать за fk0(2049 знаков, 17.12.2019 12:06)
- Железо нужно симулировать не на уровне битов и фронтов сигналов, а на уровне высокоуровневых операций (например, чтение-запись блоков данных в EEPROM делается через функцию HAL)... fk0(3835 знаков, 07.11.2019 12:59)
- От проекта зависит. Насколько чётко выделена аппаратно-зависимая часть и насколько абстракции используемые в старом проекте реализуемы в новом. В 3 недели можно "HAL" не успеть сделать отладить (уарты, таймеры и т.п.) Собственно с этого и нужно fk0(1000 знаков, 24.05.2019 11:48)
- Собственно можно код запускать в эмуляторе процессора (qemu), которому привязать симуляцию нужной аппаратуры, или заменить HAL на вызов функций на ПК (где будет эмулироваться железо на каком-то уровне). - fk0(06.02.2019 00:05)
- Когда ПО прибора запускается на обычном ПК. Для этого обычно ПО разделяется на два слоя, как минимум: платформо-независимый (большая часть, условно 90%) и уровнь абстракции (HAL, 10%). Последний отдельно реализуется для МК и для ПК (где fk0(1984 знаков, 23.05.2018 10:19)
- Одни абстракции заменяются на другие, которые тоже нужно учить, документировать и запоминать, учитывать возможные побочные эффекты. Всё превращается в bloatware. Не нужно плодить лишних сущностей, сверх необходимого. Должен быть один слой HAL и в fk0(475 знаков, 23.07.2015 10:52, ссылка)
- Жалкая паделка финских студентов написана на 100% на C, из ассемблера только вектора прерываний, crt и ещё мелочи, в C30 v3.31. Это фуфлыжный и никому не нужный жалкий приборишко, работаю в подвале. GPS приёмник только один, измерять нечего, fk0(4559 знаков, 10.04.2014 02:07 - 02:15)
- В Кортексах/gcc для контроля границы кучи при вызове malloc достаточно отрихтовать _sbrk(). У вас не так? - amusin(10.04.2014 18:48)
- офигеть. сложность задач впечатляет, что у тебя что у Мбеддера. У мну все гораздо скромнее на пик24 abivan(674 знаков, 10.04.2014 10:45 - 15:17, ссылка)
- истинный программист. программирование ради программирования. всё это рожно при вынужденной смене архитектуры придётся отправить в dev/null. трэш угар и содомия. - Mahagam(10.04.2014 14:43)
- Респект и уважуха. Мне еще учиться и учиться - у меня цикл сборки настолько примитивен, что даже стыдно говорить: нажал кнопку Make, дождался сборки и автопрошивки - и смотрю на обновленный экранчик дисплея :)) MBedder(255 знаков, 10.04.2014 08:33 - 11:59)
- твоё? Snaky(41 знаков, 10.04.2014 07:19, картинка)
- :)) - MBedder(10.04.2014 08:16)
- Коллеги, Ваше обсуждение начинает мне напоминать анекдот про маяк -> - Evgeny_CD(10.04.2014 02:44 - 03:11, ссылка)
- Да, трэш угар и содомия. Иногда абстракции через край, поэтому я имею такое мнение, что иногда и не грех в исходники прямо вписать чуть ли не адрес регистра, ну и уж номер бита так точно. Только чем поможет собственно битовое поле? Формально fk0(1124 знаков, 29.12.2013 23:12)
- Не совсем. Над HAL может быть ещё один слой, уже нужный для совмещения разных программных интерфейсов. Т.е. есть модуль A, который, потенциально может работать с модулем B или модулем C. Как быть? Вариант первый: в проект можно включить либо fk0(510 знаков, 25.10.2013 16:28)
- Полезны аж 3 прослойки (ассемблеристам дальше лучше не читать): fk0(1812 знаков, 13.10.2011 19:56)