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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> stm32F429 и прерывание от таймера
zorromen
сообщение Jul 22 2015, 17:49
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



Здравствуйте, только начал осваивать проц, и столкнулся с непоняткой, уже 3 дня сижу и не могу понять.
Есть Выход
Код
   //Trigger
  /*Configure GPIO pin : PE3 */
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

Есть таймер 6, его настройка.
Код
    __TIM6_CLK_ENABLE();
    UV_state = 0;
        HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
    
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
    TIM6->PSC = 143;
    TIM6->ARR = 62499; //100 mS
    //TIM6->EGR = TIM_EGR_UG;
    TIM6->DIER = TIM_DIER_UIE;
    TIM6->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE;

Это прерывание
CODE
void TIM6_DAC_IRQHandler(void)
{
TIM6->CR1 &= ~TIM_CR1_CEN; //Остнавливаем таймер
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF

switch (UV_state)
{
case 0:
TIM6->PSC = 0;
TIM6->ARR = 0x707;//1799; //20 uS
TIM6->CNT = 0;
TIM6->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
UV_state = 1;
break;

case 1:
TIM6->PSC = 0x008f;//143
TIM6->ARR = 0xF423;//62499; //Ñðàáîòàòü íà 100 mS
TIM6->CNT = 0;
TIM6->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
UV_state = 0;
break;
}

}

Хочу иметь импульс 20 us через 100 ms, и вроде все логично, но на выходе все перевернуто
Прикрепленное изображение


Ну где тут можно ошибиться?
Заходим по состоянию 0, устанавливаем таймер на 20 us и устанавливаем ногу в 1, чтобы в следующем прерывании ее сбросить и настроить прерывание на 100 ms и потом ее установить в 1 в новом прерывании. Почему на выходе все наоборот?

Сообщение отредактировал IgorKossak - Jul 23 2015, 16:34
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jul 22 2015, 18:15
Сообщение #2


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

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



Наводящий вопрос: за что отвечает бит TIM_CR1_ARPE
и как работает запись в TIM6->ARR когда этот бит установлен?


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jul 22 2015, 18:40
Сообщение #3


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Предлагаю ещё посмотреть внимательно даташит на тему как сбрасыаать флаги прерываний в таймерах...
В Вашем случае возможны потери прерываний (если другие ещё флаги потребуются).

Небольшой пример из моего кода:
Код
    void
    TIM3_IRQHandler(void)
    {
        const uint_fast32_t st = TIM3->SR;
        if ((st & TIM_SR_UIF) != 0)
        {
            TIM3->SR = ~ TIM_SR_UIF;    // clear UIF interrupt request
            handle_timer_imterrupt();
        }
        // проверяем другие флаги в st
    }
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 22 2015, 18:54
Сообщение #4


Гуру
******

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



и если еще умничать, то это ШИМом делается, а не через прерывания... хотя думаю на самом деле это просто тестsm.gif
Go to the top of the page
 
+Quote Post
zorromen
сообщение Jul 23 2015, 01:16
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



Шим не подойдет, т.к. прерывание будет усложнятся и будут добавленны еще условия которые будут зависить от переферии. А какие еще флаги кроме UIF могут быть установленустановлены? Вот думаю может исрользовать режим импульса, по идее он точно один раз попадет в прерывание. Ну а вообще если логически подумать, приведеный код должен формировать импульс, может в коде ошибаюсь? На счет обновления ARR при установленном ARPE, ничего сказать не смогу т.к. начал изучение только недавно, но попробовать можно, сбросить этот бит и после обновить ARR и установить этот бит.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 23 2015, 05:33
Сообщение #6


Гуру
******

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



какие флаги могут быть еще?
Да какие угодно, проект будет жить, развиваться, появятся еще обработчики... да это просто надо взять себе за правило, что регистры для сброса прерывания записываются только одним значением, потому не надо делать
&= или |= вам не нужно начальное состояние регистра, просто равно и все. Это правило! Плюс запись атомарная, в отличии от &= и |=. Если очень хочется могу в очередной раз написать как возникает проблемаsm.gif

Цитата
код должен формировать импульс, может в коде ошибаюсь

Да ошибаетесь, и именно в кодеsm.gif с битами ARPE, вам намекают на буферезированный режим обновления конца счетчика. То есть когда вы пишите обновить регистр вы обновляете его не мгновенно, а только когда таймер досчитает до заданного значения. Вот и получилось что когда вы пишите 100, таймер до ходит до прошлого 20, и только потом начинает считать до 100, а вы ему пишите 20, он дойдет до 100 и заменит на 20, потому у вас все по фазе и съехало...
Go to the top of the page
 
+Quote Post
zorromen
сообщение Jul 23 2015, 12:14
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



Можете помочь как нужно написать чтобы работало.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 23 2015, 12:28
Сообщение #8


Гуру
******

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



ну либо поменяйте местами присвоения, либо присвояемое, либо уберите флаг буферезированной загрузки.

то есть в случае если у вас буферезированная загрузка будет все так:
допустим таймер считает до 20, досчитал, возникло прерывание
в прерывании таймер пошел дальше, вы задаете значение 100, но оно не применяется за за буфера
таймер досчитывает до 20, возникает очередное прерывание и он применяет ранее заданное 100
в прерывании таймер пошел дальше, вы задаете число 20, но оно не применяется из за буфера
таймер досчитывает до 100, возникает очередное прерывание и он применяет ранее заданное 20
в прерывании таймер пошел дальше....

вот что у вас происходит, то есть когда вы в таймер пишите 100 это число на следующих ход, учитывайте это или отключите буфер
Go to the top of the page
 
+Quote Post
zorromen
сообщение Jul 23 2015, 13:15
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



Но ведь PSC тоже с буфером, и он вроде не отключается, и логично чтобы ARR и PSC обновились одновременно, чувствую что нужно использовать UG, но как не понял.
Если не трогать вообще PSC, то все работает, управляется ARR без буфера, а если нужно менять еще и PSC?

Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 23 2015, 13:39
Сообщение #10


Гуру
******

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



так для того буфер и сделан, чтобы вы успели все задать и все сменилось одновременно..


у вас сейчас логика
задали режим 1, выставили сигнал 1
дождались прерывания
задали режим 2, выставили сигнал 2
и так далее


а должна быть
задали режим инициализации(просто какой то интервал, чтобы успеть задать настройки), подготовились к режиму 1
дождались прерывания (тут применяться настройки режима 1)
подготовились к режиму 2, задали сигнал 1
дождались прерывания (тут применяться настройки режима 2)
подготовились к режиму 1, задали сигнал 2
и так далее



Go to the top of the page
 
+Quote Post
SSerge
сообщение Jul 23 2015, 14:29
Сообщение #11


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

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



В процессе инициализации полезно "вручную" сгенерировать update event при котором произойдёт загрузка из теневых регистров.
Код
  TIM1->ARR = xxx;
  //и прочие настройки
  TIM1->EGR   = TIM_EGR_UG; // генерируем update event для загрузки из всех теневых регистров
  TIM1->CR1 |= TIM_CR1_CEN;   // разрешаем счёт


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
zorromen
сообщение Jul 23 2015, 15:01
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



А если это делать в прерывании, не вызовет ли это прерывание снова? Пока проверить не могу.
Go to the top of the page
 
+Quote Post
zorromen
сообщение Jul 23 2015, 18:41
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 13-12-05
Пользователь №: 12 147



Упорство победило, если хотят играть по своим правилам, то по ним и с играем. После настройки в прерывании регистров, создаю новое прерывание и ref_register=1, в него заходим сразу после данного прерывания и тем самым обновляем теневые регистры PSC и ARR, и все заработало как нужно. Очень странно видеть, что сколько читал русскую документацию, не все объясняется, только в даташите нашел, что PSC тоже имеет теневой регистр.

Настройка
CODE
TIM6->PSC = 143;
TIM6->ARR = 62499; //100 mS
TIM6->DIER = TIM_DIER_UIE;
TIM6->CR1 |= TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_ARPE;

void TIM6_DAC_IRQHandler(void)
{
if (ref_register == 0)
{
switch (UV_state)
{
case 0:
TIM6->PSC = 0;
TIM6->ARR = 0x707;//1799; //20 uS
TIM6->CNT = 0;
TIM6->EGR = TIM_EGR_UG; //Создать прерывание для обновления регистров
ref_register = 1; //Обновить регистры
TIM6->CR1 |= TIM_CR1_CEN;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
UV_state = 1;
break;

case 1:
TIM6->PSC = 0x008f;//143
TIM6->ARR = 0xF423;//62499; // 100 mS
TIM6->CNT = 0;
ref_register = 1; //Обновить регистры
TIM6->EGR = TIM_EGR_UG; //Создать прерывание для обновления регистров
TIM6->CR1 |= TIM_CR1_CEN;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);
UV_state = 0;
break;
}
}
else
{
TIM6->SR = 0;
ref_register = 0;
}
}


Сообщение отредактировал IgorKossak - Jul 24 2015, 08:26
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 24 2015, 02:38
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(zorromen @ Jul 24 2015, 00:41) *
Очень странно видеть, что сколько читал русскую документацию, не все объясняется, только в даташите нашел, что PSC тоже имеет теневой регистр.

"Не читайте по утрам советских газет" © профессор Преображенский biggrin.gif
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 24 2015, 04:22
Сообщение #15


Гуру
******

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



надеюсь вы понимаете принципиальную разницу в работе с принудительном обновлении после задания по сравнению со штатной работой.

Цитата
очень странно видеть, что сколько читал русскую документацию, не все объясняется, только в даташите нашел, что PSC тоже имеет теневой регистр.

тут даже комментировать не хочется...
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 02:27
Рейтинг@Mail.ru


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