Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2017-дек-18 08:15

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.
Автор Сообщение
СообщениеДобавлено: 2017-дек-01 21:59 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Проектируется изделие на МК 1986ВЕ92У. На один из входов изделия поступает
длинный (десятки микросекунд) импульс, по обоим фронтам которого нужно про-
изводить некоторые действия. Для этой цели использую вход 4 канала таймера
TIMER3 (PB-07). Вообще было бы, наверное, проще использовать вход ETR, но в
64-выводном корпусе для этого доступен лишь вывод PA-04, а он используется
для отладки по JTAG-A.

Рассматриваю основной режим работы, в котором этот импульс транслируется в
прямом виде на инверсный выход канала 4 (PB-08), в других режимах на этот
выход может постоянно подаваться низкий или высокий уровень...

Сначала настраиваю таймер на обнаружение переднего фронта:

Код:
MDR_TIMER3->PSG  = 0;
MDR_TIMER3->CNT  = 0;     // считать с 0
MDR_TIMER3->ARR  = 2;     // считать до 2
MDR_TIMER3->CCR1 = 65535; // запрет сравнения в канале 1
MDR_TIMER3->CCR2 = 65535; // запрет сравнения в канале 2
MDR_TIMER3->CCR3 = 65535; // запрет сравнения в канале 3
MDR_TIMER3->CCR4 = 1;     // формировать REF при CNT == 1
MDR_TIMER3->CH4_CNTRL  = TIMER_CH_MODE_PWM    //  работа канала 4 в режиме ШИМ
                       | TIMER_CH_REF_Format1 //  REF = 1 если CNT == CCR
                       | TIMER_CH_EvSrc_PE;   //  ждать положительный фронт на входе канала
MDR_TIMER3->CH4_CNTRL1 = (TIMER_CH_OutMode_Input <<  0)     // прямой выход канала 4 на выход не работает
                       | (TIMER_CHOPolarity_Inverted << 12) // инв.выход деинвертируется
                       | (TIMER_CH_OutSrc_REF << 10)        // на инв.выход подается сигнал REF
                       | (TIMER_CH_OutMode_Output <<  8);   // инв.выход канала 4 всегда работает на выход
MDR_TIMER3->CH4_CNTRL2 = TIMER_CH_CCR_Update_Immediately;   // немедленное обновление CCR
MDR_TIMER3->STATUS = 0;   // сброс событий таймера
MDR_TIMER3->CNTRL  = TIMER_CntMode_EvtFixedDir       // счет внешних событий
                   | TIMER_CntDir_Up                 // счет вверх
                   | TIMER_EvSrc_CH4                 // считать события на канале 4
                   | TIMER_ARR_Update_Immediately    // обновлять ARR немедленно
                   | TIMER_CNTRL_CNT_EN;             // включить TIMER3
MDR_TIMER3->IE = 8 << TIMER_IE_CCR_REF_EVENT_IE_Pos; // прерывание по совпадению в канале 4

Далее в обработчике прерываний таймера TIMER3 проверяю, какое прерывание
произошло. Если по совпадению в канале 4, перенастраиваю таймер TIMER3 на
обнаружение заднего фронта, а если по достижению ARR, то выключаю таймер:

Код:
s = MDR_TIMER3->STATUS;  // запомнить события в регистре состояния
MDR_TIMER3->STATUS  = 0; // сброс событий таймера
if (s & TIMER_STATUS_CNT_ARR_EVENT)
{ // Достигнут предел счета:
  MDR_TIMER3->CNTRL = 0; // выключить таймер
  MDR_TIMER3->CNT   = 0; // сбросить счетчик
  MDR_TIMER3->IE    = 0; // запретить прерывания
  ...
} else
if (s & TIMER_STATUS_CCR_REF_CH4)
{ // Совпадение в канале 4:
  MDR_TIMER3->CH4_CNTRL  = TIMER_CH_MODE_PWM    // работа канала 4 в режиме ШИМ
                         | TIMER_CH_REF_Format1 // REF = 1 если CNT == CCR
                         | TIMER_CH_EvSrc_NE;   // ждать отрицательный фронт на входе канала
  MDR_TIMER3->IE = TIMER_IE_CNT_ARR_EVENT_IE;   // прерывание по счетчику
  ...
}

