Перейти к содержанию

Не Работает Задержка В Прерываниях


user437

Рекомендуемые сообщения

Здравствуйте. Почему-то не работает HAL_Deley в прерываниях по нажатию кнопки.:

void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_14, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_13|GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(1000);
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}

По нажатию кнопки вместо всех этих действий - ничего не происходит и по истечению времени к основной программе не возвращается.

Если организовать задержку через for, то все нормально срабатывает.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Весь код можно увидеть?

ЗЫ

Чтобы функция HAL_Delay() работала в обработчиках других прерываний, требуется чтобы приоритет этих прерываний был меньше, чем у SysTick.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Весь код можно увидеть?

ЗЫ

Чтобы функция HAL_Delay() работала в обработчиках других прерываний, требуется чтобы приоритет этих прерываний был меньше, чем у SysTick.

Т.е. в кубе где я активировал прерывание - там надо выставить высокий приоритет? Какой можете подсказать?

У меня прерывания по нажатию кнопки, происходят.

Код из main.c что-ли?

Вот:

HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(500);

Изменено пользователем user437
Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Кусок с нициализацией интересует.

Прерывания от пина 0 надо в самый низкий, либо прерывания системного таймера в самый высокий

Так там 0 итак был изначально.

Я инициализацию вообще не трогал и ничего не добавлял.

Я прописал только то, что вам сюда отправил.

Я недавно начал только изучать это. Вот это вас интересует?:

static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct;
 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 /*Configure GPIO pin : PA0 */
 GPIO_InitStruct.Pin = GPIO_PIN_0;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 /*Configure GPIO pins : PD12 PD13 PD14 PD15 */
 GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
 /* EXTI interrupt init*/
 HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

Инициализация выводов.

Ссылка на комментарий
Поделиться на другие сайты

ваше прерывание будет выполняться 6 секунд. Вы в своем уме вообще?

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

А если действительно надо было бы по нажатию кнопки выполнить такую 6-секундную процедуру ?

Вот мой вариант:

1) сработало прерывание по кнопке.

- потушили светодиоды на ногах 12, 13,14,15. Ну, вот это: HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

- создали вспомогательную переменную, которая будет считать эти 6 циклов, присвоили переменной значение "0".

- Запустили таймер на 1000 мс

- вышли из прерывания.

2) сработало прерывание от таймера после 1000 мс.

- проверяем, что вспомогательная переменная меньше 6.

- выполняем команду HAL_GPIO_TOGGLE, ну или как там.

- инкрементируем вспомогательную переменную на 1.

- Запустили таймер на 1000 мс.

- вышли из прерывания.

Изменено пользователем Добрячок
Ссылка на комментарий
Поделиться на другие сайты

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

Но и это не оптимальный подход.

Оптимально - запилить CMSIS OS и из прерывания послать потоку сообщение OSMessage

Примерно так (процедура выполнения)

void StartBEEPtask(void const * argument)
{
osEvent event;
for(;
{
const uint8_t Beep_length = 20;
const uint8_t Beep_pause = 60;
event = osSignalWait(0x0001|0x0002, osWaitForever);
if (event.value.signals == 0x0001)
{
BEEP_ON;
osDelay(Beep_length);
BEEP_OFF;
}
if (event.value.signals == 0x0002)
{
BEEP_ON;
osDelay(Beep_length);
BEEP_OFF;
osDelay(Beep_pause);
BEEP_ON;
osDelay(Beep_length);
BEEP_OFF;
}
event.value.signals = 0;
taskYIELD();
}
}

Инициатор

if (Keyboard.Mode.event && !MAIN_DATA.onoff_state)
{
Keyboard.Mode.event =0;
osSignalSet(BEEP_TaskHandle, 0x0001);
}

Поясню

В этом коде процедура выполнения останавливается на функции event = osSignalWait(0x0001|0x0002, osWaitForever); и ничего не делает, пока для этойго потока не поступит соответствующее сообщение от ОС. Таких собщений может быть максимум 32 с кодами от 0 до 32 соответственно.

Как только из любого места (в том числе и прерывания) отправляется сообщение (сигнал) osSignalSet(BEEP_TaskHandle, 0x0001); тут же начинается выполнение кода потока. if распознает сигнал и делает то что положено делать именно по этому сигналу (одинарный бип или двойной). Как только поток завершен он передает управление ОС. На самом деле он передает его ОС-ке много раз по каждому вызову osDelay(Beep_length);

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

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

ваше прерывание будет выполняться 6 секунд. Вы в своем уме вообще?

Ну мне для эксперемента)

