jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 (изменено) · Жалоба Что бы проверить работу таймера в режиме энкодера я решил эмулировать на двух ножках 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 градусов, но на скопе я вижу сигналы в одной фазе. Это скоп так показывает или у меня ошибка? Изменено 24 июля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба Задайте состояния выходов для энкодера таблицей. И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция. (закрашенные сектора на диске - таже таблица) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 (изменено) · Жалоба Задайте состояния выходов для энкодера таблицей. И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция. (закрашенные сектора на диске - таже таблица) это то что я делаю в коде - прокручиваю состояния каждый тайм слот (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). но когда код бежит они мигают одновременно. Изменено 24 июля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба скорее всего глючек не в приведенном коде, а "наружи", в виде "накладки" нескольких выдач в порт. Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные фазы выдачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба скорее всего глючек не в приведенном коде, а "наружи", в виде "накладки" нескольких выдач в порт. Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные фазы выдачи. я вывел ножки на светодиоды. частота мигания раз в 4 секунды. тут невооруженным глазом все видно. что интересно что по брейкпоинтам отрабатывается правильно - первый зажигается потом второй первый гаснет потом второй. а без остановок зажигаются и гаснут одновременно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба А таймер случайно в ту же ногу не выдает импульсы? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба А таймер случайно в ту же ногу не выдает импульсы? нет. я вижу два светодиода мигают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба Тут прерывание срабатывает два раза. После команды сброса флажка прерывания надо что-то типа __DSB(); или просто несколько nop'ов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 (изменено) · Жалоба Тут прерывание срабатывает два раза. После команды сброса флажка прерывания надо что-то типа __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. но как это влияет на обработку прерывания? Изменено 24 июля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 (изменено) · Жалоба Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз. понял. спасибо. если сбрасывать флаг TIM7->SR = 0; вначале прерывания а не в конце тоже помогает. чудеса. Изменено 24 июля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба А частота какая? Странно, что такой небольшой кусок кода не успевает выполниться между переполнениями таймера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 (изменено) · Жалоба А частота какая? Странно, что такой небольшой кусок кода не успевает выполниться между переполнениями таймера. до 4kHz выставлял я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты. Изменено 24 июля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба . . . я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты. я посмотрел бы на приоритеты прерываний + errata.pdf :) ps - А что за чип ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 июля, 2017 Опубликовано 24 июля, 2017 · Жалоба я посмотрел бы на приоритеты прерываний + errata.pdf :) ps - А что за чип ? а при чем тут прерывания. чип STM32F303VCT6. при частоте энкодера 400 герц счетчик переполняется за минуту. у меня может возникнуть система с большим прогоном , больше минуты. логически было предположить что входные сигналы A/B можно поделить чтоб увеличить дальность. но я такой опции не нашел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться