понедельник, 01 октября 2012
Ознакомимся с такой очень полезной и простой периферией, как простой таймер (Basic timer), в микроконтроллерах STM32F4 простыми являются таймеры TIM6 и TIM7. Вообще, редкий микроконтроллер не имеет хоть какого-нибудь таймера для точного отсчёта времени. В STM32 все таймеры похожи по основным регистрам, просто в более сложных таймерах появляются новые флаги для настройки и новые регистры для контроля их работы в разных режимах.
Так вот, что же умеет и чем является даже самый простой и примитивный таймер?
читать дальшеВо-первых, он 16-разрядный, т.е. может считать до 65535.
Во-вторых, настраиваемый предделитель входной частоты. Тоже 16 бит.
В-третьих, у него есть регистр перезагрузки - при достижении какого числа он сбрасывается в ноль и начинает считать заново.
В-четвёртых, он может выдавать сигналы для DMA и для контроллера прерываний (NVIC). Сигнал у него только один — перезагрузка таймера (update в иностранной терминологии).
В-пятых, он может быть мастером для синхронизации других таймеров. Но это уже сложности, и фиг с ними.
Ну и как бонус: режим одного импульса. То есть таймер посчитает до максимума, перезагрузится и остановится, сняв флаг разрешения работы.
Вот такое вот счастье.
Ввиду малого количества возможностей и режимов работы, регистров настройки тоже немного. Вот они:
TIMx_CR1 — регистр управления (включение, выбор режима работы: непрерывный, один импульс);
TIMx_CR2 — регистр управления;
TIMx_DIER — регистры разрешения передачи сигналов в DMA и в NVIC. Флаг разрешения прерываний;
TIMx_SR — статусный регистр (было ли переполнение);
TIMx_EGR — генерация событий, в частности для синхронизации других таймеров;
TIMx_CNT — текущее значение счётчика;
TIMx_PSC — предделитель;
TIMx_ARR — до скольки таймер считает. Это число в счётчике ещё будет встречаться, а вот больше него уже нет.
Описание их всех побитово есть в Reference Manual.
Я расскажу лишь о двух самых нужных флагах.
CEN (бит 0) из регистра TIMx_CR1. Включение счёта. Если регистр TIMx_ARR не равен нулю, то таймер при установке данного флага начинает считать.
UIE (бит 0) из регистра TIMx_DIER. Разрешение прерывания по перезагрузке (переполнению).
Порядок запуска таймера таков:
1. Подать тактирование на выбранный таймер. Через RCC. Все таймеры сидят на шине APB1, и, соответственно, включаются с помощью регистра RCC_APB1EN. Расположение битов в RM.
2. Назначить предделитель, записав необходимое число в регистр TIMx_PSC. Частота счёта будет определяться как Ftclk / (TIMx_PSC + 1). Например, если мы тактируем таймер с частотой 8 МГц, а TIMx_PSC равен 7, то частота счёта (с какой скоростью будет увеличиваться значение счётчика) будет равна 8 / (7 + 1) = 1 МГц.
3. Назначить максимальное значение счётчика, при коем он будет перезагружаться, записав его в TIMx_ARR. При наличии там нуля, таймер работать не будет.
4. Установить флаг разрешения счёта (CEN в TIMx_CR1).
После этого таймер будет прекрасно работать и считать. При этом в любой момент времени можно посмотреть текущее состояние счётчика в регистре TIMx_CNT и узнать, была ли перезагрузка, проверяя флаг UIF (из регистра TIMx_SR) и сбрасывая его.
На асме:
На си аналогично.
Пример настройки ШИМ (уже для обычного таймера TIM2) показан далее.
Интересное:
main.s
stm32f4xx.inc
Проект. << Предыдущее Следующее >>
@темы:
arm,
программизмы,
электроника,
ассемблер,
stm32f4discovery,
stm32
If you need, I can send it to e-mail.
АЦП... Хорошо, посмотрим на АЦП =)
Спасибо за отзыв ^^
Настройка, очистка, работа с прерыванием желательна.
Как написано на we.easyelectronics.ru, людей знающих asm на stm(arm) мало, используйте Си.
Поэтому возможно, ваш дневник и блог(+плюс пару статей на we.easyelectronics.ru) помогут увеличить количество людей пишущих именно на asm.
Надеюсь на это =)
teplofizik, 2. Назначить предделитель, записав необходимое число в регистр TIMx_PSC. Частота счёта будет определяться как Ftclk / (TIMx_PSC + 1). Например, если мы тактируем таймер с частотой 8 МГц, а TIMx_PSC равен 7, то частота счёта (с какой скоростью будет увеличиваться значение счётчика) будет равна 8 / (7 + 1) = 1 МГц.
эта самая Ftclk чему равна если настройки предделителей шин не трогал? Где ее посмотреть? Как я понял надо смотреть частоту APB1 и в РМ указано, что максимальная частота этой шины 42МГц, однако реализовав простейшую моргалку на таймере получил результат отличный от ожидаемого(что конечно не удивительно при моем то опыте=D). Вот использованные константы:
длительность импульса вместо ожидаемой 1 секунда получилась 2+ секунды.
заметил еще одну особенность:
в этом варианте обработчика я поместил сброс бита TIM6_SR_UIF в самое начало.
В первом варианте сброс TIM6_SR_UIF был в конце обработчика и я наблюдал такую ситуацию, когда отлаживаю код через дебагер и ставлю брейкпоинт в нутри прерывания все работает гуд(светодиод инвенртируется по переполнению), а когда просто запускаю выполнение программы ничего не происходит(тоесть переполнение происходит, но светодиод не инертируется), как я понял выполнение подпрограммы заканчивалось раньше чем бит TIM6_SR_UIF оказывался сброшен, в результате чего инвертирование происходило повторно и визуально светодиод не успевал даже моргнуть. С чем может быть связанна такая особенность работы контроллера?
HSI (внутренний RC) частота 16 МГц, предделителей на APB/AHB нет (RCC_CFGR==0). Частота периферийной шины такая же. Предделитель на таймер 42000. Частота счёта: 16 МГц / 42000 = 380 Гц. За 1000 циклов пройдёт порядка 1000/380 = 2,6 сек.
Чтоб 1 секунда была, надо и записать 380 =)
Ессно, это для случая, когда PLL не включён и выбран внутренний RC-генератор.
Суть вопроса здесь:
Тут я походу немного не понимаю, как контроллер узнает, что из прерывания вышел? По идее для выхода из прерывания используется просто комманда перехода, так какая процессору нахрен разница? Может после использования регисра ссылки LR коммандой BX у него внутри как-то сбрасывается признак нахождения в прерывании? Можно этот момент пояснить?
Я не очень понял вопрос Оо
Вообще, что проц делает при каждой команде можно посмотреть в technical reference manual на ядро. Там в псевдоинструкциях всё показано.