Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 и много прерываний
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Lmx2315
Добрый день уважаемый Олл!

Такая проблема - есть 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


}

Пока мк работает - все прерывания функционируют , ловят свои импульсы.

Может у кого есть идеи - почему так происходит?
scifi
Цитата(Lmx2315 @ Feb 8 2016, 16:20) *
Если включаю, МК виснет через несколько минут.

Внутрисхемным отладчиком подключались? Чтобы посмотреть на это "зависание".
Lmx2315
Цитата(scifi @ Feb 8 2016, 16:49) *
Внутрисхемным отладчиком подключались? Чтобы посмотреть на это "зависание".

..нет возможности.
з.ы.
забыл указать что по одному из уартов идёт интенсивный обмен 512кбит/c пачками по 20 байт каждые 20 млс.
KnightIgor
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 или что угодно с большой частотой: вот проц и не вылазит из прерываний вообще.
adnega
Цитата(KnightIgor @ Feb 9 2016, 00:14) *
Это значит, что какая бы нога с номером 9 ни дернулась, будет прерывание.

Это не так. Имя порта для номера 9 указывается в 4..7 битах регистра AFIO_EXTICR3.
Активность 9 линии на других портах игнорируется.
Огурцов
а покажите-ка обработчик uart`а
Lmx2315
Цитата(Огурцов @ 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 нс я проскакиваю отклик на ноге?
Сергей Борщ
Цитата(Lmx2315 @ Feb 9 2016, 09:42) *
Код
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE))
  {
    USART_ClearFlag(USART1,USART_FLAG_ORE);
    // Overrun Error
  }
Вот это работать не будет. Флаг ORE сбрасывается чтением регистра DR. Так что при возникновении ORE вы вполне могли циклиться на этом прерывании.
Огурцов
совершенно оно
Lmx2315
Цитата(Сергей Борщ @ Feb 9 2016, 11:29) *
Вот это работать не будет. Флаг ORE сбрасывается чтением регистра DR. Так что при возникновении ORE вы вполне могли циклиться на этом прерывании.

..спасибо - попробую.
Aaron
сейчас не глянуть, но емнип USART_SendData(USART1,tx_buffer1[tx_rd_index1++]); содержит в себе while() - очень плохо! Почему TXdata сразу в регистр не пишете?
Lmx2315
Цитата(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
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.