Plexus
Aug 29 2014, 09:10
Требуется помошь в поиске проблемы.
Непроизвольно срабатывает прерывание
EXTI0_IRQHandler().
Нога подтянута к 3.3В резистором. И на нее подается импульс.
Прерывание должно срабатывать по спаду. И срабатывает. Но время от времени, в обработчик залетает и выполняется проверка на EXTI_GetITStatus(EXTI_Line0). Импульсы в этот момент не поступают (слежу на осцилле).
Что за магия такая?
CODE
void init_EXTI()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void init_NVIC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
RCC_Configuration();
init_timer();
init_EXTI();
init_NVIC();
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_DisableIRQ(TIM6_DAC_IRQn);
while(1);
}
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line0);
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
TIM_SetCounter(TIM6, 0);
if (flag)
{
flag = 0;
NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
}
}
Цитата(Plexus @ Aug 29 2014, 13:10)

Импульсы в этот момент не поступают (слежу на осцилле).
А на GPIO 0 port B, С, D что происходит?У меня все нормально работает, только у меня нет работы с TIM6 и приоритеты стоят не 0x0f, а 3...
Plexus
Aug 29 2014, 10:43
Цитата(Ant_m @ Aug 29 2014, 16:45)

А на GPIO 0 port B, С, D что происходит?
Ничего. Я использую STM32VLDiscovery. Единственное, я удалил из вышепреведенного кода настройку таймера и настройку светодиодов на PC8 и PC9.
Срабатывание происходит само по себе, когда плата лежит и ее никто не касается.
Порт был настроен так:
Код
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_WriteBit(GPIOC, GPIO_Pin_8 | GPIO_Pin_9, Bit_SET);
Это же не значит, что ошибка в том, что я указал
GPIO_Pin_8 | GPIO_Pin_9 вместо
GPIO_Pin_All?
Golikov A.
Aug 29 2014, 11:51
это ваще может значить черти что, куча народу нарывалось на то что эти дурные функции делали что хотели а не что надо.
там через раз срабатывает вот это GPIO_Pin_8 | GPIO_Pin_9;
иногда биты настройки одного пина и второго находятся в разных регистрах и в этом случае такое вызывает ваще непредсказуемые результаты. надо проверить состояние регистров, как они настроились. А лучше настроить их ручками
Plexus
Aug 30 2014, 05:01
Т.е. достаточно настроить все GPIO и проблема пропадет?
Кто еще сталкивался с этой проблемой? Если есть ссылки на топики - поделитесь, пожалуйста.
Golikov A.
Aug 30 2014, 05:55
где то краем ухо я слышал про ложные срабатывания прерываний, этим грешили процы от ST,
вот типа
http://electronix.ru/forum/index.php?showt...%E2%E0%ED%E8%E5и в других контекстах слышал.
эта тема про UART, про пины вроде тоже проходило где то...
Другое дело что надо сначала все верно настроить, чтобы в регистрах было то что надо, а не дергая странные индуские функции. Многие из них очень плохо написаны. И только потом уже верить в ложное срабатывание.
adnega
Aug 30 2014, 08:57
Цитата(Golikov A. @ Aug 30 2014, 09:55)

где то краем ухо я слышал про ложные срабатывания прерываний, этим грешили процы от ST,
Правильнее называть те прерывания "повторными". Это, скорее, грех Cortex-M, чем ST.
Plexus
Aug 30 2014, 09:56
Цитата(adnega @ Aug 30 2014, 15:57)

Правильнее называть те прерывания "повторными". Это, скорее, грех Cortex-M, чем ST.
Хорошо. А этого можно как-то избежать? Это лечится? Как другие разработчики решали подобные проблемы?
adnega
Aug 30 2014, 10:16
Цитата(Plexus @ Aug 30 2014, 13:56)

Хорошо. А этого можно как-то избежать? Это лечится? Как другие разработчики решали подобные проблемы?
Это не ваш случай.
Попробуйте ногу посадить железно на 3.3В. Попробуйте настроить EXTI на другой вывод. Если и в этом случае будут вызовы, то ищем в одном месте, если пропадут, то в другом, например, в ES
Цитата
A low-amplitude voltage glitch may be generated (on ADC input 0) on the PA0 pin, when the
ADC is converting with injection trigger. It is generated by internal coupling and
synchronized to the beginning and the end of the injection sequence, whatever the
channel(s) to be converted.
Кста, уSTM32VLDiscovery на PA0 сидит кнопка. Если вы имеете дребезг по нажатию/отпусканию кнопки, то это третий случай.
Plexus
Aug 30 2014, 10:24
Цитата(adnega @ Aug 30 2014, 17:16)

Это не ваш случай.
Попробуйте ногу посадить железно на 3.3В. Попробуйте настроить EXTI на другой вывод. Если и в этом случае будут вызовы, то ищем в одном месте, если пропадут, то в другом, например, в ES
Кста, уSTM32VLDiscovery на PA0 сидит кнопка. Если вы имеете дребезг по нажатию/отпусканию кнопки, то это третий случай.
Зачем сажать на 3.3В? У меня и так подтяжка железно через резистор на 3.3В, а не программно. Что вы имеете в виду?
Буду на другом выводе юзать, но я должен быть уверен, что все работает как часы. А ждать самопроизвольного срабатывания - очень долго. Не всегда ж срабатывает.
Дребезг исключен 100%. Проверка и на осцилле была и физически дребезг исключен. Подключение через транзистор на землю.
Golikov A.
Aug 30 2014, 14:16
самое правильное, при прерывании проверять флаг, что именно от этой ноги все получилось, иначе игнорировать прерывание. Если это правда беда кортекса-М, но что-то тьфу тьфу тьфу на лпц не замечал такого....
AHTOXA
Aug 30 2014, 14:41
Цитата(adnega @ Aug 30 2014, 14:57)

Правильнее называть те прерывания "повторными". Это, скорее, грех Cortex-M, чем ST.
Не, spurious - это как раз "ложные". Они не обязательно повторные, просто прерывание без причины.
Цитата(Golikov A. @ Aug 30 2014, 20:16)

самое правильное, при прерывании проверять флаг, что именно от этой ноги все получилось, иначе игнорировать прерывание.
Вот именно.
Цитата(Golikov A. @ Aug 30 2014, 20:16)

но что-то тьфу тьфу тьфу на лпц не замечал такого....
Гы.
AN10414 Handling of spurious interrupts in the LPC2000
Golikov A.
Aug 30 2014, 15:06
ну он же не кортекс-м...
Можно в 2 словах откуда они рождаются? Я как то не искушен в этом вопросе, думал это чисто СТ косяк, а выходит все же нет, че почитать?
UPD. А нашел, в приведенном же документе есть причина их возникновения. Но что-то получается что это не для любой периферии возможно и причина в конвейере, то есть фактически на самом деле прерывание было, просто пока конвейер чистился оно исчезло. Но такое не возможно для GPIO прерываний, или возможно?
Как оно все рождается то?
adnega
Aug 30 2014, 15:53
Цитата(Golikov A. @ Aug 30 2014, 19:06)

ну он же не кортекс-м...
Согласен. У кортексов и контроллер прерываний совсем другой. Про ложные срабатывания (даже на STM32) ничего не слышал за более чем 4 года использования в серийном производстве (~ 100 изделий в месяц) на STM32F100/103/107/407.
Plexus
Aug 30 2014, 18:41
Цитата(Golikov A. @ Aug 30 2014, 21:16)

самое правильное, при прерывании проверять флаг, что именно от этой ноги все получилось, иначе игнорировать прерывание. Если это правда беда кортекса-М, но что-то тьфу тьфу тьфу на лпц не замечал такого....
А какой именно флаг проверять? Разве в моем коде обработчик не полный?
AHTOXA
Aug 30 2014, 19:11
Цитата(Golikov A. @ Aug 30 2014, 21:06)

ну он же не кортекс-м...
Ну так spurious interrupt - это не кортексо-специфическая штука. Откуда рождается - вопрос сложный, покрытый мраком

Возможно, что очень сложный контроллер прерываний, и не всегда всё успевает сбрасываться. Возможно ещё что-то. Главное, что жить это не мешает.
Цитата(adnega @ Aug 30 2014, 21:53)

Согласен. У кортексов и контроллер прерываний совсем другой. Про ложные срабатывания (даже на STM32) ничего не слышал за более чем 4 года использования в серийном производстве (~ 100 изделий в месяц) на STM32F100/103/107/407.
Погуглите "spurious interrupt stm32", найдёте изрядно примеров. К тому же, если у вас в процедурах обработчиков прерывания есть проверка флага прерывания на входе, то вы это ложное прерывание никак и не заметите. Особенно в производстве

Цитата(Plexus @ Aug 31 2014, 00:41)

А какой именно флаг проверять? Разве в моем коде обработчик не полный?
У вас всё правильно, так и надо.
adnega
Aug 30 2014, 19:22
Цитата(AHTOXA @ Aug 30 2014, 23:11)

Погуглите "spurious interrupt stm32", найдёте изрядно примеров. К тому же, если у вас в процедурах обработчиков прерывания есть проверка флага прерывания на входе, то вы это ложное прерывание никак и не заметите.
Флаги на входе конечно же обрабатываю. Я знаю как минимум два источника "ложных" прерываний:
1. Не сброшены флаги отложенных прерываний в NVIC и/или периферийного модуля при разрешении прерывания от этого модуля;
2. Очистка бита запроса прерывания от периферийного модуля в самом конце обработчика прерывания от этого модуля.
ST в этих случаях совершенно ни при чем, и косяк целиком программиста.
В то, что прерывание может само по себе возникнуть - не верю. Ибо для всех неиспользуемых прерываний у меня заглушка, и я ни разу в нее не влетал.
Или речь идет только о разрешенных прерываниях?
Golikov A.
Aug 30 2014, 19:42
о разрешенных конечно, иначе это была бы мощная бага.
Я так понял их описания есть такой расклад, на примере UART идут данные, возникает прерывание что пришел байт, но сразу мы в прерывание не попадаем, сначала конвейер должен доработать, и если в конвейере будут команды запрета прерывания то будет флаг, когда его быть не может. Или если будут какие то ошибки за такты конвейера то возникнет другое прерывание, но первое возникшее все равно убдет отработано.
Вообще как то мутно написано%(... хорошо бы чтобы кто на пальцах объяснил...
AHTOXA
Aug 30 2014, 21:30
Цитата(adnega @ Aug 31 2014, 01:22)

Флаги на входе конечно же обрабатываю.
Тогда вы ничего не можете утверждать наверняка

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

Цитата(adnega @ Aug 31 2014, 01:22)

Я знаю как минимум два источника "ложных" прерываний:
Да, эти два вида конечно наиболее распространены. Но есть и другие.
Лично сталкивался с возникновением прерывания от DMA при отключении канала в F4. Вот
аналогичный случай. Наверняка есть ещё (не зря же
во всех примерах от ST
во всех обработчиках прерываний стоят проверки флагов, даже когда источник прерывания гарантированно один-единственный). Смысла копать глубже не вижу, проверка флагов решает проблему.
ЗЫ. Речь конечно только о разрешённых прерываниях.
Plexus
Aug 31 2014, 06:09
Цитата(AHTOXA @ Aug 31 2014, 02:11)

У вас всё правильно, так и надо.
Так дело в том, что эта проверка в прерывании и проходит.
Код
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
Самопроизвольно выполняется это условие.
Если цеплять купюроприемник и в обработчике прерывания инкрементировать каждый импульс (сумму денег), то через некоторое время самопроизвольно отработает обработчик прерывания, и приплюсуется лишняя сумма денег. Как быть?
Golikov A.
Aug 31 2014, 06:18
а полингом проверить состояние пина нельзя? Кстати а сумму откуда узнаете или этот девайс сумму импульсами сообщает? Может правильнее этот импульс повесить на таймер, счетчиком, пусть в железе само считается чего на прерывания то реагировать?
кстати про сброс прерывания в самом конце,насколько в конце? Прям последняя команда? Я так понимаю это вариант когда флаг не успевает сброситься до выхода? Сколько команд сбрасывается флаг?
Plexus
Aug 31 2014, 06:26
Цитата(Golikov A. @ Aug 31 2014, 13:18)

а полингом проверить состояние пина нельзя? Кстати а сумму откуда узнаете или этот девайс сумму импульсами сообщает? Может правильнее этот импульс повесить на таймер, счетчиком, пусть в железе само считается чего на прерывания то реагировать?
Закидываешь 50 руб - 5 импульсов, 100 руб - 10 импульсов, и т.д.
Ширина импульса 50 мс. В обычном состоянии логическая "1". Поэтому настроил прерывание на спад.
Я так понял, можно эти импульсы как-то таймерам продвинутыми считать? Я не смог пример найти.
adnega
Aug 31 2014, 06:31
Цитата(Plexus @ Aug 31 2014, 10:09)

Если цеплять купюроприемник и в обработчике прерывания инкрементировать каждый импульс (сумму денег), то через некоторое время самопроизвольно отработает обработчик прерывания, и приплюсуется лишняя сумма денег. Как быть?
Либо опросом с защитой от дребезга, либо выбрать купюроприемник с управлением по RS232.
Я импульсы от купюро/монетоприемников делал опросом - там скорость импульсов совсем никакая.
Потом перешли на управление по RS232, ибо 5000 купюра очень на долго парализует аппарат.
Цитата(Golikov A. @ Aug 31 2014, 10:18)

кстати про сброс прерывания в самом конце,насколько в конце? Прям последняя команда? Я так понимаю это вариант когда флаг не успевает сброситься до выхода? Сколько команд сбрасывается флаг?
Флаг в периферийном модуле сбрасывается мгновенно, но пока реакция дойдет до NVIC... может не успеть до выхода из прерывания, и NVIC после выхода тут же попадает в прерывание снова.
Plexus
Aug 31 2014, 06:43
Цитата(adnega @ Aug 31 2014, 13:31)

Либо опросом с защитой от дребезга, либо выбрать купюроприемник с управлением по RS232.
Я импульсы от купюро/монетоприемников делал опросом - там скорость импульсов совсем никакая.
Потом перешли на управление по RS232, ибо 5000 купюра очень на долго парализует аппарат.
Дребезг исключен - проверяли на осциллографе. А с 5000 купюрой действительно долго )
adnega
Aug 31 2014, 06:58
Цитата(Plexus @ Aug 31 2014, 10:43)

