Basilij 0 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба Здравствуйте господа. Давно терзает меня вопрос, почему в момент инициализации NVIC_Init(&NVIC_InitStructure); может возникнуть прерывание? Выглядит это так, как будто в момент запуска МК, в регистре EXTI->PR уже заранее что то есть, и когда включаем NVIC произсходит прерывание. Микроконтроллер STM32F100C4 Вот код: void InitButton() { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitTypeDefStructure; NVIC_InitTypeDef NVIC_InitStructure; /* GPIOB clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*Включили тактирование AFIO на шине APB2. Этот блок отвечает за внешние прерывания как AF*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // Configure PB.13/13/14 as Input GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOB, &GPIO_InitStructure); //Подключаем порт к прерыванию GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14); EXTI_InitTypeDefStructure.EXTI_Line = EXTI_Line12 | EXTI_Line13 | EXTI_Line14; EXTI_InitTypeDefStructure.EXTI_LineCmd = ENABLE; EXTI_InitTypeDefStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitTypeDefStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitTypeDefStructure); //EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); }; void EXTI15_10_IRQHandler() { if (EXTI_GetITStatus(EXTI_Line12) != RESET) { EXTI_ClearITPendingBit(EXTI_Line12); } else if (EXTI_GetITStatus(EXTI_Line13) != RESET) { EXTI_ClearITPendingBit(EXTI_Line13); } else if (EXTI_GetITStatus(EXTI_Line14) != RESET) { EXTI_ClearITPendingBit(EXTI_Line14); }; }; Перед Инициализацией NVIC пробовал очищать регистр прерываний EXTI командой EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14); После этого вроде как всё нормально. Но почему так!? Пины настраивал и внутренней и с внешней подтяжкой, но это не влияет. Внешняя подтяжка достаточная. Еще на STM32L152 такое явление замечал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vlad_new 1 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 2 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба А вы бы посмотрели 1. что конкретно делает функция NVIC_Init() 2. содержимое EXTI_PR до вызова NVIC_Init и сразу же после него (отладчиком, либо вывести в UART, либо на LCD) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Basilij 0 22 октября, 2012 Опубликовано 22 октября, 2012 (изменено) · Жалоба Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить. Предполагаю что если лапки подтянуты к GND, и ждут нажатия кнопки которая подтянет их к +3v то в момент включения там всётаки низкий уровень нежели высокий. Может вы имели в виду не NVIC чистить а EXTI? А вы бы посмотрели 1. что конкретно делает функция NVIC_Init() 2. содержимое EXTI_PR до вызова NVIC_Init и сразу же после него (отладчиком, либо вывести в UART, либо на LCD) Конечно смотрел, в основном там "EXTI->PR" 0b010 0000 0000 0000 т.е. преимущественно на EXTI_Line13 флаг прерывания стоит после подачи питания и реже на EXTI_Line14. На EXTI_Line12 Вообще почти никогда из 1000 один раз может возникнет. EXTI->PR Заполняется спонтанно, т.е. может быть заполнен на момент NVIC_Init может быть не заполнен. Вопрос в том что я не нашёл примера от ST где бы вызывалась EXTI_ClearITPendingBit перед инициализацией NVIC. И в документации не нашёл где сказано что биты в EXTI->PR нужно чистить перед вызовом NVIC_Init. Изменено 22 октября, 2012 пользователем Basilij Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба В мануале про EXTI_PR написано Reset value: undefined, так что очищать обязательно. А вообще есть хорошее правило - всегда сбрасывать любые статусы, перед тем как разрешать соответствующее им прерывание, помогает избежать трудно-уловимых глюков. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Basilij 0 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба Удалось добиться стабильной повторяемости. Судя по отладчику, флаг EXTI->PR выставляеться не сразу после подачи питания, а в основном после GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) { uint32_t tmp = 0x00; /* Check the parameters */ assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource)); assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)); AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp; AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03))); } Если возникло прерывание, и мы останавливаем отладку, но питание с МК не убираем, а просто перезапускаем отладку т.е. начинаем с Reset Handler то "EXTI->PR" уже равен 0b010 0000 0000 0000 при запуске. Т.е. значение регистра "EXTI->PR" в ОЗУ не очищается после Reset Handler. В мануале про EXTI_PR написано Reset value: undefined, так что очищать обязательно. А вообще есть хорошее правило - всегда сбрасывать любые статусы, перед тем как разрешать соответствующее им прерывание, помогает избежать трудно-уловимых глюков. Действительно написано.. Спасибо вам. Десять раз просмотрел весь это раздел и всё как то этот момент упускал из виду. У меня ещё вопрос, ниже написано: "This bit is cleared by writing a 1 into the bit or ..." т.е. если в прерывание нас привело "EXTI->PR" 0b010 0000 0000 0000, то чтобы снять флаг прерывания мы должны выполнить команду EXTI->PR = 0b010 0000 0000 0000 верно? В библиотеке так и есть. А вот что значит ""...or by changing the sensitivity of the edge detector." ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nis 0 23 октября, 2012 Опубликовано 23 октября, 2012 (изменено) · Жалоба А вот что значит ""...or by changing the sensitivity of the edge detector." ? Так сказано же что состояние не определено, а точнее определяется случайными факторами, т.к. внешние прерывания чувствительны к уровню а не к значению. Соответственно при подаче тактового сигнала на этот модуль мы получаем на выходе срабатывание. Изменено 23 октября, 2012 пользователем IgorKossak бездумное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться