Перейти к содержанию
    

Что бы проверить работу таймера в режиме энкодера я решил эмулировать на двух ножках AB сигналы.

void TIM7_IRQHandler(void)
{
   switch (enc_state)
   {
       case 0:
           GPIOF->BSRR = GPIO_Pin_9;   //1
           GPIOF->BRR = GPIO_Pin_10;   //0
       break;
       case 1:
           GPIOF->BSRR = GPIO_Pin_9;   //1
           GPIOF->BSRR = GPIO_Pin_10;  //1
       break;
       case 2:
           GPIOF->BRR = GPIO_Pin_9;   //0
           GPIOF->BSRR = GPIO_Pin_10; //1
       break;
       case 3:
           GPIOF->BRR = GPIO_Pin_9;   //0
           GPIOF->BRR = GPIO_Pin_10; //0
       break;
   }
   
   if(enc_state == 3)
     enc_state = 0;
   else
     enc_state++;
   
   TIM7->SR = 0;
}

По идее должно работать как на картинке, сигналы сдвинуты на 90 градусов, но на скопе я вижу сигналы в одной фазе. Это скоп так показывает или у меня ошибка?

post-71075-1500875105_thumb.jpg

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задайте состояния выходов для энкодера таблицей.

И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция.

(закрашенные сектора на диске - таже таблица)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задайте состояния выходов для энкодера таблицей.

И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция.

(закрашенные сектора на диске - таже таблица)

это то что я делаю в коде - прокручиваю состояния каждый тайм слот (1-2-3-4).

 

снизил частоту и подключил светодиоды на выходы. мигают одновременно. значит скоп тут не виноват.

 

пробовал выставлять выход через ODR

void TIM7_IRQHandler(void)
{
   switch (enc_state)
   {
       case 0:
           //ENC_PORT->BSRR |= ENC_PIN_A;  //1
           //ENC_PORT->BRR |= ENC_PIN_B;   //0
           ENC_PORT->ODR = 0x200;
       break;
       case 1:
           //ENC_PORT->BSRR |= ENC_PIN_A;  //1
           //ENC_PORT->BSRR |= ENC_PIN_B;  //1
             ENC_PORT->ODR = 0x600;
       break;
       case 2:
           //ENC_PORT->BRR |= ENC_PIN_A;   //0
           //ENC_PORT->BSRR |= ENC_PIN_B;  //1
           ENC_PORT->ODR = 0x400;
       break;
       case 3:
           //ENC_PORT->BRR |= ENC_PIN_A;   //0
           //ENC_PORT->BRR |= ENC_PIN_B;   //0
         ENC_PORT->ODR = 0x000;
          
       break;
   }
   
   if(enc_state == 3)
     enc_state = 0;
   else
     enc_state++;
   
   TIM7->SR = 0;
}

тот же результат

 

если я ставлю 4 брекпойнта - в каждом кейсе - то я вижу что состояния выходов меняются по таблице (10 11 01 00). но когда код бежит они мигают одновременно.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

скорее всего глючек не в приведенном коде, а "наружи",

в виде "накладки" нескольких выдач в порт.

Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные

фазы выдачи.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

скорее всего глючек не в приведенном коде, а "наружи",

в виде "накладки" нескольких выдач в порт.

Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные

фазы выдачи.

я вывел ножки на светодиоды. частота мигания раз в 4 секунды. тут невооруженным глазом все видно. что интересно что по брейкпоинтам отрабатывается правильно - первый зажигается потом второй первый гаснет потом второй. а без остановок зажигаются и гаснут одновременно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А таймер случайно в ту же ногу не выдает импульсы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А таймер случайно в ту же ногу не выдает импульсы?

нет. я вижу два светодиода мигают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут прерывание срабатывает два раза.

После команды сброса флажка прерывания надо что-то типа __DSB(); или просто несколько nop'ов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут прерывание срабатывает два раза.

После команды сброса флажка прерывания надо что-то типа __DSB(); или просто несколько nop'ов.

О! __DSB(); помогло, спасибо. а что эта инструкция делает?

 

описание такое

The Data Synchronization Barrier (DSB) acts as a special kind of memory barrier. The DSB operation will complete when all explicit memory accesses before this instruction have completed. No instructions after the DSB will be executed until the DSB instruction has completed, that is, when all of the pending accesses have completed.

 

но как это влияет на обработку прерывания?

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз.

понял. спасибо.

 

если сбрасывать флаг TIM7->SR = 0; вначале прерывания а не в конце тоже помогает. чудеса.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

до 4kHz выставлял

 

я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

. . .

я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты.

я посмотрел бы на приоритеты прерываний + errata.pdf :)

ps - А что за чип ?

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я посмотрел бы на приоритеты прерываний + errata.pdf :)

ps - А что за чип ?

а при чем тут прерывания.

чип STM32F303VCT6. при частоте энкодера 400 герц счетчик переполняется за минуту. у меня может возникнуть система с большим прогоном , больше минуты. логически было предположить что входные сигналы A/B можно поделить чтоб увеличить дальность. но я такой опции не нашел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...