STM32 Режим захвата.
Режим захвата — это особый режим работы таймера, суть которого в следующем, при изменении логического уровня на определённом выводе микроконтроллера, значение счётного регистра записывается в другой регистр, который именуют регистром захвата.
Для чего это надо?
С помощью этого режима можно измерить длительность импульса или период сигнала.
Режим захвата у STM32 обладает некоторыми особенностями:
Для настройки режима захвата предназначены регистры CCMR1(для 1 и 2 канала) и CCMR2(для 3 и 4), а также регистры CCER, DIER.
Давайте рассмотрим подробнее битовые поля регистра CCMR2, отвечающие за настройку 4 канала таймера, именно его мы будем настраивать в примере. Ещё хотелось бы отметить, что в этом же регистре находятся битовые поля, которые используются при настройке таймера в режиме сравнения.
CC4S — определяет направление работы четвёртого канала(вход или выход). При настройке канала как вход сопоставляет ему сигнал захвата
IC4PSC – определяют коэффициент деления, для сигнала захвата
IC4F — предназначен для настройки входного фильтра, кроме количества выборок, в течение которых микроконтроллер не будет реагировать на входные сигналы, также можно настроить частоту выборок. По сути мы настраиваем время задержки с момента прихода фронта до "подтверждающей" выборки.
Теперь давайте рассмотрим регистр CCER.
CC4E — включает/выключает режим захвата.
CC4P — определяет фронт по которому будет производиться захват, 0 — передний, 1 — задний.
И регистр DIER.
CC4DE — разрешает формировать запрос к DMA.
CC4IE — разрешает прерывание по захвату.
После того как произошёл захват формируется событие захвата, которое устанавливает соответствующий флаг. Это может привести к генерации прерывания и запросу DMA, если они разрешены в регистре DIER. Кроме того, событие захвата может быть сформировано программно, установкой битового поля в регистре генерации событий EGR:
Битовые поля CC1G, CC2G, CC3G и CC4G позволяют генерировать событие в соответствующем канале захвата/сравнения.
Кстати, CCR1, CCR2, CCR3 и CCR4 — регистры захвата, в которых сохраняется значение таймера по сигналу захвата.
Для того чтобы контролировать формирование сигнала захвата, в регистре SR для каждого канала выделено по два флага.
CC4IF — устанавливается когда формируется сигнал захвата, сбрасываются эти флаги программно или чтением соответствующего регистра захвата/сравнения.
CC4OF — устанавливается если флаг CC4IF не был очищен, а пришёл очередной сигнал захвата. Этот флаг очищается программно записью нуля.
Теперь давайте применим полученные знания на практике, с генератора сигналов на вход TIM5_CH4 подадим синусоиду с частотой 50Гц и попробуем измерить её период. Для того чтобы ускорить процесс предлагаю использовать DMA. Какой вывод МК соответствует 4 каналу TIM5 можно найти в даташите на МК в разделе Pinouts and pin description.
Для DMA необходим адрес регистра CCR4, вот как его найти. Открываем RM0008 и в таблице Register boundary addresses находим начальный адрес TIM5.
смещение для регистра CCR4 можно найти в том же документе в разделе register map.
На скриншоте видно, что период сигнала равен 20мс, что соответствует действительности. В следующей статье опишу, как измерить частоту сигнала.
Для чего это надо?
С помощью этого режима можно измерить длительность импульса или период сигнала.
Режим захвата у STM32 обладает некоторыми особенностями:
- возможность выбрать какой фронт будет активным
- возможность изменить частоту входного сигнала с помощью предделителя (1,2,4,8)
- каждый канал захвата оснащён встроенным входным фильтром
- источником сигнала захвата может служить другой таймер
- для каждого канала предусмотрено по два флага, первый выставляется если произошёл захват, второй если произошёл захват при установленном первом флаге
Для настройки режима захвата предназначены регистры CCMR1(для 1 и 2 канала) и CCMR2(для 3 и 4), а также регистры CCER, DIER.
Давайте рассмотрим подробнее битовые поля регистра CCMR2, отвечающие за настройку 4 канала таймера, именно его мы будем настраивать в примере. Ещё хотелось бы отметить, что в этом же регистре находятся битовые поля, которые используются при настройке таймера в режиме сравнения.
CC4S — определяет направление работы четвёртого канала(вход или выход). При настройке канала как вход сопоставляет ему сигнал захвата
- 00 — канал работает как выход
- 01 — канал работает как вход, сигнал захвата — TI4
- 10 — канал работает как вход, сигнал захвата — TI3
- 11 — канал работает как вход, сигнал захвата — TRC
IC4PSC – определяют коэффициент деления, для сигнала захвата
- 00 — делитель не используется, сигнал захвата IC1PS формируется по каждому событию
- 01 — сигнал захвата формируется по каждому второму событию
- 10 — сигнал захвата формируется по каждому четвёртому событию
- 11 — сигнал захвата формируется по каждому восьмому событию
IC4F — предназначен для настройки входного фильтра, кроме количества выборок, в течение которых микроконтроллер не будет реагировать на входные сигналы, также можно настроить частоту выборок. По сути мы настраиваем время задержки с момента прихода фронта до "подтверждающей" выборки.
Теперь давайте рассмотрим регистр CCER.
CC4E — включает/выключает режим захвата.
CC4P — определяет фронт по которому будет производиться захват, 0 — передний, 1 — задний.
И регистр DIER.
CC4DE — разрешает формировать запрос к DMA.
CC4IE — разрешает прерывание по захвату.
После того как произошёл захват формируется событие захвата, которое устанавливает соответствующий флаг. Это может привести к генерации прерывания и запросу DMA, если они разрешены в регистре DIER. Кроме того, событие захвата может быть сформировано программно, установкой битового поля в регистре генерации событий EGR:
Битовые поля CC1G, CC2G, CC3G и CC4G позволяют генерировать событие в соответствующем канале захвата/сравнения.
Кстати, CCR1, CCR2, CCR3 и CCR4 — регистры захвата, в которых сохраняется значение таймера по сигналу захвата.
Для того чтобы контролировать формирование сигнала захвата, в регистре SR для каждого канала выделено по два флага.
CC4IF — устанавливается когда формируется сигнал захвата, сбрасываются эти флаги программно или чтением соответствующего регистра захвата/сравнения.
CC4OF — устанавливается если флаг CC4IF не был очищен, а пришёл очередной сигнал захвата. Этот флаг очищается программно записью нуля.
Теперь давайте применим полученные знания на практике, с генератора сигналов на вход TIM5_CH4 подадим синусоиду с частотой 50Гц и попробуем измерить её период. Для того чтобы ускорить процесс предлагаю использовать DMA. Какой вывод МК соответствует 4 каналу TIM5 можно найти в даташите на МК в разделе Pinouts and pin description.
Для DMA необходим адрес регистра CCR4, вот как его найти. Открываем RM0008 и в таблице Register boundary addresses находим начальный адрес TIM5.
смещение для регистра CCR4 можно найти в том же документе в разделе register map.
#include "stm32f10x.h"
#define TIM5_CCR4_Address ((u32)0x40000C00+0x40)
#define DMA_BUFF_SIZE 2
uint16_t buff[DMA_BUFF_SIZE];//Буфер
uint16_t volatile T;
void DMA2_Channel1_IRQHandler (void)
{
T = (buff[1] > buff[0]) ? (buff[1] - buff[0]) : (65535+ buff[1] - buff[0]);
DMA2->IFCR |= DMA_IFCR_CGIF1;
}
void Init_DMA(void)
{
RCC->AHBENR |= RCC_AHBENR_DMA2EN; //Разрешаем тактирование первого DMA модуля
DMA2_Channel1->CPAR = TIM5_CCR4_Address; //Указываем адрес периферии - регистр результата преобразования АЦП для регулярных каналов
DMA2_Channel1->CMAR = (uint32_t)buff; //Задаем адрес памяти - базовый адрес массива в RAM
DMA2_Channel1->CCR &= ~DMA_CCR1_DIR; //Указываем направление передачи данных, из периферии в память
DMA2_Channel1->CNDTR = DMA_BUFF_SIZE; //Количество пересылаемых значений
DMA2_Channel1->CCR &= ~DMA_CCR1_PINC; //Адрес периферии не инкрементируем после каждой пересылки
DMA2_Channel1->CCR |= DMA_CCR1_MINC; //Адрес памяти инкрементируем после каждой пересылки.
DMA2_Channel1->CCR |= DMA_CCR1_PSIZE_0; //Размерность данных периферии - 16 бит
DMA2_Channel1->CCR |= DMA_CCR1_MSIZE_0; //Размерность данных памяти - 16 бит
DMA2_Channel1->CCR |= DMA_CCR1_PL; //Приоритет - очень высокий
DMA2_Channel1->CCR |= DMA_CCR1_CIRC; //Разрешаем работу DMA в циклическом режиме
DMA2_Channel1->CCR |= DMA_CCR1_TCIE;//Разрешаем прерывание по окончанию передачи
DMA2_Channel1->CCR |= DMA_CCR1_EN; //Разрешаем работу 1-го канала DMA
}
int main(void)
{
Init_DMA();
//включаем тактирование порта А, альтернативных функций и таймера
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
TIM5->PSC = 56000-1;//новая частота 1Khz
TIM5->CCMR2 |= TIM_CCMR2_CC4S_0;//выбираем TI4 для TIM5_CH4
TIM5->CCMR2 &= ~(TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC);//не фильтруем и делитель не используем
TIM5->CCER &= ~TIM_CCER_CC4P;//выбираем захват по переднему фронту
TIM5->CCER |= TIM_CCER_CC4E;//включаем режим захвата для 4-го канала
TIM5->DIER |= TIM_DIER_CC4DE;//разрешаем формировать запрос к DMA
//TIM5->DIER |= TIM_DIER_CC4IE; //разрешаем прерывание по захвату
TIM5->CR1 |= TIM_CR1_CEN; //включаем счётчик
//NVIC->ISER[1] |= NVIC_ISER_SETENA_18; //TIM5 Interrupt
NVIC->ISER[1] |= NVIC_ISER_SETENA_24; //DMA Interrupt
while(1)
{
}
}
На скриншоте видно, что период сигнала равен 20мс, что соответствует действительности. В следующей статье опишу, как измерить частоту сигнала.
Похожие статьи