Дребезг исключен - проверяли на осциллографе. А с 5000 купюрой действительно долго )
Смотря что считать дребезгом...
Если вместо 50мс импульса придет 30 мс?!
Мы в свое время решили так: если контроль ослабить, то будут лишние импульсы - пользователь получает лишние услуги и, естественно, не будет об этом сообщать и тем более оплачивать. Если контроль за импульсами усилить, то некоторые импульсы пропадут - пользователь это заметит и сообщит администратору - администратор решит вопрос. Правда, у нас особенность - музыкальные аппараты в барах и т.п. - т.е. администратор есть, услуга в виде проигрывания песни, т.е. убыток не настоящий. Другое дело платежные терминалы.
AHTOXA
Aug 31 2014, 08:04
Цитата(Plexus @ Aug 31 2014, 12:09)

Так дело в том, что эта проверка в прерывании и проходит.
Код
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
Самопроизвольно выполняется это условие.
А, вон оно что... Тогда это не spurious. Если дребезг точно исключён, то, скорее всего, не успевает сброситься флаг прерывания до выхода из обработчика.
Вставьте строчку
Код
__DSB();
после очистки флага прерывания, всё должно пройти.
adnega
Aug 31 2014, 09:51
А мне очень не нравится эта строчка
Цитата
if (flag)
{
flag = 0;
NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
Зачем дергать NVIC (причем не правильно), когда лучше разрешать/запрещать прерывание в периферийном модуле (в данном случае TIM6 или DAC)?
Причем, обязательно сбросить флаг запроса прерывания, если он взведен, иначе тут же улетим в обработчик.
Golikov A.
Aug 31 2014, 11:16
Цитата
Флаг в периферийном модуле сбрасывается мгновенно, но пока реакция дойдет до NVIC... может не успеть до выхода из прерывания, и NVIC после выхода тут же попадает в прерывание снова.
ну это сено-солома

Сколько тактов, нет таких данных? насколько от конца функции надо отодвигать сброс флага?
А если функция как заглушка только и сбрасывает флаг, надо нопов напихать или барьер какой что ли, типа __DSB();?
Цитата
Закидываешь 50 руб - 5 импульсов, 100 руб - 10 импульсов, и т.д
ну так импульсы надо считать не прерыванием, а таймером. Берете таймер, и эти импулсы заводите как его клок (там есть много режимов, можно выбрать). Делаете счетчик вперед. Если появляются импульсы, таймер считает. Время от времени проверяете что он насчитал, что насчитал запоминаете, таймер сбрасываете. как то так
adnega
Aug 31 2014, 13:01
Цитата(Golikov A. @ Aug 31 2014, 15:16)

ну это сено-солома

Сколько тактов, нет таких данных? насколько от конца функции надо отодвигать сброс флага?
А если функция как заглушка только и сбрасывает флаг, надо нопов напихать или барьер какой что ли, типа __DSB();?
Ага, барьера хватает.
Цитата(Golikov A. @ Aug 31 2014, 15:16)

ну так импульсы надо считать не прерыванием, а таймером. Берете таймер, и эти импулсы заводите как его клок (там есть много режимов, можно выбрать). Делаете счетчик вперед. Если появляются импульсы, таймер считает. Время от времени проверяете что он насчитал, что насчитал запоминаете, таймер сбрасываете. как то так
Вообще не гуд. Лучше уж EXTI. В момент сброса таймера может появиться импульс от купюрника. Проверять нужно периодически -- еще один таймер.
И опять же, это решение, не учитывающее форму импульса и его тайминги. Импульсная помеха легко может добавить сотню-другую денег на счет.
Plexus
Aug 31 2014, 15:07
Цитата(AHTOXA @ Aug 31 2014, 15:04)

А, вон оно что... Тогда это не spurious. Если дребезг точно исключён, то, скорее всего, не успевает сброситься флаг прерывания до выхода из обработчика.
Вставьте строчку
Код
__DSB();
после очистки флага прерывания, всё должно пройти.
Та функция вызывается непроизвольно не сразу после ее правильного вызова, т.е. проходит минут 5 и только после этого вызывается непроизвольно. Неужели флаг не успевает сброситься за 5 минут? )
Golikov A.
Aug 31 2014, 17:04
мне кажется у вас все таки проходит какая - то помеха. Может не нога дергается, а земля к примеру прыгает. Или что-то типа того. В общем думаю если оно стоит стоит и вдруг опа прерывание, то это скорее всего на ноге что-то было, нежели какой-то могучий глюк проца...
Цитата
Вообще не гуд. Лучше уж EXTI. В момент сброса таймера может появиться импульс от купюрника. Проверять нужно периодически -- еще один таймер.
И опять же, это решение, не учитывающее форму импульса и его тайминги. Импульсная помеха легко может добавить сотню-другую денег на счет.
из существенных только последний аргумент про форму и тайминги. Я бы конечно в таком щекотливом месте CPLD поставил бы, и импульсы уже отдавал в цифровом виде, чтобы быть уверенным что ничего внутри проца не прервало процесс. Хотя вроде как говорилось есть уже приемники с цифровым выходом.
adnega
Aug 31 2014, 20:11
Цитата(Golikov A. @ Aug 31 2014, 21:04)

