Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывания STM32F050 не работают, если не дёргаешь этот порт
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры
shdv
Прерывания заведены с ног порта B0 и B2 дабы различать их было можно!
Ноги B9, B10, B11 - включены на выход. До тех пор, пока не начинаю периодично дёргать одну из выходных ног, прерывания от ног B0 и B2 не возникают (если одна нога стоит в 1, этого не достаточно, прерывание возникает если на порт подается меандр...).
Может кто сталкивался с данной проблемой? Убил уже день и ночь на решение, ничего путного в голову не лезет...
Использую Coocox.
wangan
Доброго дня, не юзал STМ, ночью нужно отдыхать, утро вечера мудреннее!!
ну как бы прерывания возникают не по форме сигнала а по перепадам с 1->0 или c 0->1, возможно у вас прерывание одно а маски прерывания настроенны в том числе и на пины выходов.
И получается что вы дергаете ногами, возникает прерывание, вы не отслеживаете какое именно прерывание произошло, и сами додумываете что это прерывания для входов, только по тому что вы ждете от туда прерывания. Плюс почитать Errata
shdv
Датчик висящий на B0 вызывает прерывание настроенное именно на эту линию, вызывается нужный обработчик, проверяет, точно ли прерывание вызвано с этой линии. Точно так же с датчиком висящем на B2 - вызывается и обрабатывается прерывание именно по этой линии с проверкой. Насчет маски ещё раз проверю. В errata не встретил никаких ограничений по прерываниям.
wangan
поменять контроллер, помыть плату, мож статикой пробиты ноги или грязь, поставить органичивющие резюки по входам, проверить что выхода не поцеплены к питанию или землю, глянуть помехи по питанию, помолится и поспать
shdv
На данном этапе пока так работает, но так работать конечно не дело. Макет девайса отдали заказчику на утверждение концепции. Когда вернётся, продолжу ковырять.
Сергей Борщ
Даю 99.9%, что причина - ошибка в вашей программе. Но, не видя исходников, невозможно сказать - в каком именно месте.
shdv
Мне важно знать какой датчик сработал первым.

Два глобальных флага для отработки прерываний внутри бесконечного цикла:
c_flag = 0;
g_flag = 0;

Инициализация внутри main:
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

//enable peripherals clocking
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC|RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

/* Connect EXTI0 Line to PB0 pin */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource0);

/* Configure EXTI0 line */
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);

/* Enable and set EXTI0 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource2);

/* Configure EXTI2 line */
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Enable and set EXTI2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/*GPIO init*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

NVIC_EnableIRQ (EXTI0_1_IRQn);
NVIC_EnableIRQ (EXTI2_3_IRQn);

for(;;)
{if (g_flag == 1)
{
NVIC_DisableIRQ (EXTI0_1_IRQn);
NVIC_DisableIRQ (EXTI2_3_IRQn);

// учитываем срабатывание

NVIC_EnableIRQ (EXTI0_1_IRQn);
NVIC_EnableIRQ (EXTI2_3_IRQn);
c_flag = 0;
g_flag = 0;
}
else {
NVIC_DisableIRQ (EXTI0_1_IRQn);
NVIC_DisableIRQ (EXTI2_3_IRQn);

// учитываем срабатывание

NVIC_EnableIRQ (EXTI0_1_IRQn);
NVIC_EnableIRQ (EXTI2_3_IRQn);
c_flag = 0;
g_flag = 0;
}
}


Обработчики прерываний:

void EXTI0_1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
if((c_flag==0)&(g_flag==0))
{
c_flag = 0;
g_flag = 1; //флаг будет сброшен в main после того, как срабатывание датчика будет учтено
}
EXTI_ClearITPendingBit(EXTI_Line0);//Очищаем флаг прерывания
}
}

void EXTI2_3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line2) != RESET)
{
if((c_flag==0)&(g_flag==0))
{
c_flag = 1;//флаг будет сброшен в main после того, как срабатывание датчика будет учтено
g_flag = 0;
}
EXTI_ClearITPendingBit(EXTI_Line2);//Очищаем флаг прерывания
}
}
Alien85
Код
if((c_flag==0)&(g_flag==0))

заменить на
Код
if((c_flag==0)&&(g_flag==0))
shdv
Логично, но проблему это всё равно не решит.
Сергей Борщ
1) как объявлены c_flag и g_flag?
2) для полной красоты не хватает __DSB() в конце каждого обработчика прерывания
3) Если одно из прерываний произойдет с момента выхода из другого до сброса c_flag, g_flag в основном цикле - оно просто сбросит свой флаг и основной цикл его не заметит, потеряет.
4) прерывания имеют разный приоритет, значит прерывание EXTI0 может сработать внутри обработчика EXTI2 и случится полная каша.
5) в железе PB9, 10, 11 подключены к другим входам EXTI и влиять не должны никак.

Полагаю, что причина в п. 1. Могу предположить, что вы объявили их без квалификатора volatile и тогда добавление кода махания ногами PB9...11, из-за использования вызовов функций SPL, заставляет компилятор вычитывать c_flag и g_flag из памяти в начале каждой итерации цикла. Без кода махания ногами компилятор из-за отсутствия volatile оставляет их закешированными в регистрах и изменение обработчиками их копий в памяти на значения в регистрах не влияет.
shdv
Учел все замечания и предложения, ничего не помогало. Перевел принудительно датчики в состояние "1" и измерил напряжение на выходе датчиков. Оказалось чуть ниже 1/2 напряжения питания. Получалось, что шум порта + напряжение с датчика приводили к срабатыванию входа, а само по себе напряжение датчика не приводило. Всем спасибо за советы!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.