реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Прерывания и таймеры в STM32
alex_avr2
сообщение Feb 14 2013, 23:50
Сообщение #1





Группа: Новичок
Сообщений: 4
Регистрация: 24-11-12
Пользователь №: 74 538



Здравствуйте коллеги.
Мучаюсь уже который день с таймером в стм32 (контроллер стм32ф303, таймеры аналогичны тем что в ф4).

Используется таймер общего назначения 4.
Задача - вызывать прерывание по переполнению и по совпадению, в прерывании определять какое из событий произошло и принимать соответствующие действия.
Вот код настройки таймера:

Код
void pwm_init(void){
  
  RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
  
  TIM4->PSC = 0;
  TIM4->ARR = 1000;
  
  TIM4->CCR3 = 800;
  
//  TIM4->DIER = TIM_DIER_CC3IE;
  TIM4->DIER = TIM_DIER_UIE;  

  NVIC_EnableIRQ(TIM4_IRQn);
  NVIC_SetPriority (TIM4_IRQn, 5);

  TIM4->CR1 |= TIM_CR1_CEN;

}

Таймер считает до 1000. В третьем канале записано 800.

Включено тольеко прерывание по переполнению.

Вот обработчик:
Код
void TIM4_IRQHandler(void){

  if(TIM4->SR & TIM_SR_UIF){
    TIM4->SR = ~TIM_SR_UIF;  
    GPIOE->ODR |= GPIO_ODR_12;
    GPIOE->ODR &= ~GPIO_ODR_12;
  }  

  if(TIM4->SR & TIM_SR_CC3IF){
    TIM4->SR = ~TIM_SR_CC3IF;  
    GPIOE->ODR |= GPIO_ODR_10;
    GPIOE->ODR &= ~GPIO_ODR_10;
  }  
  
  GPIOE->ODR |=  GPIO_ODR_15;
  GPIOE->ODR &= ~GPIO_ODR_15;
  
}


Проверяем флаг прерывания, сбрасываем этот флаг путем записи в него нуля, и мигаем светодиодиком. Так для прерывания по переполнению и по совпадению третьего канала. В конце мигаем еще одинм светодиодиком, чтобы видет что обработчик вообще вызвался.

Но в итоге, несмотря на то что разрешено только прерывание по переполнению - выполняются оба обработчика, все светодиоды мигают.
Если разрешить только прерывание по совпадению, то ничего не меняется. Если оба одновременно - то опять ничего не меняются. Оба if выполняются друг за другом через одинаковые промежутки времени. Дебаг показывает постоянно единички во флагах CC4IF, CC3IF, CC2IF, CC1IF, UIF.

Что я делаю не так?
Хочу чтобы при переполнении мигал один светодиодик, а при совпадении - другой.

Go to the top of the page
 
+Quote Post
nx6310
сообщение Feb 15 2013, 03:12
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



У вас канал захвата сравнения не настроен вроде.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 15 2013, 03:15
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



разрешение или запрет прерывания не влияет на появление флага. Это виляет только на появление вызова в след за появлением флага. Так что поскольку происходят оба события вот и появляются оба флага. И надо уточнить, может так оказаться что для сброса флага не 0 надо писать и не в этот регистр.....
Go to the top of the page
 
+Quote Post
alex_avr2
сообщение Feb 15 2013, 07:51
Сообщение #4





Группа: Новичок
Сообщений: 4
Регистрация: 24-11-12
Пользователь №: 74 538



Цитата
У вас канал захвата сравнения не настроен вроде.

Для выполнения прерывания достаточно лишь прописать значение в регистр сравнения, т.к. нулевые значения в регистре настройки по умолчанию настраивают канал в режим output.

Цитата(Golikov A. @ Feb 15 2013, 07:15) *
разрешение или запрет прерывания не влияет на появление флага. Это виляет только на появление вызова в след за появлением флага. Так что поскольку происходят оба события вот и появляются оба флага.

Спасибо, это опхоже то, что я хотел услышать. Не очень удобно получается, хотя может быть так и правильние.

Цитата(Golikov A. @ Feb 15 2013, 07:15) *
И надо уточнить, может так оказаться что для сброса флага не 0 надо писать и не в этот регистр.....