В результате при работе передний фронт импульса на входе канала
обнаруживается и в данном режиме транслируется на выход канала,
а вот прерывание по заднему фронту никогда не происходит, и на
выходе канала остаётся высокий уровень, пока "будильник" не
сбросит таймер TIMER3.

Что я делаю не так?

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-02 11:35 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1039
Откуда: Тула
Может стоит разрешить прерывание по переполнению счётчика?
Код:
MDR_TIMER3->IE = (8 << TIMER_IE_CCR_REF_EVENT_IE_Pos) | (1<<2); // прерывание по совпадению в канале 4 ИЛИ событию cnt==arr

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-02 12:50 
Не в сети

Зарегистрирован: 2010-сен-21 12:57
Сообщения: 641
Откуда: г. Санкт-Петербург
stranderer писал(а):
...
Что я делаю не так?

Для фиксации фронтов канал таймера д.б. запрограммирован в режиме "захват".
Бит 15 регистра MDR_TIMER3->CH4_CNTRL д.б. = 1.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-03 16:45 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Спасибо, попробую режим захвата...

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 12:36 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Хм... Попробовал... Правда сразу возникли сомнения, будет ли в режиме Захват работать выход канала? На всякий случай оставил настройки выхода почти без изменений, чтоб посмотреть, что туда выведется. Однако посмотреть не удалось, т.к. при новых настройках программа вообще не запустилась :-( Не завёлся ни основной цикл временнОй диаграммы на таймере TIMER2, ни даже цикл Автотестирования на таймере TIMER1, в котором генерируются синхросигналы, команды в UART1 и входные данные для устройства.
Новый код выглядит примерно так:

Код:
  // Начальная установка таймера:
  MDR_TIMER3->PSG        = 0;                                  // предделитель = 1
  MDR_TIMER3->ARR        = 1;                                  // конечное значение счетчика
  MDR_TIMER3->CH4_CNTRL1 = (TIMER_CH_OutMode_Input     <<  0)  // прямой выход канала 4 на выход не работает
                         | (TIMER_CHOPolarity_Inverted << 12)  // инв.выход деинвертируется
                         | (TIMER_CH_OutSrc_Only_1     << 10)  // на инв.выход подается "0" (выкл.Строб)
                         | (TIMER_CH_OutMode_Output    <<  8); // инв.выход канала 4 всегда работает на выход
  MDR_TIMER3->CH4_CNTRL2 = TIMER_CH_CCR_Update_Immediately     // немедленное обновление CCR (default)
                         | TIMER_CH_CNTRL2_CCR1_EN             // разрешение работы CCR1
                         | TIMER_CH_CCR1EvSrc_NE;              // захват отр.фронта в CCR1
  MDR_TIMER3->CCR1       = MaxTime;                            // запрет сравнения в канале 1
  MDR_TIMER3->CCR2       = MaxTime;                            // запрет сравнения в канале 2
  MDR_TIMER3->CCR3       = MaxTime;                            // запрет сравнения в канале 3
  MDR_TIMER3->CCR4       = 1;                                  // порог включения REF в канале 4
// ---------------------------------------------------------------------------
  // Перенастройка таймера
// ...........................................................................
  // Выключение таймера:
  MDR_TIMER3->STATUS     = 0;                                  // сброс событий таймера
  MDR_TIMER3->CNT        = 0;                                  // считать вверх с "0"
  MDR_TIMER3->CH4_CNTRL  = TIMER_CH_ETR_RESET_Disable          // запрет сброса по ETR (default)
                         | TIMER_CH_BRK_RESET_Disable          // запрет сброса по BRK (default)
                         | TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                         | TIMER_CH_REF_Format3                // переключение REF при CNT == CCR
  MDR_TIMER3->CNTRL      = 0;                                  // сброс управления TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                           // сброс флага ожидания прерываний
  MDR_TIMER3->IE         = 0;                                  // запрет прерываний
// ...........................................................................
  // Ожидание переднего фронта:
  MDR_TIMER3->STATUS     = 0;                                  // сброс событий таймера
  MDR_TIMER3->CNT        = 0;                                  // считать вверх с "0"
  MDR_TIMER3->CH4_CNTRL  = TIMER_CH_ETR_RESET_Disable          // запрет сброса по ETR (default)
                         | TIMER_CH_BRK_RESET_Disable          // запрет сброса по BRK (default)
                         | TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                         | TIMER_CH_REF_Format3                // переключение REF при CNT == CCR
                         | TIMER_CH_EvSrc_PE;                  // ждать полож.фронт на входе канала
  MDR_TIMER3->CNTRL      = TIMER_CntMode_EvtFixedDir           // счет внеш.событий
                         | TIMER_CntDir_Up                     // счет вверх
                         | TIMER_EvSrc_CH4                     // считать события на канале 4
                         | TIMER_ARR_Update_Immediately        // обновлять ARR немедленно (default)
                         | TIMER_CNTRL_CNT_EN;                 // включить TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                           // сброс флага ожидания прерываний
  MDR_TIMER3->IE         = 8 << TIMER_IE_CCR_CAP_EVENT_IE_Pos; // прерывание по переднему фронту
// ...........................................................................
  // Ожидание заднего фронта:
  MDR_TIMER3->STATUS     = 0;                                  // сброс событий таймера
  MDR_TIMER3->CNT        = 1;                                  // считать вверх с "1"
  MDR_TIMER3->CH4_CNTRL  = TIMER_CH_ETR_RESET_Disable          // запрет сброса по ETR (default)
                         | TIMER_CH_BRK_RESET_Disable          // запрет сброса по BRK (default)
                         | TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                         | TIMER_CH_REF_Format3                // переключение REF при CNT == CCR
                         | TIMER_CH_EvSrc_NE;                  // ждать отриц.фронт на входе канала
  MDR_TIMER3->CNTRL      = TIMER_CntMode_EvtFixedDir           // счет внеш.событий
                         | TIMER_CntDir_Up                     // счет вверх
                         | TIMER_EvSrc_CH4                     // считать события на канале 4
                         | TIMER_ARR_Update_Immediately        // обновлять ARR немедленно (default)
                         | TIMER_CNTRL_CNT_EN;                 // включить TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                           // сброс флага ожидания прерываний
  MDR_TIMER3->IE         = 8 << TIMER_IE_CCR1_CAP_EVENT_IE_Pos;// прерывание по заднему фронту
// ---------------------------------------------------------------------------
  // Обработчик прерывания TIMER3:
  s                   = MDR_TIMER3->STATUS; // запомнить события в регистре состояния таймера
  MDR_TIMER3->STATUS  = 0;                  // сброс событий таймера
  if (s & TIMER_STATUS_CCR_CAP1_CH4)
  {                                         // задний фронт:
    MDR_TIMER3->CNTRL = 0;                  // выключить таймер
    MDR_TIMER3->CNT   = 0;                  // сбросить счетчик
    NVIC_ClearPendingIRQ(TIMER3_IRQn);      // сбросить флаг ожидания прерываний
    MDR_TIMER3->IE    = 0;                  // запретить прерывания
    ...
  } else
  if (s & TIMER_STATUS_CCR_CAP_CH4)
  {                                                             // передний фронт:
    MDR_TIMER3->CH4_CNTRL = TIMER_CH_ETR_RESET_Disable          // запрет сброса по ETR (default)
                          | TIMER_CH_BRK_RESET_Disable          // запрет сброса по BRK (default)
                          | TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                          | TIMER_CH_REF_Format3                // переключение REF при CNT == CCR
                          | TIMER_CH_EvSrc_NE;                  // ждать отриц.фронт на входе канала
    NVIC_ClearPendingIRQ(TIMER3_IRQn);                          // сбросить флаг ожидания прерываний
    MDR_TIMER3->IE        = 8 << TIMER_IE_CCR1_CAP_EVENT_IE_Pos;// прерывание по заднему фронту
    ...
  }


Пока не успел посмотреть в отладчике, где именно программа останавливается. На экране логического анализатора ничего нет, т.к. он запускается началом цикла Автотестирования, который в этом режиме почему-то не заработал.

Перечитал в спецификации МК раздел "Таймеры общего назначения". В подразделе "Внешний тактовый сигнал режим 1. События на линиях TxCHi данного счетчика" (стр.261) чёрным по русскому написано: "Счётчик может считать по положительному фронту или по отрицательному фронту на выбранном входе или по положительному фронту на других каналах" и далее на рисунке 71 ясно виден детектор фронтов на входе канала, а на рисунке 72 показаны варианты счёта как по положительному, так и по отрицательному фронту при разных значениях входного фильтра. И ни слова о том, что для этого канал должен обязательно работать в режиме захвата. А вот про выбор источника выхода канала как раз написано, что это в режиме ШИМ.

Теперь осталось понять, что же было не так в первоначальном коде, где канал работает в режиме ШИМ, но почему-то видит только положительный фронт, а отрицательный не видит...

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 12:55 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
prostoRoman, это прерывание при ожидании отрицательного фронта разрешено в последней строке кода:

Код:
MDR_TIMER3->IE = TIMER_IE_CNT_ARR_EVENT_IE;   // прерывание по счетчику

засада в том, что оно в данном случае не срабатывает. Я останавливался в отладчике при срабатывании "будильника" через 140 мкс после окончания входного импульса, и там таймер по-прежнему включен, в счётчике таймера "1", а не "2", в статусе только совпадение в канале 4 (т.к. по-прежнему CNT == CCR), и внутренний флаг в программе показывает, что импульс всё ещё не кончился. Т.е. таймер вроде был настроен на работу по отрицательному фронту на входе канала, но по непонятной мне причине не увидел этого фронта

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 13:10 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1039
Откуда: Тула
stranderer писал(а):
Вообще было бы, наверное, проще использовать вход ETR, но в
64-выводном корпусе для этого доступен лишь вывод PA-04, а он используется
для отладки по JTAG-A.

При работе в режиме SWD можно использовать PA-04 как gpio. Так что пробуйте.

В остальном же нужно поколдовать с режимами работы таймеров и ЦЦР. Я вот выловил баг, что при НЕ установленном бите MDR_TIMERx->CHy_CNTRL2 CCR1_EN основной CCR не ловит падающие фронты.

Удобно потыкать галочки в разделе периферии кейла на рабочем железе.

_________________
сочувствующий…


Последний раз редактировалось prostoRoman 2017-дек-05 14:39, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 13:40 
Не в сети

Зарегистрирован: 2010-сен-21 12:57
Сообщения: 641
Откуда: г. Санкт-Петербург
stranderer писал(а):
Хм... Попробовал... Правда сразу возникли сомнения, будет ли в режиме Захват работать выход канала? ...

Думаю, что не будет.
Режим захват подразумевает работу канала на вход.
Режим ШИМ - подразумевает работу канала на выход.
Соответственно разное функциональное назначение регистров CCR,CCR1 для разных режимов работы.
Ваше решение формировать запрос прерывания по фронтам внешних импульсов на входе канала таймера, работающего в режиме ШИМ представляется нестандартным и возможно не реализуемым в данном МК.
Советую изменить решение и фиксировать фронты импульсов в режиме захват (здесь проблем не должно быть - проверено неоднократно). При этом режим ШИМ можете реализовать на другом канале.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 18:25 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Спасибо, prostoRoman, у меня как раз та же ситуация: CCR1 не разрешён, при этом отрицательный фронт не ловится.
Завтра попробую...

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-05 19:55 
Не в сети

Зарегистрирован: 2010-сен-21 12:57
Сообщения: 641
Откуда: г. Санкт-Петербург
stranderer писал(а):
Спасибо, prostoRoman, у меня как раз та же ситуация: CCR1 не разрешён, при этом отрицательный фронт не ловится.
Завтра попробую...

Попробовал реализовать вашу ситуацию на отладочной плате.
Промежуточный вывод - источником событий с вывода канала 4 таймера 3 для счета таймера 3 может быть только фронт, независимо от состояния поля CHSEL(00 или 01) регистра CH4_CNTRL. На спад счетчик таймера не реагирует ни при каких уставках.
Для уточнения этой ситуации советую обратиться в службу техподдержки.
P.S. В режиме захват фронт и спад фиксируются без проблем.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-06 00:49 
Не в сети

Зарегистрирован: 2016-окт-14 19:39
Сообщения: 31
Откуда: СПБ
В моем понимании, выход ШИМ и вход захвата - взаимоисключающие вещи. Попробуйте вход/выход делать на разных каналах.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-06 09:36 
Не в сети

Зарегистрирован: 2010-сен-21 12:57
Сообщения: 641
Откуда: г. Санкт-Петербург
СП Версия 3.10.0 от 04.10.2016
стр.279:

Внешний тактовый сигнал «Режим 1». События на линиях TxCHO
данного счетчика

Этот режим выбирается, когда EVENT_SEL = 01xx в регистре CNTRL. Счетчик считает
только по переднему фронту (см. Рисунок 74). Биты CHSEL[1:0] регистра MDR_TIMERx-
>CHy_CNTRL не имеют значения. Канал таймера работает с битами CHSEL[1:0] только в
режиме захвата, генерируя прерывание по соответствующему фронту.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-07 10:44 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Вероятно, у меня более старый вариант спецификации, там не так написано...
В любом случае всем спасибо за содействие!
Эксперименты действительно показали, что в режиме ШИМ счётчик работает только по положительному фронту на входе канала или ETR, в режиме захвата ловятся оба фронта, но, разумеется, на выходе канала при этом ничего нет. Пока что перенастроил этот вывод как просто выход порта и сигнал на нём задаю в обработчике прерывания. Правда, при этом задержка со входа на выход выросла с 0.11 до 1.35 мкс, чему заказчик не особо рад. При отключении всяческой отладки это время уменьшится, но если всё равно будет много, придётся переделывать схему и использовать выход канала 1 через вывод PE-02 или 03, которые пока что заняты

_________________
Странник


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-07 11:17 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1039
Откуда: Тула
stranderer писал(а):
...вывод как просто выход порта и сигнал на нём задаю в обработчике прерывания. Правда, при этом задержка со входа на выход выросла с 0.11 до 1.35 мкс...

Многовато... Увеличьте тактовую и установите приемлемую EEPROM_Delay (оптимально 2 такта паузы на частотах до 75 МГц). Посмотрите ассемблерный код, установите оптимизацию минимум О2, выполняйте минимум действий от входа прерывания до установки сигнала. На вскидку можно уменьшить до 0,5 мкс.

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2017-дек-08 19:30 
Не в сети
Аватара пользователя

Зарегистрирован: 2013-июн-21 15:27
Сообщения: 76
Откуда: Новосибирск
Я попробовал на отл.плате вместо программного задействовать аппаратное формирование выходного импульса с помощью канала 1, работающего в режиме ШИМ. В остальном код почти не изменился.

Начальная установка таймера:

Код:
  MDR_TIMER3->STATUS     = 0;                                   // сброс событий таймера
  MDR_TIMER3->PSG        = 0;                                   // предделитель = 1
  MDR_TIMER3->ARR        = 2;                                   // конечное значение счетчика
  MDR_TIMER3->CNT        = 0;                                   // считать вверх с "0"
  MDR_TIMER3->CNTRL      = 0;                                   // сброс управления TMRr
  MDR_TIMER3->IE         = 0;                                   // запрет прерываний
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  MDR_TIMER3->CH1_CNTRL  = TIMER_CH_MODE_PWM                    // работа канала 1 в режиме ШИМ
                         | TIMER_CH_REF_Format1;                // REF == 1 при CNT == CCR
  MDR_TIMER3->CH1_CNTRL1 = (TIMER_CH_OutMode_Output       << 0) // прямой выход канала 1 всегда работает на выход
                         | (TIMER_CH_OutSrc_Only_0        << 2) // на прямой выход подается "0" (default)
                         | (TIMER_CHOPolarity_NonInverted << 4) // прямой выход не инвертируется (default)
                         | (TIMER_CH_OutMode_Input        << 8);// инв.выход канала 1 на выход не работает (default)
  MDR_TIMER3->CH1_CNTRL2 = TIMER_CH_CCR_Update_Immediately      // немедленное обновление CCR (default)
                         | TIMER_CH_CNTRL2_CCR1_EN;             // разрешение работы CCR1
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  MDR_TIMER3->CH4_CNTRL  = TIMER_CH_MODE_CAPTURE                // работа канала 4 в режиме Захват
                         | TIMER_CH_EvSrc_PE;                   // ждать полож.фронт на входе канала (default)
  MDR_TIMER3->CH4_CNTRL1 = 0;                                   // канал 4 на выход не работает (default)
  MDR_TIMER3->CH4_CNTRL2 = TIMER_CH_CCR_Update_Immediately      // немедленное обновление CCR (default)
                         | TIMER_CH_CNTRL2_CCR1_EN              // разрешение работы CCR1
                         | TIMER_CH_CCR1EvSrc_NE;               // захват отр.фронта в CCR1
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  MDR_TIMER3->CCR1       = 1;                                   // порог включения REF в канале 1
  MDR_TIMER3->CCR2       = MaxTime;                             // запрет сравнения в канале 2
  MDR_TIMER3->CCR3       = MaxTime;                             // запрет сравнения в канале 3
  MDR_TIMER3->CCR4       = MaxTime;                             // запрет сравнения в канале 4
  MDR_TIMER3->CCR11      = MaxTime;                             // запрет сравнения 1 в канале 1
  MDR_TIMER3->CCR21      = MaxTime;                             // запрет сравнения 1 в канале 2
  MDR_TIMER3->CCR31      = MaxTime;                             // запрет сравнения 1 в канале 3
  MDR_TIMER3->CCR41      = MaxTime;                             // запрет сравнения 1 в канале 4

Процедура перенастройки таймера:

Код:
  // Выключение таймера:
  MDR_TIMER3->STATUS    = 0;                                // сброс событий таймера
  MDR_TIMER3->CNT       = 0;                           //  считать вверх с "0"
  MDR_TIMER3->CH4_CNTRL = TIMER_CH_MODE_CAPTURE        //  работа канала 4 в режиме Захват
                        | TIMER_CH_EvSrc_PE;           //  ждать полож.фронт на входе канала (default)
  MDR_TIMER3->CNTRL     = 0;                               // - сброс управления TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                 // сброс флага ожидания прерываний
  MDR_TIMER3->IE        = 0;                                  //  запрет прерываний
// ...........................................................................
  // Ожидание переднего фронта:
  MDR_TIMER3->STATUS    = 0;                                 // сброс событий таймера
  MDR_TIMER3->CNT       = 0;                                 // считать вверх с "0"
  MDR_TIMER3->CH4_CNTRL = TIMER_CH_MODE_CAPTURE              // работа канала 4 в режиме Захват
                        | TIMER_CH_EvSrc_PE;                 // ждать полож.фронт на входе канала (default)
  MDR_TIMER3->CNTRL     = TIMER_CntMode_EvtFixedDir          // счет внеш.событий вверх/вниз
                        | TIMER_CntDir_Up                    // сначала вверх (default)
                        | TIMER_EvSrc_CH4                    // считать события на канале 4
                        | TIMER_ARR_Update_Immediately       // обновлять ARR немедленно (default)
                        | TIMER_CNTRL_CNT_EN;                // включить TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                         // сброс флага ожидания прерываний
  MDR_TIMER3->IE        = 8 << TIMER_IE_CCR_CAP_EVENT_IE_Pos;// прерывание по переднему фронту
// ...........................................................................
  // Ожидание заднего фронта:
  MDR_TIMER3->STATUS    = 0;                                  // сброс событий таймера
  MDR_TIMER3->CNT       = 1;                                  // считать вверх с "1"
  MDR_TIMER3->CH4_CNTRL = TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                        | TIMER_CH_EvSrc_NE;                  // ждать отриц.фронт на входе канала
  MDR_TIMER3->CNTRL     = TIMER_CntMode_EvtFixedDir           // счет внеш.событий вверх/вниз
                        | TIMER_CntDir_Up                     // сначала вверх (default)
                        | TIMER_EvSrc_CH4                     // считать события на канале 4
                        | TIMER_ARR_Update_Immediately        // обновлять ARR немедленно (default)
                        | TIMER_CNTRL_CNT_EN;                 // включить TMRr
  NVIC_ClearPendingIRQ(TIMER3_IRQn);                          // сброс флага ожидания прерываний
  MDR_TIMER3->IE        = 8 << TIMER_IE_CCR1_CAP_EVENT_IE_Pos;// прерывание по заднему фронту

Обработчик прерывания TIMER3:

Код:
  s                   = MDR_TIMER3->STATUS; // запомнить события в регистре состояния таймера
  MDR_TIMER3->STATUS  = 0;                  // сброс событий таймера
  if (s & TIMER_STATUS_CCR_CAP1_CH4)
  {                                         // задний фронт:
    MDR_TIMER3->CNT   = 0;                  // сбросить счетчик
    MDR_TIMER3->CNTRL = 0;                  // выключить таймер
    NVIC_ClearPendingIRQ(TIMER3_IRQn);      // сбросить флаг ожидания прерываний
    MDR_TIMER3->IE    = 0;                  // запретить прерывания
    ...
  } else
  if (s & TIMER_STATUS_CCR_CAP_CH4)
  {                                                             // передний фронт:
    MDR_TIMER3->CH4_CNTRL = TIMER_CH_ETR_RESET_Disable          // запрет сброса по ETR (default)
                          | TIMER_CH_BRK_RESET_Disable          // запрет сброса по BRK (default)
                          | TIMER_CH_MODE_CAPTURE               // работа канала 4 в режиме Захват
                          | TIMER_CH_REF_Format3                // переключение REF при CNT == CCR
                          | TIMER_CH_EvSrc_NE;                  // ждать отриц.фронт на входе канала
    NVIC_ClearPendingIRQ(TIMER3_IRQn);                          // сбросить флаг ожидания прерываний
    MDR_TIMER3->IE        = 8 << TIMER_IE_CCR1_CAP_EVENT_IE_Pos;// прерывание по заднему фронту
    ...
  }

И тут обнаружилась ещё одна засада: обработчик прерываний действительно срабатывает и на положительный, и на отрицательный фронт входного импульса, а вот счётчик (CNT) на переднем фронте, как и ожидалось, переходит из "0" в "1" (при этом на выходе импульс появляется с задержкой 0.1 мкс), а на заднем фронте остаётся в состоянии "1", не переходит ни в "0" (если ARR == 1), ни в "2" (если ARR == 2), поэтому выходной импульс снимается с задержкой 0.98 мкс, когда в обработчике выполняется команда
Код:
MDR_TIMER3->CNT = 0;


Я ещё что-то упустил в особенностях этого хитрого устройства?

_________________
Странник


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB