STM32: как вызывать Delay на System Tick Timer из обработчика внешнего прерывания?

Я новичек в ARM и в частности STM32. Пытаюсь сделать задержку на System Tick Timer. Функция, которая это реализует, вызывается в обработчике внешнего прерывания EXTI0. После единоразового срабатывания внешнего прерывания оно перестает работать. Что я делаю не так?


STM32VLDiscovery ( STM32F100RBT6B ). Дефайны STM32F10X_MD_VL USE_STDPERIPH_DRIVER указаны в свойствах проекта.

#include "stm32f10x.h"

int SysTickDelay=0;

GPIO_InitTypeDef PORT_Init_Struct;

void Delay( unsigned int Val);

int main(void)
{	
//- init ---------------------------------------------------------
// Clock enable
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_USART1 | RCC_APB2ENR_AFIOEN | RCC_APB2Periph_AFIO , ENABLE);
// PortC8|9 Out Push-Pull (LED)
	PORT_Init_Struct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
	PORT_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
	PORT_Init_Struct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOC, &PORT_Init_Struct);
// Interrupts
	AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI1_PB;
	EXTI->IMR |= EXTI_IMR_MR0;
	EXTI->RTSR |= EXTI_RTSR_TR0;
	NVIC_EnableIRQ(EXTI0_IRQn);
	
//-----------------------------------------------------------------
	SysTick_Config(SystemCoreClock /1000);
	while(1);	
}

void Delay( unsigned int Val)  
{  
	SysTickDelay = Val;  
	while (SysTickDelay != 0); 
}  

void SysTick_Handler(void)  
{  
	if (SysTickDelay != 0)  
	{  
		SysTickDelay--;  
	}  
}  

void EXTI0_IRQHandler(void)
{
	GPIOC->ODR^=GPIO_Pin_8 | GPIO_Pin_9;
	EXTI->PR|=0x01;
	Delay(100);
}
  • Вопрос задан
  • 10899 просмотров
Пригласить эксперта
Ответы на вопрос 2
@smartly
1. Вызывать задержки изнутри обработчика прерывания — это очень плохо.
2. Функция Delay должна зависнуть. нужно пометить SysTickDelay как volatile.
3. Не помню про EXTI, но возможно, его нужно сбрасывать явно перед выходом.
Ответ написан
@itxs
Инженер-электронщик
1. В прерывании EXTI нужно очищать флаг прерывания для возможности повторного срабатывания этого прерывания.
2. SysTickDelay должен иметь тип uint32_t, иначе вы не используете целую половину возможного диапазона.
3. Хорошо что у вас SysTickDelay декрементируется, а то были случаи.
4. Никаких прерываний с дилеями внутри! Делайте асинхронно, с таймерами, спинлоками (это просто переменная-флаг) и т.д.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы