2016-04-07 2 views
2

В приведенном ниже коде я вижу, что таймер работает нормально, так как индикатор всегда мигает. Но значение переменной count никогда не изменяется внутри второго while.Значение переменной не обновляется прерыванием на STM32F4 Discovery

Я не знаю, что могло бы пойти не так?

// count variable used only in main and TIM2_IRQHandler. 
uint8_t count=0; 

int main(void) 
{ 
    count=0; 
    SystemInit(); 
    GPIOInit(); 
    NVIC_Configuration(); 
    TIM_Configuration(); 
    init_USART3(115200); 
    // All initialization is ok. 
    USART_puts(USART3, "\r\nConnection ok.\r\n");// Working normally 
    while (1) 
    { 
     if(asterixok==1)// No problem. This code if ok ->>process continue next step. 
     { 
      GPIO_SetBits(GPIOD , GPIO_Pin_12); // Led on (ok) 
      count=0;// count going to zero, timer working, must be change in there 
      while(1) 
      { 
       //Led blinking continue 
       //Timer query working normal led (13) blink. 
       //There is a problem 
       if(count>5) // Timer working, count never change in timer interrupt query (WHY) 
       { 
        GPIO_SetBits(GPIOD , GPIO_Pin_14); // LED OFFFFFFFFFFFFFFFF 
        USART_puts(USART3, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n"); 
        goto nextstate; 
       } 
      } 
      nextstate: 
      GPIO_SetBits(GPIOD , GPIO_Pin_15); // Led never going on because code step in while loop. 
     } 
    } 
} 

void USART3_IRQHandler(void) 
{ 
    if(USART_GetITStatus(USART3, USART_IT_RXNE)) 
    { 
     unsigned char t = USART3->DR; 
     if(t=='*') 
     { 
      asterixok=1; 
     } 
    } 
} 

void TIM2_IRQHandler(void) 
{ 
    if (TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET) 
    { 
     TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); 
     count++; 
     if(count>100) 
      count=0; 
     if(display) 
     { 
      GPIO_ResetBits(GPIOD , GPIO_Pin_13); 
     } 
     else 
     { 
      GPIO_SetBits(GPIOD , GPIO_Pin_13); 
     } 
     display = ~display; 
    } 
} 

Я пробовал с другой панелью Discovery, но проблема продолжается. Пожалуйста, помогите. Я схожу с ума!

ответ

1

Вы должны объявить count в volatile, как таковой:

volatile uint8_t count; 

При составлении main компилятор смог доказать, что count не был изменен в теле цикла, и поэтому, вероятно, кэшировать его значение в регистре и, возможно, даже оптимизировал заявление if. Вы можете проверить это, посмотрев на разборку. Компилятор не знает о прерываниях в соответствии со стандартом и поэтому разрешается выполнять такие оптимизации. Квалификационный count как volatile запретит компилятору совершать эти оптимизации, заставляя его перезагружать переменную из памяти каждый раз, когда она используется.

В этом простом случае volatile будет достаточно, но имейте в виду, что он не гарантирует атомарность операций, и это не мешает компилятору и процессору переупорядочить инструкции по доступу к переменной. Это заставляет компилятор генерировать инструкции доступа к памяти каждый раз, когда используется переменная. Для атомарности вам нужны блокировки, и для предотвращения переупорядочения вам нужны барьеры памяти.

+0

Tahnk вы для своих решений. Я пробовал ключевое слово volatile variable. Иногда проблема повторялась снова. Насколько я понимаю, возможно, это происходит, если и обработчик запросов прерываний, и зависимый код получают доступ к той же переменной «named count» GLOBAL. Возможно, отключить/разрешить действие прерывания исправить это. Я попробую в соответствующее время. – Fico