мне кажется у вас все таки проходит какая - то помеха. Может не нога дергается, а земля к примеру прыгает.
Согласен более чем полностью. Землю осциллографа тоже ведь по разному подключить можно...
Насколько я понимаю конструкцию, это (купюроприемник) некий блок, в котором находятся несколько двигателей, несколько излучающих диодов, видеодетекторов, могучий DSP для обработки, а на выходе импульсный сигнал по проводу на несколько десятков сантиметров в окружении другого электрооборудования. Как правило, провод не экранирован и возвратная земля проходит "черт знает где". А если есть GSM-модем внутри, то при обмене
с базовой станцией он может наводить в этот контур приличную помеху. Сюжетов можно придумать много. Я советовал железно замкнуть PA0 на 3.3В и, убедившись, что прерываний не возникает, искать проблемы в схемотехнике.
А резистор подтяжки линии с open drain где установлен? На стороне ключа или на стороне приемника?
AHTOXA
Aug 31 2014, 23:07
Цитата(Plexus @ Aug 31 2014, 21:07)

Та функция вызывается непроизвольно не сразу после ее правильного вызова, т.е. проходит минут 5 и только после этого вызывается непроизвольно. Неужели флаг не успевает сброситься за 5 минут? )
Не, тогда я согласен с предыдущими ораторами, это стопудово помеха.
Цитата(adnega @ Sep 1 2014, 03:11)

А резистор подтяжки линии с open drain где установлен? На стороне ключа или на стороне приемника?
Резистор со стороны приемника.
Тестирую, как вы и сказали - без купюроприемника, с подтяжкой на выводе PA0 для исключения помех/дребезга со стороны купюроприемника.
Golikov A.
Sep 1 2014, 06:36
1. Есть еще образец платы, вдруг именно на этой какой не пропай в резюке, к примеру. Или у него тепловой шум такой...
2. Проверьте и напишите значения регистров конфигурации, не то что вы функциями делаете, а прям реальное значение этих регистров
3. Уберите все переключения в программе после окончания конфигурации, вы спокойно можете какими-то функциями горе библиотеки от СТМ чего то еще подключать по ходу дела, то есть вызываете для включения 6 таймера, а ставиться может любой бит
4. if (EXTI_GetITStatus(EXTI_Line0) != RESET) - вот это замените пожалуйста на temp_reg = Значение регистра флагов.
if((temp_reg & НУЖНЫЙ_ПИН) != 0)
Потому что внешние прерывание принимает прерывание от 18 источников, 16 из них ноги, а 2 источника это будильник и PVD (че такое кстати ?). Ваша проверка смотрит только на то что было внешние прерывание, но она не смотрит на то какой пин или что его вызывало. Да и вообще полезно для отладки попечатать состояние флагов, мало ли что там как... Кроме прерываний есть же еще и еванты
В общем общие рекомендации при поиски магии, устраните все ее источники в виде дурных библиотек. Работайте напрямую с регистрами проца. Это часто более быстро, и всегда более безопасно и определено!
KnightIgor
Sep 1 2014, 07:14
Цитата(Golikov A. @ Sep 1 2014, 08:36)

4. if (EXTI_GetITStatus(EXTI_Line0) != RESET) - вот это замените пожалуйста на temp_reg = Значение регистра флагов.
Потому что внешние прерывание принимает прерывание от 18 источников, 16 из них ноги, а 2 источника это будильник и PVD (че такое кстати ?). Ваша проверка смотрит только на то что было внешние прерывание, но она не смотрит на то какой пин или что его вызывало.
Вот эту тему тоже высказать хотел. Присоединяюсь и настоятельно рекомендую разобраться со всеми ногами, которые обрабатываются _Line0. Это же вроде все типа PA0, PB0, и т.д.? Достаточно какой-то ноге из этой гвардии быть высокоомным входом (что именно и имеет место быть при рестарте процессора), как помехи гарантированы. Посему, влетая в прерывание, читайте еще состояние именно той ножки порта, которая прерывание вызвать должна была.
P.S. не могу удержаться: заголовок темы уж очень медицинские термины напоминает, особенно слово "непроизвольное" и "прерывание". Фантазия пустилась в пляс...
Цитата(Golikov A. @ Sep 1 2014, 12:36)

4. if (EXTI_GetITStatus(EXTI_Line0) != RESET) - вот это замените пожалуйста на temp_reg = Значение регистра флагов.
if((temp_reg & НУЖНЫЙ_ПИН) != 0)
Потому что внешние прерывание принимает прерывание от 18 источников, 16 из них ноги, а 2 источника это будильник и PVD (че такое кстати ?). Ваша проверка смотрит только на то что было внешние прерывание, но она не смотрит на то какой пин или что его вызывало.
Вообще-то смотрит, видите параметр EXTI_Line0 - это как раз оно.
Цитата(KnightIgor @ Sep 1 2014, 13:14)

Присоединяюсь и настоятельно рекомендую разобраться со всеми ногами, которые обрабатываются _Line0. Это же вроде все типа PA0, PB0, и т.д.?
Нет. Там в конфигурации задаётся порт для данной ножки. (GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0))
ЗЫ. Эх вы, библиотекофобы

Я тоже не пользую SPL, но хоть примерно знаю, как она работает. (Врага надо знать в лицо!

)
Таймеры в STM32 очень функциональные. Я бы сделал на таймере:
- по спаду запускаю счет;
- по фронту делаю захват таймера (длительность отрицательного импульса) в CCR1;
- по совпадению с CCR2 (50 мс + например, 5 мс) вызываю прерывание, где анализирую содержимое CCR1.
Если в диапазоне, то прибавляю единичку в счетчике импульсов. Иначе игнорирую.
- останавливаю таймер.
Итого: одно прерывание на импульс, а в регистре длительность этого импульса. Пачка коротких импульсов не вешает систему, т.к. таймер будет пересбрасываться и в окончании пачки сгенерит одно прерывание с некорректной длиной импульса.
Golikov A.
Sep 1 2014, 08:14
мне лень было лезть и смотреть именно эти функции. А по старым моим исканиям, пока не посмотришь что точно функция внутри делает, утверждать что она работает как видится нельзя

. Но в целом я не настаиваю, это же не у меня левые прерывания выпрыгивают)
Цитата(KnightIgor @ Sep 1 2014, 14:14)

P.S. не могу удержаться: заголовок темы уж очень медицинские термины напоминает, особенно слово "непроизвольное" и "прерывание". Фантазия пустилась в пляс...
Если честно, я подумывал об этом же, когда писал. Но, спасибо что заметили, поржал на работе в голос... Хорошо, рядом никого не было (:
KnightIgor
Sep 1 2014, 10:34
Цитата(AHTOXA @ Sep 1 2014, 09:55)

Нет. Там в конфигурации задаётся порт для данной ножки. (GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0))
Да, да, это я перепутал. Нельзя одновременно использовать в качестве входов для внешних прерываний ножки разных портов того же номера. То есть, PA0 и PB0 не получится использовать одновременно, что накладывает существенные ограничения схемотехнику: если надо несколько внешних прерываний, надо раскидывать их на разные индексы.
И снова автору топика: как говорил один наш доцент, вся дрянь от - источников питания. Где-то шумит масса, видать. Может повесить кондерчик с ноги на массу?
Цитата(Golikov A. @ Sep 1 2014, 14:14)

мне лень было лезть и смотреть именно эти функции.
Если вам лень, то зачем отвечать? Вы же вроде помочь хотите, а получается, что запутываете человека.
Golikov A.
Sep 1 2014, 11:41
Да я вроде предложил ему привести что получилось в регистрах после всего сделанного. Даже если оставить функции в покое вроде бы проверить это имеет смысл. Функции функциями, а состояние регистров определяет работу схемы.
Если человек посмотрит в регистрах будет не то что он хотел то значит виноваты функции и их надо изучить
Если человек посмотрит и в регистрах все будет как надо, а прерывание будет, значит виновато железо.
Какой смысл сразу ковырять код, если не понятно где искать?
Думаю хорошим тестом будет как он поймает прерывание которое не видит осциллограф, а он как то умеет это детектировать. Списать состояние всех регистров в этот момент. Состояние флагов, потому я предлагал ему их сохранить, а также все настроечные регистры. Также при входе в прерывание состояние ножки оценивать и сохранять тоже будет не лишним.
И мне до сих пор кажется что я помогаю...
Цитата(Golikov A. @ Sep 1 2014, 17:41)

Да я вроде предложил ему привести что получилось в регистрах после всего сделанного. Даже если оставить функции в покое вроде бы проверить это имеет смысл. Функции функциями, а состояние регистров определяет работу схемы.
Вы всерьёз думаете, что ошибка в библиотечных функциях? Причём в функциях конфигурирования, которыми пользуется огромное количество народа?
Цитата(Golikov A. @ Sep 1 2014, 17:41)

И мне до сих пор кажется что я помогаю...
Почитайте тред сначала, посчитайте, сколько пурги вы нагнали и окститесь.
Даже если среди ваших предложений и есть здравое зерно, то отыскать его практически невозможно.
Господа, да вы что в самом то деле?
Для меня любая помощь в радость.
На то и нужен мозговой - кто в какой области силен - железо, прошивка.
Пока сделал костыль - таймером опрашиваю ножку каждые 10 мс. Но выяснить нужно где непорядок. Сегодня начал смотреть регистры.
А осциллограф-то хороший был? Он может словить короткий всплеск на ножке? А очень короткий?
Golikov A.
Sep 1 2014, 15:32
Цитата
Вы всерьёз думаете, что ошибка в библиотечных функциях? Причём в функциях конфигурирования, которыми пользуется огромное количество народа?
А вы видели весь код ТС, чтобы быть уверенным что нигде неправильно не вызвана функция?
В целом все свои мысли по этому вопросу сказал, полезны или без покажет время...
Столкнулся с похожей проблемой что и автор топика. Контроллер STM32F100RB на плате STM32VLDISCOVERY.
На плате имеется штатная кнопка USER при нажатии на которую на ножку PA0 подаётся высокий уровень (2.9V - питание контроллера). Ножка PA0 изначально подтянута внешним резистором к общему проводу (к земле). Мне хочется чтобы при нажатии срабатывало прерывание EXTI и светодиод LD3 менял своё состояние на противоположное. Пример как можно видеть простейший и всё работает как и задумано, но есть БОЛЬШАЯ проблема с устойчивостью всей этой системы. При любом касании ножки PA0 металлическим пинцетом или щупом мультиметра происходит прерывание. Ничего подобного на других МК мною раньше не наблюдалось.
Как пробовал бороться:
1. Проверил подтяжку ножки осцилогафом - при касании уровень не меняется (или осцилографф не успевает это зафиксировать). Попробовал подтянуть через резистор меньшего номинала (вплоть до 100 Ом) - НЕ ПОМОГАЕТ
2. Пробовал ставить RC фильтр на ножку (100 Ом 100 нФ) - НЕ ПОМОГАЕТ.
3. Пробовал менять процедуру инициализации ножки и внешнего прерывания. Вместо SPL пробовал инициализацию через прямую запись в регистры - НЕ ПОМОГАЕТ. Также пробовались разные варианты инициализации из разных примеров/форумов/руководств - НЕ ПОМОГАЕТ.
4. Пробовал другие линии EXTI и другие ножки МК - НЕ ПОМОГАЕТ.
Устойчивость достигается только в одном случае - при прямой (без резистора) подтяжке ноги к питанию или земле. Тогда реакции на касания пинцетом нет. Сомнений в качестве разводки платы быть не может. Всё-таки это фирменная плата от STM. Поведение МК абсолютно не поддаётся логике и если честно уже начинают опускаться руки. В процессе поиска решения натыкался на темы форумов где описывались похожие глюки этих МК судя по всему авторам так и не смогли помочь с этим. Вообще какая-то засада...
Схема платы

Код проекта. IDE CooCox 1.7.8
CODE
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
#include "misc.h"
void EXTI_USER_Button_init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// Set pin PA0 as input
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Tell system that you will use PA0 for EXTI_Line0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitTypeDef EXTI_InitStructure;
// PA0 is connected to EXTI_Line0
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
// Interrupt mode
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
// Triggers on rising edge
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
// Enable interrupt
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
// Add to EXTI
EXTI_Init(&EXTI_InitStructure);
// Add IRQ vector to NVIC
NVIC_InitTypeDef NVIC_InitStruct;
// PA0 is connected to EXTI_Line1, which has EXTI0_IRQn vector
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
// Set priority
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
// Set sub priority
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
// Enable interrupt
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
// Add to NVIC
NVIC_Init(&NVIC_InitStruct);
}
int main(void)
{
// Инициализируем светодиоды LD3 и LD4
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // PC8 - LD4, PC9 - LD3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Set pin PC8 and PC9 as output
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_9);
GPIO_SetBits(GPIOC,GPIO_Pin_8);
EXTI_USER_Button_init();
while(1)
{
//
}
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET) // Judge whether a line break
{
GPIOC->ODR ^= GPIO_Pin_9;
for(uint32_t i = 0; i < 500000; i++); // Simple delay
}
EXTI_ClearITPendingBit(EXTI_Line0); // Remove LINE interrupt flag bit
}
Цитата(ISF @ May 9 2017, 11:30)

Мне хочется чтобы при нажатии срабатывало прерывание EXTI и светодиод LD3 менял своё состояние на противоположное. Пример как можно видеть простейший и всё работает как и задумано, но есть БОЛЬШАЯ проблема с устойчивостью всей этой системы.
Вы в курсе, что есть такая штука, как дребезг металлического контакта? Самый простой способ бороться с ним - не опрашивать состояние кнопки после его изменения в течение 50-100 мс. Это автоматически реализуется, если состояние кнопки опрашивается с периодом 50-100 мс. Если вам так нравится прерывание, можно запрещать прерывание на это время, используя таймер и его прерывание, но это просто лишний геморрой.
Цитата(scifi @ May 9 2017, 11:01)

Вы в курсе, что есть такая штука, как дребезг металлического контакта? Самый простой способ бороться с ним - не опрашивать состояние кнопки после его изменения в течение 50-100 мс. Это автоматически реализуется, если состояние кнопки опрашивается с периодом 50-100 мс. Если вам так нравится прерывание, можно запрещать прерывание на это время, используя таймер и его прерывание, но это просто лишний геморрой.
Про дребезг контактов и методы борьбы с ним мне известно, но то что я описываю это не дребезг. Прерывание срабатывает именно от касания (не замыкание на на что либо!) вывода МК любым металлическим предметом (палец такого эффекта не даёт). При этом не спасает даже подтяжка вывода к питанию или земле через резистор. Программно в обработчике прерывания удалось отследить что это всё-таки не случайность, а кратковременное изменение уровня на ножке при касании проводящим предметом. Удивляет поразительная чувствительность STM32 к такому. Тот же AVR на такое никогда не реагировал. И как в таком случае мерить потенциал на ножке если любое касание её даже щупом тестера вызывает подобные эффекты?
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.