Да, это точно.

В процессе изучения проблемы увидел, что очень у многих сброс флагов делается неправильно, через " &= ~". Тут есть тонкость - в референсе в каждом регистре под битом пишется его тип. В случае с флагами таймера тип обозначен как "rc_w0". В начале референса есть расшифровка всех обозначений, где срези прочего написано:
Цитата
read/clear (rc_w0) Software can read as well as clear this bit by writing 0. Writing ‘1’ has no effect on
the bit value.


Сообщение отредактировал alex_avr2 - Feb 15 2013, 07:55
Go to the top of the page
 
+Quote Post
SSerge
сообщение Feb 15 2013, 11:08
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Чтобы реагировать только на флаги от которых разрешены прерывания можно использовать содержимое DIER как маску.
или просто вручную (константой) маскировать флаги у которых прерывания не разрешены.
Код
void TIM4_IRQHandler(void)
{
  uint32_t tmp = TIM4->SR;
  tmp &= TIM4->DIER;
  TIM4->SR = 0;
  if( tmp & TIM_SR_UIF )    ...
  if( tmp & TIM_SR_CC1IF )  ...
  if( tmp & TIM_SR_CC2IF )  ...

или сразу uint32_t tmp = TIM4->SR & TIM4->DIER;
но тогда может выдать предупреждение
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
alex_avr2
сообщение Feb 15 2013, 13:12
Сообщение #6





Группа: Новичок
Сообщений: 4
Регистрация: 24-11-12
Пользователь №: 74 538



Цитата(SSerge @ Feb 15 2013, 15:08) *
Чтобы реагировать только на флаги от которых разрешены прерывания можно использовать содержимое DIER как маску.
или просто вручную (константой) маскировать флаги у которых прерывания не разрешены.
Код
void TIM4_IRQHandler(void)
{
  uint32_t tmp = TIM4->SR;
  tmp &= TIM4->DIER;
  TIM4->SR = 0;
  if( tmp & TIM_SR_UIF )    ...
  if( tmp & TIM_SR_CC1IF )  ...
  if( tmp & TIM_SR_CC2IF )  ...

или сразу uint32_t tmp = TIM4->SR & TIM4->DIER;
но тогда может выдать предупреждение
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined

Ага, спасибо, так и понял. В моем случае конфигурация прерываний не меняется, всегда нужны только два, так что просто ненужные флаги не проверяю и не очищаю.
Но принцип понятен.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 15 2013, 15:09
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



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


ну да для регистров не реагирующих на 1, можно делать не &=(~MASK), а сразу =(~MASK), но я думаю тут уже играет роль привычка, пару лишних тактов обычно не критично, зато несколько больше переносимость кодов, да и при совместной разработке, другой программист взяв код не будет радостно кричать что нашел ошибку, и ему не понадобиться лезть в мануал проверять так ли тут все! Иногда это важнее 2 тактов...
Go to the top of the page
 
+Quote Post
alex_avr2
сообщение Feb 15 2013, 15:43
Сообщение #8





Группа: Новичок
Сообщений: 4
Регистрация: 24-11-12
Пользователь №: 74 538



Цитата(Golikov A. @ Feb 15 2013, 19:09) *
ну да для регистров не реагирующих на 1, можно делать не &=(~MASK), а сразу =(~MASK), но я думаю тут уже играет роль привычка, пару лишних тактов обычно не критично, зато несколько больше переносимость кодов, да и при совместной разработке, другой программист взяв код не будет радостно кричать что нашел ошибку, и ему не понадобиться лезть в мануал проверять так ли тут все! Иногда это важнее 2 тактов...

Только если во время этого самого "&=(~MASK)" выставится еще какой-то флаг, то он может превратиться в тыкву и мы о нем не узнаем. Не зря разработчики СТ сделали именно такую очистку флагов, одной записью, атомарно.

Сообщение отредактировал alex_avr2 - Feb 15 2013, 15:44
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 15 2013, 16:49
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ваша правда! что-то я не подумал сразу о таком исходе...
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01426 секунд с 7
ELECTRONIX ©2004-2016