Так это не работает почему? В прерываниях нельзя просто использовать задержки подобным образом и если они нужны точными, то делать как посоветовали выше - через таймер?

Ссылка на комментарий
Поделиться на другие сайты

прерывания одного приоритета не могут вызываться одновременно. Вам уже вроде как объясняли, но по моему это бесполезно

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

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

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

А если до или после этого есть другие Ифы, которые точно также ждут флага из других прерываний ? Тогда получится, что "то самое" прерывание может отработаться только после того, как другие прерывания обработались. Причем, даже если у "того самого" прерывания высокий приоритет, то это ничего не изменит, ибо основной цикл дойдет до "того самого" флага все равно не раньше и не позже обычного.

Ссылка на комментарий
Поделиться на другие сайты

Вы задаете правильные вопросы.

Все это называется диспетчеризацией приложения. Вот для этого случая как раз и созданы операционные системы реального времени. И к радости СТМ-щиков для этого камня они не представляют сколь нибудь весомой нагрузки, а пользы от них дохрена. РТОС средней конфигурации отъедает всего 6К флеша и гдето столько же ОЗУ, но пользы при этом гораздо больше.

Итак - у нас есть одно прерывание и несколько процессов которые ждут этого прерывания. Как же нам запустить их одновременно? А никак. Потому как ядро у нас одно и выполняться всегда может только одна задача. Поэтому можно запустить все это дело только псевдоодновременно. И это пока лучшее на что можно надеяться на одноядерной машине.

Как это делается?

Вместо блоков if в операционке создаются задачи. Задачи эти управляются диспетчером задач. Пока задаче делать нечего, она остановлена, либо выполняется с определенной периодичностью если нужно программисту (в том числе и тогда, когда в задаче возникает задержка типа Delay). Это делается просто - в ожидании события указывается таймаут, и если за это время событие не произошло задача один раз прогоняется принудительно. Пример - рефреш экрана. Если данные на экране не меняются, то и обновлять нечего, а событие изменения данных на экране вызывает обновление экрана. Для TFT это ощутимый по времени процесс.

Инициирует старт задачи сообщение операционной системе, что произошло прерывание. Это сообщение собственно в обработчике и отправляется. Как именно решает программист. Будет это просто событие (event), сообщение (message), или некоторые данные в очереди. Как только ОС получает сообщение, она запускает на выполнение те потоки, которые ждут этого сообщения (прописывается в теле задачи которая ждет). И дальше диспетчер начинает вызывать эти задачи и запускать в порядке приоритета, при этом распределяя между ними процессорное время. Но не стоит думать что при этом каждая задача получит лишь кратное количество процессорного времени. Каждая из них получит 100% производительности ядра в тот момент, когда задаче это потребуется, если в задачах много задержек. Потому что как только в задаче появляется задержка, диспетчер бросает ее и переходит к задаче у которой есть полезные дела, а эту отставляет в сторонку до конца задержки.

Но это очень примитивное описание довольно мощного инструмента, который руками вы запаритесь писать, если делать это с нуля. Поэтому восхвалим кодеров создавших FreeRTOS!

и почитаем отличную мануалку про нее http://microsin.net/...rtos-part1.html

изучив этот документ я уже через 3 дня нацарапал свой первый код под РТОС. Там все удивительно просто, главное не бояться

Для пользователей куба дополнительно читать еще надо про CMSIS OS. Это обертка для FreeRTOS и на мой взгляд вполне удобная. Куб генерирует именно CMSIS OS код, хотя и фришные либы тоже включает и они работают.

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

то процедура обработки прерывания начнется не тогда, когда случилось прерывание, а когда основной цикл дойдет до соответствующего Ифа

Чушь. Смысл прерывания как раз в том, что основной код прерывается и обработка переходит прерыванию. Не сразу прерывание выполнится, только если уже выполняется более приоритетное прерывание.

Ссылка на комментарий
Поделиться на другие сайты

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

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

  • 5 месяцев спустя...

человек спросил одно - ему ответили про другое. замечательно!!! эксперты!

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

а человек спрашивал почему одно прерывание не перебивает другое. и от того, что он новенький его вопрос нельзя трактовать глупым!

ведь действительно если выставить через HAL приоритет SysTick в 0 а приоритет внешнего прерывания например 4 то в SysTick считать в прерывании не будет пока не выйдет из обработчика внешнего прерывания.

ну а если обновить HAL то работает :rolleyes:

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Актуальная потребность) Тоже развлекался подобным способом, только с немного другим ибп. Хотел перевести его на железофосфат, но он до конца не заряжал батарею. Блок зарядки у него не калибровался, и по моему с микроконтроллером. В итоге оставил свинец. Когда то он тянул серверную на 4х батарейках по 200а/ч. Серверную он вытянул за ночь, а вот из за отсутствия охлаждегия все пошло в разнос. В итоге все закончилось полной заменой силовой комплектухи и устранением лишних отверстий в плате. Но картошку хватило сварить и даже немного поработать, зимой на железофосфате 4 часа отапливал тепловентилятором балкон)). Дешевле чем из розетки днем)) А для ленивых( ну или если в лом или нет достойного донора) можно взять инвертор от SVC он довольно не дорогой и мощный, при этом может работать с авто батарейками, зарядный ток до 10А. Я на нем гоняю насосы котла и кондиционер в шкафу, иногда еще станок.  
    • @Александр2, это у тебя в голове что-то с чем-то вступает в противоречие.  Я знаю, что ты ярый поклонник Ланзара. Поэтому пояснение для тебя того, почему симметричная на бумаге/на экране монитора схема, и спаянная на реальной плате с реальными комплектующими в отличии от неё за редким исключением вместо 0 на выходе зачастую имеет сдвиг напряжения величиной в +/- километр, думается мне излишняя трата времени.    
    • Верно подмечено. Вот их-то, КТ602ВМ и BD139 в ТО-126 в 1969-ом как раз-таки и не было. Не только у J. L. Hood-а, их вообще ещё не существовало. К тому же КТ602БМ  в корпусе КТ-27-2 (как и BD139 в TO-126) и КТ602А в корпусе КТЮ-3-9 - это совсем не близнецы-братья. Технология изготовления совершенно разная, а она при работе транзисторов динамическом режиме, как в случае с JLH-69, играет далеко не последнюю роль. Просто юноша в силу своего быстрого и раннего развития об этом ничего не знает. 
    • Садится разбираться в алгоритме работы и на микроконтроллере делать замену.  Попробуйте прогреть микросхему на зажигалке, когда-то читал о таком способе восстановления процессора от телевизора. Шансов мало, но вам нечего терять, а потом в панельку.
    • Я хочу попробовать разные способы победить эти шумы. Для начала собрать фильтр для блока питания. Корпус с блютуз антенной я пробовал убрать, ничего не изменилось, если фильтр для блока питания тоже не поможет, значит дело в самом усилителе. В Aiyima A3001, который выдает шум гораздо тише, на выходе стоят электролитические конденсаторы и фильтры, можно попробовать сделать также и на Aiyima A09, может таким образом удастся снизить шумы. Если нет, то буду искать еще варианты. Кроме шумов еще надо разобраться с щелчками в колонки при включении и выключении Brzhifi. Aiyima A09 выдает щелчок только при выключении сетевого фильтра, и слабый. А вот Brzhifi щелкает так, что аж диффузоры в колонках двигаются. Схема питания у них отличается, Brzhifi остается в режиме ожидания и питание не отключается, я хочу переделать его так, чтобы оно отключалось, как на Aiyima A09. Может там что сдохло. а может он так спроектирован. Либо что то делать с контроллером питания, либо найти в схеме где можно врезать выключатель и впихнуть его.
    • @CrazyDog34RU Понять, что изначально были неправы, и питание в вашей проблеме не виновато, например?
    • Неожиданный вопрос... При измерениях в любой точке вот этой части схемы "масса" осциллографа вот тут: При измерениях вот в этой части схемы - вот тут: У этой части схемы - вот в этой точке: Подключать "массу" к одной части схемы, а смотреть точки в другой - нельзя. Все эти три "общие" точки - совершенно разные точки. Между ними может быть вполне ощутимое напряжение. Вот тут это хорошо видно:
×
×
  • Создать...