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

CH32V

  • записей
    8
  • комментариев
    12
  • просмотра
    3 083

О блоге

CH32V003. Формирование временнЫх интервалов

Делать так, как описано в этой короткой статье, я бы не рекомендовал. Эта статья предназначена не ради готового примера для применения в каких-либо коммерческих программах, а ради "первой ступеньки" в освоении модуля таймера.

Таймеры в STM32 и в CH32V по сравнению с другими микроконтроллерами (например, MSP430, ATMEGA и другими) сильно навороченные, и разобраться сходу, как с ними работать, -- довольно-таки трудно. По себе сужу.

Документация в интернете в основном представлена на английском языке. На русском тоже есть, но есть один момент. Документации по таймерам конкретно для CH32V нет. Хотя таймеры в CH32V и STM32 очень похоже, но состав, названия регистров, названия битов по отношению к STM32 несколько различаются. Поэтому у разработчиков возникают определённые трудности, которые выливаются в затягивание сроков разработки программ.

Представленный в статье пример помогает быстрее начать с таймером работать.

В микроконтроллерах CH32V реализованы два таймера -- таймер общего назначения (General Purpose)  TIM2 и продвинутый таймер (Advanced) TIM1. В примере используется таймер общего назначения TIM2, но представленный код пригоден и для продвинутого таймера TIM1.

У таймера много функций, которые он может выполнять. Начать освоения таймера лучше с самой простой функции -- формирование временнЫх промежутков. Что это значит?

Допустим, мы пишем программу, которая выполняет какие-то действия (например, измеряет температуру). Поскольку программа измеряет температуру значительно быстрее, чем температура обычно меняется, то измерять температуру каждую миллисекунду нет смысла. Допустим, что нам нужно измерять температуру с периодом один раз в секунду. Само же время измерения и время передачи полученного значения температуры во внешний мир (на LCD или по последовательному каналу в компьютер) составляет 10 мс.

В этом случае главный цикл программы будет выглядеть как-то так:

int main(void)
{
  ...
  tim_init(); // Настраиваю таймер

  // Главный цикл программы
  while (1)
  {
    temperature = get_temperature(); // Измеряю температуру
    send_value(temperature); // Передаю показания
    wait(); // Жду секунду
  }
}

В функции tim_init() производится настройка таймера на формирование секундных промежутков времени, а функция wait() тупо останавливявает выполнение программы до начала следующего промежутка времени.

Вот, эти-то функции мы сейчас и рассмотрим более подробно. Начнём с функции tim_init().

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

RCC->APB1PCENR |= RCC_TIM2EN; // Включаю таймер

Следующим шагом нужно настроить работу таймера. Допустим, что тактовая частота SysClock, на которой работает ядро микроконтроллера, равно 24 МГц, а предделитель для шины мы не используем (то есть тактовая частота шины APB1 тоже 24 МГц). Тогда оставшийся код инициализации таймера будет выглядеть так:

TIM2->INTFR = 0; // Предочистка
TIM2->PSC = 24000; // Входная частота таймера = 1 кГц
TIM2->ATRLR = 1000; // Соответствует одной секунде
TIM2->CTLR1 = TIM_CEN; // Запускаю таймер в работу

У каждого таймера есть свой предделитель. Он делить входную частоту на заданное значение и потом подает её на счетчик таймера. В нашем случае мы записываем коэффициент деления 24000 в регистр предделителя (PSC). Это значит, что после предделителя частота, котораяубдет поступать на счётчик таймера, будет равна 1 кГц.

У каждого счётчика так же имеется регистр автозагрузки. Работа этого регистра зависит от направления счёта счетчика -- увеличивает ли счетчик свое значение или же уменьшает. Значение из этого регистра либо загружается в счётчик каждый раз при достижении счётчиком нулевого значения, либо наоборот -- при достижении счётчиком значения, равного записанному в регистре PSC, счётчик обнуляется. В обоих случая счётчик формирует событие UIF, которое мы и будем отслеживать в функции wait().

Код функции wait() ещё проще:

void wait(void)
{
  while (!(TIM2->INTFR & TIM_UIF))
    ; // Ожидаю поднятия флага UIF
  TIM2->INTFR = 0; // Сбрасываю флаг
}

Как можно понять из приведённого кода, функция тормозит выполнение программы до тех пор, пока не сработает таймер и не будет взведён флаг UIF. После этого происходит очистка этого флага и программа может продолжить своё выполнение.

Еще раз отмечу, что не смотря на то, что программа, построенная по предложенному способу, будет вполне рабочей, делать так не надо. Код программы был приведён только в учебных целях. С чего-то же нужно начинать?

Записи в этом блоге

Systick

Системный таймер SysTick состоит из четырёх регистров: Все регистры 32-разрядные. Однако в регистре управления используется всего пять бит, а в регистре состояния -- так вообще один бит. Базовый адрес регистров Системного таймера 0xE000F000. Регистры располагаются относительно базового адреса со смещением, которое приведено в таблице. Таким образом, узнать текущее состояние счетчика можно обратившись по адресу 0xE000F008. uint32_t value; ... value = *((uint32_t *)

zhevak

zhevak в CH32V

Среда разработки MounRiver Studio

Интегрированная среда разработки MountRiver Studio предназначена для работы с проектами на базе микроконтроллеров CH32V. Среда выпускается для трёх основных платформ — для Виндовс, для Линукса и для Макоси. Причём, версии для Линукса выходят с небольшой задержкой и, как мне видится, выходят за авторством не фирмы, а некоторого сообщества. Это я так думаю, так как в версии для Винды среда называется MountRiver Studio, а в версии для Линукса — MountRiver Studio Community. Я не особо копался,

zhevak

zhevak в CH32V

Распиновка

По началу, когда я только-только начал осваивать эти бестии, я ничего толком не понял — где какая нога у них. Таблица назначения выводов Table 2.1 на странице 11 , приведённая в описании по CH32V0003, не столько проясняет ситуацию, сколько ещё больше запутывает. По началу, когда не понимаешь, что они там вообще хотели сказать, это какой-то трэш! В самом конце этой статьи я раскрыл "секрет" производителя. К стати, для тех, кто , как и я , пользуется давно этим описанием, — второй половине ма

zhevak

zhevak в CH32V

Режим одиночного импульса

Продолжаю публикацию материалов на тему работы с таймером. У таймеров, которые встроены в CH32V003, имеется один полезный режим -- режим одиночного импульса (OPM, One Pulse Mode). Этот режим работы характеризуется тем, что таймер создаёт одиночный кусочек времени, а не генерирует периодический сигнал. Иначе говоря, мы стартуем таймер, он один раз отрабатывает заданное время  и на этом всё заканчивается. Чтобы повторить процедуру, нужно ещё раз стартануть таймер. В задаче, код кото

zhevak

zhevak в CH32V

Формирование интервалов времени

Это короткая заметка про то, как с помощью аппаратного таймера, который имеется в микроконтроллере CH32V003, сформировать пару сигналов. Поставленная задача чем-то напоминает задачу ШИМ (широтно-импульсной модуляции). Но в отличие от классической ШИМ-задачи, в описываемой здесь задаче не используется модуляция (то есть ширина импульса не меняется) и не предполагается использование (аппаратного) сигнала, который обычно выводится на ножки МК и который подаётся на управляющие выводы силовых тр

zhevak

zhevak в CH32V

Как затактировать систему

То решение, какое предлагает фирменный фреймфорк (или как это  китайцы называют у себя на фирме) мне, честно говоря, вообще не нравится. Я уже писал об этом. Там, в их коде полно ошибок, а, кроме того, компилятор генерирует много ненужного кода. Я вообще не понимаю, зачем нужно использовать структуру GPIO_InitStructure разработчику, который, знает состав портов ввода-вывода и как они работают. Вот, пример, кода который, я взял из фреймворка: void GPIO_Toggle_INIT(void) { GPIO_Init

zhevak

zhevak в CH32V

Минимальный проект

Здесь я описываю минимальный проект на базе микроконтроллера CH32V003, с которого можно легко стартовать и развивать свои проекты. Проект не идеальный, но вполне рабочий. Основная фишка проекта заключается в том, что он минимальный. То есть вполне осязаемый, в него не надо долго «залазить» и изучать. Дополнительным действием к проекту является установка самого тулчейна из файла MRS_Toolchain_Linux_X64_V170.tar.xz. Как это сделать, я уже описал где-то в предыдущих статьях. На своём компе я у

zhevak

zhevak в CH32V

CH32V003

Чем программировать CH32V Смешной вопрос! Чем вообще программируются STM32? У кого достаточно финансовых возможностей, тот покупает дорогие фирменные программаторы. Я, как и многие другие разработчики, использую китайские «свистки» по 150 рублей. (Это они раньше столько стоили. Сколько стоят сейчас — я не знаю. Уже давно не покупал. Для работы с STM32 я всё ещё пользуюсь свистком, купленным лет пять назад.) Беда, однако, в том, что ST-Link не подходит для работы с CH32V. Ну, хорош

zhevak

zhevak в CH32V


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