|
|
  |
STM32 и много прерываний |
|
|
|
Feb 8 2016, 13:20
|

отэц
    
Группа: Свой
Сообщений: 1 729
Регистрация: 18-09-05
Из: Москва
Пользователь №: 8 684

|
Добрый день уважаемый Олл! Такая проблема - есть STM32F103 72 Мгц и много прерываний: три USARTa , SysTick +8 EXTI. Если выключаю EXTI - всё работает. Если включаю, МК виснет через несколько минут. На внешние прерывания приходят импульсы длительностью 0.5 мкс, с периодом 1 миллисекунда. (импульсы - нули, т.е. - ямы) CODE void init_EXT(void)
{
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource10); //прерывание с порта D ножки 13 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource11); //прерывание с порта D ножки 13 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling EXTI_InitStructure.EXTI_Line = EXTI_Line11; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource12); //прерывание с порта D ножки 13 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling EXTI_InitStructure.EXTI_Line = EXTI_Line12; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource13); //прерывание с порта D ножки 13 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling EXTI_InitStructure.EXTI_Line = EXTI_Line13; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource14); //прерывание с порта D ножки 13 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling EXTI_InitStructure.EXTI_Line = EXTI_Line14; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
NVIC_SetPriority(EXTI15_10_IRQn, 2); NVIC_EnableIRQ(EXTI15_10_IRQn);
//-----------------------------------------------------------------
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource7); //прерывание с порта D ножки 11 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising EXTI_InitStructure.EXTI_Line = EXTI_Line7; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource8); //прерывание с порта D ножки 11 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising EXTI_InitStructure.EXTI_Line = EXTI_Line8; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource9); //прерывание с порта D ножки 11 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; // EXTI_Trigger_Rising EXTI_InitStructure.EXTI_Line = EXTI_Line9; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
NVIC_SetPriority(EXTI9_5_IRQn, 2); NVIC_EnableIRQ(EXTI9_5_IRQn);
} CODE void EXTI9_5_IRQHandler (void) { EXTI_ClearFlag(EXTI_Line5); EXTI_ClearITPendingBit(EXTI_Line5); EXTI_ClearFlag(EXTI_Line6); EXTI_ClearITPendingBit(EXTI_Line6); // EXTI_ClearFlag(EXTI_Line7); // EXTI_ClearITPendingBit(EXTI_Line7); // EXTI_ClearFlag(EXTI_Line8); // EXTI_ClearITPendingBit(EXTI_Line8);
if (EXTI_GetITStatus(EXTI_Line7)!=RESET) { EXTI_ClearFlag(EXTI_Line7); EXTI_ClearITPendingBit(EXTI_Line7); state_TNO_1=1; }
if (EXTI_GetITStatus(EXTI_Line8)!=RESET) { EXTI_ClearFlag(EXTI_Line8); EXTI_ClearITPendingBit(EXTI_Line8); state_T1hz=1; } if (EXTI_GetITStatus(EXTI_Line9)!=RESET) { EXTI_ClearFlag(EXTI_Line9); EXTI_ClearITPendingBit(EXTI_Line9); //Transf("ТНО\r\n"); state_TNO=1; }
}
void EXTI15_10_IRQHandler (void) { /* NVIC_ClearPendingIRQ (EXTI15_10_IRQn);
Transf("принято прерывание! INT15_10\r\n"); */
SCH_INT_OUT++; state_TNO_1=1; state_T1hz=1; state_TNO=1; if (EXTI_GetITStatus(EXTI_Line10)!=RESET) { EXTI_ClearFlag(EXTI_Line10); EXTI_ClearITPendingBit(EXTI_Line10); // Transf("ТНЦ\r\n");
state_TKP =1; SCH_INT_IN++; }
if (EXTI_GetITStatus(EXTI_Line11)!=RESET) { EXTI_ClearFlag(EXTI_Line11); EXTI_ClearITPendingBit(EXTI_Line11); state_TNP =1; }
if (EXTI_GetITStatus(EXTI_Line12)!=RESET) { EXTI_ClearFlag(EXTI_Line12); EXTI_ClearITPendingBit(EXTI_Line12); state_TKI =1; }
if (EXTI_GetITStatus(EXTI_Line13)!=RESET) { EXTI_ClearFlag(EXTI_Line13); EXTI_ClearITPendingBit(EXTI_Line13); state_TNI =1; }
if (EXTI_GetITStatus(EXTI_Line14)!=RESET) { EXTI_ClearFlag(EXTI_Line14); EXTI_ClearITPendingBit(EXTI_Line14); state_TNC =1; } EXTI_ClearFlag(EXTI_Line11); EXTI_ClearITPendingBit(EXTI_Line11); EXTI_ClearFlag(EXTI_Line12); EXTI_ClearITPendingBit(EXTI_Line12); EXTI_ClearFlag(EXTI_Line13); EXTI_ClearITPendingBit(EXTI_Line13); EXTI_ClearFlag(EXTI_Line14); EXTI_ClearITPendingBit(EXTI_Line14); EXTI_ClearFlag(EXTI_Line15); EXTI_ClearITPendingBit(EXTI_Line15); }
CODE void init_GPIO (void) { GPIO_AFIODeInit(); GPIO_DeInit(GPIOA); GPIO_DeInit(GPIOB); GPIO_DeInit(GPIOC); GPIO_DeInit(GPIOD); GPIO_DeInit(GPIOE);
/* Configure the выходы GPIOA pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure выходы GPIOB pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure выходы GPIOC pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure выходы GPIOD pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPI O_Pin_8|GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Configure выходы GPIOE pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure);
// конфигурируем входы port E , все с подтяжкой вниз GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 |GPIO_Pin_3 | GPIO_Pin_4 |GPIO_Pin_5 |GPIO_Pin_7| GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10|GPIO_Pin_11| GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_PinLockConfig(GPIOE,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);
// конфигурируем входы port B, GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinLockConfig(GPIOB,GPIO_Pin_9);
// конфигурируем входы port D, GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 |GPIO_Pin_10|GPIO_Pin_13|GPIO_Pin_11;; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
// конфигурируем входы port C для прерывания, GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
} CODE void init_RCC (void) {
// Cогласно документации необходимо разрешить тактирование // AFIO (альтернативные функции линий ввода-вывода), так как регистры // управления мультиплексорами находится в данном модуле:
/* Initialize Enable the Clock*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC |RCC_APB2Periph_GPIOD |RCC_APB2Periph_GPIOE |RCC_APB2Periph_USART1|RCC_APB2ENR_AFIOEN |RCC_APB2Periph_AFIO , ENABLE);// RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2 |RCC_APB1Periph_USART3, ENABLE);
SysTick_Config(SystemCoreClock /1000);//1ms
} Пока мк работает - все прерывания функционируют , ловят свои импульсы. Может у кого есть идеи - почему так происходит?
--------------------
b4edbc0f854dda469460aa1aa a5ba2bd36cbe9d4bc8f92179f 8f3fec5d9da7f0 SHA-256
|
|
|
|
|
Feb 8 2016, 14:13
|

отэц
    
Группа: Свой
Сообщений: 1 729
Регистрация: 18-09-05
Из: Москва
Пользователь №: 8 684

|
Цитата(scifi @ Feb 8 2016, 16:49)  Внутрисхемным отладчиком подключались? Чтобы посмотреть на это "зависание". ..нет возможности. з.ы. забыл указать что по одному из уартов идёт интенсивный обмен 512кбит/c пачками по 20 байт каждые 20 млс.
--------------------
b4edbc0f854dda469460aa1aa a5ba2bd36cbe9d4bc8f92179f 8f3fec5d9da7f0 SHA-256
|
|
|
|
|
Feb 8 2016, 21:14
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
1. EXTI_ClearFlag(EXTI_Line*); и EXTI_ClearITPendingBit(EXTI_Line*); в принципе одно и то же. Можно оставить только EXTI_ClearITPendingBit()
2. Помните, что на линии, например, EXTI_Line9, висят ВСЕ Py9 ноги, где y=[A,B,C,D,E,F,G]. Это значит, что какая бы нога с номером 9 ни дернулась, будет прерывание. Внимание! Утверждение в доках, что только порты, сконфигурированные как вход, подключаются к линии EXTI, есть полный п...ж и провокация! Проверено, что ноги, определенные и как выходы, и вообще как альтернативные функции, ТАКЖЕ вызывают прерывание. Поэтому гляньте, а нет ли по схеме ноги, которая с тем же номером, что и ноги для прерываний, но на которой быстрая периферия как UART или SDIO или что угодно с большой частотой: вот проц и не вылазит из прерываний вообще.
|
|
|
|
|
Feb 9 2016, 07:42
|

отэц
    
Группа: Свой
Сообщений: 1 729
Регистрация: 18-09-05
Из: Москва
Пользователь №: 8 684

|
Цитата(Огурцов @ Feb 9 2016, 01:26)  а покажите-ка обработчик uart`а CODE void USART1_IRQHandler (void) { if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)) { USART_ClearFlag(USART1,USART_FLAG_ORE); // Overrun Error }
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //прерывание по приему данных { if ((USART1->SR & (USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE|USART_FLAG_ORE)) == 0) //проверяем нет ли ошибок { rx_buffer1[rx_wr_index1++]= (uint8_t) (USART_ReceiveData(USART1)& 0xFF); //считываем данные в буфер, инкрементируя хвост буфера if (rx_wr_index1 == RX_BUFFER_SIZE1) rx_wr_index1=0; //идем по кругу if (++rx_counter1 == RX_BUFFER_SIZE1) //переполнение буфера { rx_counter1=0; //начинаем сначала (удаляем все данные) rx_buffer_overflow1=1; //сообщаем о переполнении } } else { USART_ReceiveData(USART1); error_rx_usart1=1; }; //в идеале пишем здесь обработчик ошибок, в данном случае просто пропускаем ошибочный байт. }
if(USART_GetITStatus(USART1, USART_IT_ORE) == SET) //прерывание по переполнению буфера { USART_ReceiveData(USART1); //в идеале пишем здесь обработчик переполнения буфера, но мы просто сбрасываем этот флаг прерывания чтением из регистра данных. rx_fifo_buffer_overflow1=1; } //----------------------- if(USART_GetITStatus(USART1, USART_IT_TXE) == SET) { if (tx_counter1) { --tx_counter1; USART_SendData(USART1,tx_buffer1[tx_rd_index1++]); if (tx_rd_index1 == TX_BUFFER_SIZE1) tx_rd_index1=0; } else { USART_ITConfig(USART1, USART_IT_TXE, DISABLE); } }
}
CODE void USART2_IRQHandler (void) {
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)) { USART_ClearFlag(USART2,USART_FLAG_ORE); // Overrun Error } if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET) //прерывание по приему данных { if ((USART2->SR & (USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE|USART_FLAG_ORE)) == 0) //проверяем нет ли ошибок { rx_buffer2[rx_wr_index2++]= (uint8_t) (USART_ReceiveData(USART2)& 0xFF); //считываем данные в буфер, инкрементируя хвост буфера if (rx_wr_index2 == RX_BUFFER_SIZE2) rx_wr_index2=0; //идем по кругу if (++rx_counter2 == RX_BUFFER_SIZE2) //переполнение буфера { rx_counter2=0; //начинаем сначала (удаляем все данные) rx_buffer_overflow2=1; //сообщаем о переполнении } } else { USART_ReceiveData(USART2); error_rx_usart2=1; } //в идеале пишем здесь обработчик ошибок, в данном случае просто пропускаем ошибочный байт. }
if(USART_GetITStatus(USART2, USART_IT_ORE) == SET) //прерывание по переполнению буфера { USART_ReceiveData(USART2); //в идеале пишем здесь обработчик переполнения буфера, но мы просто сбрасываем этот флаг прерывания чтением из регистра данных. rx_fifo_buffer_overflow2=1; } }
Кстати, ещё вопрос: Я пробовал все прерывания внешние, завести через логическое ИЛИ на одно прерывание (благо перед мк есть ПЛИС и импульсы ввиде едениц) 10 нога порта D, и по срабатыванию этого прерывания смотреть на какой ножке МК появился импульс (туда приходят те же но инвертированные импульсы с оптронов) - так вот почти никогда не мог в эти импульсы попасть, хотя импульс прерывания опережает импульс что приходил на ножки МК всего на 200 нс делал так : CODE void EXTI15_10_IRQHandler (void) {
if (EXTI_GetITStatus(EXTI_Line10)!=RESET) { EXTI_ClearFlag(EXTI_Line10); EXTI_ClearITPendingBit(EXTI_Line10); if (GPIO_ReadInputDataBit (GPIOE,GPIO_Pin_13) ==0) state_TNI=1; if (GPIO_ReadInputDataBit (GPIOE,GPIO_Pin_12) ==0) state_TKI=1; if (GPIO_ReadInputDataBit (GPIOE,GPIO_Pin_11) ==0) state_TNP=1; if (GPIO_ReadInputDataBit (GPIOE,GPIO_Pin_10) ==0) state_TKP=1; } }
но что странно - импульс с 10 ноги порта E ловился, а остальные - нет. Почему так происходит? слишком долго обрабатывается прерывание и за 0.5 мкс + 200 нс я проскакиваю отклик на ноге?
--------------------
b4edbc0f854dda469460aa1aa a5ba2bd36cbe9d4bc8f92179f 8f3fec5d9da7f0 SHA-256
|
|
|
|
|
Feb 9 2016, 08:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Lmx2315 @ Feb 9 2016, 09:42)  Код if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)) { USART_ClearFlag(USART1,USART_FLAG_ORE); // Overrun Error } Вот это работать не будет. Флаг ORE сбрасывается чтением регистра DR. Так что при возникновении ORE вы вполне могли циклиться на этом прерывании.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 5 2016, 19:17
|

отэц
    
Группа: Свой
Сообщений: 1 729
Регистрация: 18-09-05
Из: Москва
Пользователь №: 8 684

|
Цитата(Aaron @ Feb 11 2016, 17:25)  сейчас не глянуть, но емнип USART_SendData(USART1,tx_buffer1[tx_rd_index1++]); содержит в себе while() - очень плохо! Почему TXdata сразу в регистр не пишете? ..спасибо за замечание! посмотрю. з.ы. посмотрел : Код void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); /* Transmit Data */ USARTx->DR = (Data & (uint16_t)0x01FF); } вроде нет - while
--------------------
b4edbc0f854dda469460aa1aa a5ba2bd36cbe9d4bc8f92179f 8f3fec5d9da7f0 SHA-256
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|