Пользователь
0,0
рейтинг
9 июля 2011 в 22:00

Разработка → STM32F1xx — лечимся от ардуинозависимости вместе

Добрый день, уважаемые хабровчане!
После длительного перерыва, связанного с защитой дипломного проекта в Бауманке, я снова вернулся к написанию статей. Так как с недавнего времени я занялся 32-битными микроконтроллерами серии STM32F на ядре ARM Cortex-M3, об этом и пойдет мой рассказ. Мне статья поможет систематизировать знания об этих замечательных микроконтроллерах, а вам, я надеюсь, послужит одной из ступеней на пути к их использованию и развеет страхи и сомнения, которые всегда возникают после уютных 8-битных AVRок при упоминании страшных 32-битных монстров.
Итак, почему Cortex, чем же плохи АVR?

Потолок


Вообще говоря, ничем. Микроконтроллеры из семейства AVR очень удобные, мало потребляющие и легкие в освоении. Но в этом и таится некоторая особенность – начав свой путь с AVR, человеку трудно заставить себя перейти на более сложную архитектуру. Казалось бы – все и так работает, а не работает – так возьму AVRку побольше. Еще больше. Все равно не лезет? Возьму две AVRки, буду строить этажерки из Arduino, пока все что я задумал не влезет в микросхемы. Это неправильный подход. Чаще всего это проявляется у тех, кто занимается электроникой «для себя». Не могу сказать что это прямо таки отвратительно и ардуины надо разбивать молотками, но если вы хотите выйти за рамки поделок на коленке или вывести ваше хобби на новый уровень, следует объективно оценивать области применения микроконтроллеров. Кстати, производители микроконтроллеров на ARM Cortex-M3 призывают именно к активным действиям, за видео уничтожения вами вашей старой отладочной платы на 8-битном контроллере они готовы выслать новенькую отладочную на ARM, однако, мы постараемся обойтись без вандализма.
Итак, переходя к конкретным примерам. Младшие модели семейства STM32F10x можно приобрести по цене от 30р за штуку. Как видите, цена сопоставима с AVRками. За эту цену вы получите 32-разрядный микроконтроллер, рассчитанный на частоту 24 МГц с объемом Flash и RAM примерно аналогичным ATMega88. Старшие же модели могут быть тактированы с частотой до 72 МГц, объемы флеша/RAM доходят до 1М/128К. Когда же следует использовать его, а не мегу? Тогда, когда упираетесь в «потолок» AVR. Таким «потолком» обычно являются вычислительные задачи (обработка сигнала, в частности). Да, я знаю, при желании можно попытаться и в мегу упихать DSP-алгоритмы, в целях обучения это даже полезно. Но в реальном устройстве куда целесообразнее применить подходящий процессор. Что мы получим, выбрав STM?
  1. Полноценные 32-битные вычисления. Не придется тратить драгоценные такты на работу данными, разрядностью больше 8 бит, АЛУ сделает это за вас.
  2. DMA. Контроллер DMA для пользователей AVR это роскошь, доступная только в старших, монструозных моделях. В STM32F1xx DMA есть даже в самых младших кристаллах. Используя его можно легко и непринужденно пересылать блоки данных между периферией и памятью без использования процессора. Очень полезно при работе с картами памяти, пересылке больших объемов данных по всяким UARTам и иже с ними, организации захвата звука с АЦП и вывода данных на ЦАП.
  3. Кстати о ЦАП – в большинстве моделей, в том числе и младших, в наличии 12-битный ЦАП. Для меломанов не подойдет, а всякую отладочную аналоговую инфу выводить удобно. Да и всякие игрушки со звуком делать удобнее, чем с ШИМ.
  4. NVIC, то бишь Nested Vector Interrupt Controller, программируемый контроллер прерываний, позволяющий назначить им приоритеты и гарантирующий постоянное время входа в прерывание – необходимая вещь для систем с ограничениями реального времени.
  5. Приятная мелочь типа контроллера SD-карточки – т.к. SPI-контроллер на STMках содержит аппаратный вычислитель CRC, его можно использовать для полноценного общения с SD-карточками.
  6. Наличие некоторых DSP команд. По правде говоря, Cortex-M3 не совсем DSP-ядро, но часто требуется именно такой процессор – не жрущие монстры типа DSP от TI, но и не слабые AVRки. В обработке сигнала на M3 поможет наличие аппаратного умножителя 32х32 и умножения с накоплением.
  7. У более продвинутых моделей есть USB-контроллер, а объемы флеша доходят до мегабайта, при том что корпуса вы по-прежнему можете выбирать сами – STM совместимы по пинам и даже старшие модели можно купить в 64-ногом корпусе. Плату переразводить не придется.

Теперь перейдем к недостаткам. Я могу отметить два:
  1. Корпуса у STM32F1xx намного менее паябельные в домашних условиях чем у тех же AVR. Плату изготовить удастся, но это потребует некоторой сноровки.
  2. Архитектура этих контроллеров весьма сложная, на один таймер приходится регистров 12 (они еще и 32-битные!), поэтому за вечерок осилить не удастся, придется целенаправленно ими заниматься.

Какой можно сделать вывод? Очень простой: старайтесь всегда думать головой, и объективно оценивать ситуацию, не давая затмить рассудок привычкам и привязанностям к конкретным архитектурам. Если вы видите, что неплохо бы использовать 16-битные (и выше) данные, считать фильтры, пересылать большие объемы информации – не хватайтесь за этажерки из ардуин. В то же время, если вам нужно просто раз в минуту проверять значение датчика освещенности и врубать настольную лампу – не стоит сразу бежать за кортексом.

Теперь перейдем к более насущным вопросам. Что же нам понадобится для того чтобы начать работать с STM32F?

Начинаем работать с STM32F1xx


Вопреки мнениям некоторых товарищей, вам будет достаточно 300р. На покупку вот такой вот отладочной платы: STM32VLDISCOVERY
image
Она сразу содержит и программатор, и программируемую часть в виде контроллера STM32F100RB на борту.
Также, очень не помешает вот такая вот макетка: WBU-206
image
Позволяет не отвлекаться на пайку, а сразу сосредоточиться на поставленных целях. Правда, сложные схемы на ней выглядят отвратительно – тугие переплетения проводов могут вселить ужас в неокрепшие умы)

Вот, в принципе и все из железа что понадобится для начала. Так как основы работы изложил в своих статьях уважаемый DiHalt, я не стану повторяться и буду считать что создать проект в Keil, скомпилять его и прошить сможет любой читатель статьи. Если нет – просвещаемся на easyelectronics.ru.
Для того чтобы было не так скучно работать, начнем не с надоевших всем светодиодов, а с сервоприводов. Сервопривод представляет собой электродвигатель, который включен в следящую систему. Обратная связь реализуется получением информации о фактическом положении вала – допустим, размещением потенциометра на одном из валов редуктора.
Управляющая система получает от нас информацию о том, на какой угол мы хотим повернуть вал сервы, от потенциометра – на какой он сейчас повернут, и формирует управляющее напряжение на обмотках двигателя. Все это китайские товарищи упихивают в очень малогабаритные корпуса, например, такие: Tower Pro MG90S
image
Стоят они меньше 200р, доставка бесплатная (правда, довольно долгая), редуктор – металлический, а не пластиковый. Традиционно, сервы управляются ШИМ-сигналом с частотой 20-60 Гц (обратите внимание, герц, а не килогерц), скважностью сигнала задается угол поворота. Конкретные значения зависят от самого серво-мотора, так что будем эксперементировать, благо можно отлаживать прошивку на ходу. К сожалению, инфы конкретно на эти моторы я не нашел, поэтому навскидку выбрал значения от японских сервоприводов Futaba — к счастью, китайские разработчики не сильно отошли от стандартов, и серва его вполне поняла. Целью статьи будет завести таймер на STM32F1xx, сформировать им ШИМ-сигнал и с помощью это ШИМа покрутить китайскую серву.
Обратимся к железу. В данном случае никаких особых схем от нас не потребуется – все уже есть на отладочной плате. Нам остается только подключить к ней серву. Стандартный сервомотор имеет 3 провода – земля, питание и управление (обычно раскрашенных в черный, красный и оранжевый цвета соответственно). Для упомянутых мною MG90S приводов питание может варьироваться от 4.8 до 6В, а потребление на холостом ходу, согласно моим измерениям, не превышает 40 мА, так что запитать их можно прямо от пина 5В отладочной платы. ШИМ будем подавать с одного из таймеров на борту контроллера. Каждый таймер имеет по 4 независимых ШИМ-канала, так что можно не напрягаясь крутить до 4х сервоприводов одним таймером. Таймеры с номерами 1 и 8 несколько более продвинутые, чем остальные – они предназначены для управления драйверами полевых транзисторов, включенных в полумостовую схему, поэтому пока их касаться не будем (несмотря на то, что они также могут выдавать простые шим-сигналы).
Вместо этого воспользуемся таймером под номером 2, который попадает в категорию General Purpose Timers. Для управления сервами мне было удобно воспользоваться его каналами 3 и 4. Согласно документации, 3 и 4 каналы выведены на пины PA2 и PA3.
Итак, в итоге наш плацдарм для экспериментов представляет собой отладочную плату STM32VLDISCOVERY, подключенную к USB компьютера и два сервопривода Tower Pro MG90S, земли которых (черный провод) соединены с пином GND отладочной платы, питание подключено к ее пину 5В а управляющие провода первого и второго сервы подключены к пинам PA2 и PA3 соответственно. Если у вас есть осциллограф, можно подключить его каналы к PA2, PA3 чтобы сразу наблюдать формируемый сигнал.
Теперь перейдем к коду.

Программная часть


В коде я буду делать упор на работу с регистрами вместо использования Standard Peripherals Library – т.к. ИМХО следует изучить, как это все работает изнутри, прежде чем пытаться абстрагироваться от железа. Будем считать, что создать проект для отладочной платы в кейле и подключить CMSIS для вас не составит труда, это подробно описано в статье на easyelectronics ARM. Учебный Курс. Keil + CMSIS. Создание проекта

Итак, стартовой позицией для нас будет проект в Keil uVision с подключенной CMSIS:

#include "stm32f10x.h"

int main()
{
		while(1);
}

Это все должно у вас компиляться, прошиваться в память контроллера и дебаггиться. Если этого не происходит – читаем упомянутую статью на easyelectronics.
Стартовый код из ассемблерного файла (у меня он зовется startup_stm32f10x_md_vl.s) содержит объявление хенделеров перываний и эксепшенов, которые могут быть безболезненно переопределены в нашей программе. Также он вызывает функцию SystemInit, определенную в файле core_cm3.h библиотеки CMSIS. В ней настраиваются некоторые регистры, в частности, отвечающие за тактирование – это все можно сделать и вручную, заменив вызов SystemInit в стартовом файле на вызов своей функции, но сейчас не будем останавливаться на этом вопросе. Отмечу только, что частота выставляется в соответствии с настройками в файле system_stm32f10x.c, где на строке 76 дефайнится SYSCLK_FREQ_24MHz, равное 24000000.

Управляющий код очень простой, однако, есть несколько моментов, на которые следует обратить внимание, чтобы не пришлось долго искать проблему в коде.
Первый момент упомянут DiHalt’ом – в STMках по умолчанию отключено тактирование практически всех периферийных модулей в целях сбережения энергии. Так что первым делом подаем такты на нашу периферию:

	RCC->APB1ENR|= RCC_APB1ENR_TIM2EN;	
	RCC->APB2ENR|= RCC_APB2ENR_IOPAEN;	
 

В этих двух строках мы устанавливаем биты TIM2EN (для подачи клока на таймер 2) и IOPAEN (для подачи клока на порт А) в регистрах APB1ENR и APB2ENR соответственно (APB1 и APB2 Peripheral Clock Enable Register).
А вот дальше идет еще одна важная вещь:

	GPIOA->CRL |=GPIO_CRL_MODE2;
	GPIOA->CRL &=~GPIO_CRL_CNF2_0;
	GPIOA->CRL |=GPIO_CRL_CNF2_1;

	GPIOA->CRL |=GPIO_CRL_MODE3;
	GPIOA->CRL &=~GPIO_CRL_CNF3_0;
	GPIOA->CRL |=GPIO_CRL_CNF3_1;
 

Мы настраиваем оба пина, PA2, PA3, на выход, но дело в том, что в STMках существует разделение в режимах работы GPIO. Если мы хотим программно устанавливать состояние пина в 1 или 0, то нам следует выбрать режим работы Output push-pull либо Output open drain. Если же предполагается, что его состоянием будет управлять аппаратно какая-то периферия типа таймера, которая прописана в даташите на конкретную модель контроллера в разделе распиновки в графе Alternate Functions, то режим работы следует выбирать Alternate function push-pull или Alternate function open drain. Если выставить режим неправильно, то таймер не сможет выдать ШИМ-сигнал.
Коротко о регистрах – каждый порт содержит два управляющих регистра CRL и CRH, по сути, абсолютно одинаковых. В CRL хранятся настройки пинов 0-7, в CRH – 8-15. На каждый пин приходится по 4 бита, два из которых, MODE, отвечают за направление ввода-вывода и ограничение на максимальную частоту переключения пина в режиме вывода, другие два, CNF, хранят тот самый режим работы.
Всего это дает нам восемь возможных состояний пина:
  1. Вход, не подтянутый (MODE[1:0]=00, CNF[1:0] = 01)
  2. Вход, подтянутый к питанию (MODE[1:0]=00, CNF[1:0] = 10, на выход порта подан 1 )
  3. Вход, потянутый к земле (MODE[1:0]=00, CNF[1:0] = 10, на выход порта подан 0)
  4. Аналоговый вход (MODE[1:0]=00, CNF[1:0] = 00) – при этом отключается входной триггер Шмита и резисторы подтяжки, пин переходит в Z-состояние.
  5. Выход, открытый сток GPIO (MODE[1:0]!=00, CNF[1:0] = 01)
  6. Выход, push-pull GPIO (MODE[1:0]!=00, CNF[1:0] = 00)
  7. Выход, открытый сток под управлением периферии (MODE[1:0]!=00, CNF[1:0] = 11)
  8. Выход, push-pull под управлением периферии (MODE[1:0]!=00, CNF[1:0] = 10)

Для наших целей нам нужны пины, сконфигурированные на выход, управляемый периферией в режиме push-pull. Таким образом, необходимо в регистре CRL установить значения битов MODE2[1:0] и MODE3[1:0] в какое-нибудь отличное от 00 значение, допустим, в 11, а битов CNF2[1:0] и CNF3[1:0] – в значение 10
Остальные регистры, относящиеся к периферии, подробно описаны в документе RM0008, STM32F1xx Reference Manual. Если коротко – регистры IDR и ODR содержат input и output значения на пинах порта, BSRR отвечает за установку/сброс, а BRR только за сброс битов в ODR, причем делает он это атомарно, то бишь эта операция происходит за один цикл шины и в нее не может вклиниться прерывание. Последний регистр порта, LCKR позволяет «запереть» значение пина, не давая изменить его до самого резета.

Далее настроим таймер. Согласно найденным на просторах интернета данным, период ШИМ следует выбирать от 20 до 60 Гц, при этом импульсы шириной около 1 мс означают 0 градусов, 1.5 мс – 90 градусов, а 2 мс – 180.
image
Что касается разрядности ШИМа – в принципе, можно выбрать любую, но точность позиционирования сервы все равно конечна, поэтому я выбрал 12 разрядов. Также следует помнить, что 12 разрядов описывают изменение ширины импульса от 0 мс до величины, равной его периоду, в то время как серва работает на диапазоне от 1 до 2 мс, поэтому в нашем распоряжении будут далеко не все 12 разрядов. Забегая вперед, скажу что в результате экспериментов я пришел к следующим параметрам:
  • Частота ШИМ-сигнала: 35 Гц. Выбрал просто как среднее значение, серва стабильно работает и при 30 и при 50 Гц.
  • Ширина импульса, соответствующя 0 градусам: около 0.5 мс, однако, если выбрать ее 0.5 или меньше, серва начинает трещать, т.к. находится на границе своих физических возможностей по повороту. Поэтому для более стабильной работы я использую импульсы шириной около 0.56 мс
  • Ширина импульса, соответсвующая 180 градусам: около 2.3 мс, та же ситуация что и с нулевым поворотом – если задать чуть больше граничной, начнет трещать.

Выбрав частоту ШИМ 35 Гц, а разрядность – 12 бит, получаем 4096 значений на весь период, 0х50 будет соответствовать ширине в 0.56 мс, а 0х150 – ширине в 2.34 мс.
Таким образом, получаем 256 значений на примерно 180 градусов, что означает дискретность примерно в 40 угловых минут на один отсчет. При желании, можно продолжить эксперименты и определить точные граничные значения и точность, с которой привод может осуществлять позиционирование.
Итак, следующим фрагментом кода настраиваем таймер 2:

	TIM2->PSC = 0x00A7;
	TIM2->ARR = 0x0FFF;
	TIM2->CCR3 = 0x050;
	TIM2->CCR4 = 0x0150;

Тут все весьма тривиально: регистр PSC (Prescaler) отвечает за предделитель, регистр ARR (Auto-reload register) – за максимальное значение, до которого будет тикать таймер. Выставив в ARR число 0хFFF получаем 12-разрядный таймер, период его счета будет равен тактовой частоте, деленной на 0xFFF, то есть 24000000/4096 = 5859. Разделив это значение еще на 0xA7, получим 5859/167 = 35 Гц.
Значение регистров CCR3 и CCR4 (Capture Compare register) сравнивается со значением счетчика и задает собственно скважность ШИМа. Дальше настраиваем режим работы таймера:

 	
TIM2->CCMR2 |= TIM_CCMR2_OC3M_1|TIM_CCMR2_OC3M_2;
TIM2->CCER    |= TIM_CCER_CC3E;

TIM2->CCMR2 |= TIM_CCMR2_OC4M_1|TIM_CCMR2_OC4M_2;
TIM2->CCER    |= TIM_CCER_CC4E;

TIM2->CR1 |= TIM_CR1_CEN;
 

Ситуация та же, что и с регистрами настройки порта – два регистра настройки Capture and Compare Mode register, CCMR1, CCMR2 отвечают за режимы работы каналов 1,2 и 3,4 соответственно. Настроек там много, и лучше на этот счет читать Reference Manual. Если обзорно – регистры отвечают за режимы связанные с захватом шим-сигнала по таймеру и с его выводом. Биты CCxS, где x – номер канала, настраивают данный канал на ввод или на вывод. По умолчанию включен режим вывода, поэтому их трогать не будем. Устанавливаемые биты OCxM[2:0] отвечают за то, как канал будет реагировать на сравнение значения счетчика (которое хранится, кстати, в регистре
TIM2->CNT) и регистров CCRx. Всего возможны 8 вариантов:
  1. 000 – сравнение никак не влияет на выход
  2. 001 – при совпадении значений на выходе канала устанавливается 1
  3. 010 – при совпадении значений на выходе канала устанавливается 0
  4. 011 – при совпадении значений выходной сигнал переключается в противоположное состояние
  5. 100 – выход всегда установлен в 0
  6. 101 – выход всегда установлен в 1
  7. 110 – ШИМ, режим 1, обычный (пока значение в CCRx<CNT, на выходе 1, иначе 0)
  8. 111 – ШИМ, режим 2, инверсный (пока значение в CCRx<CNT, на выходе 0, иначе 1)

Устанавливаем режим 110, обычный ШИМ. Не забываем в регистре CCER (Capture/compare enable register) установить бит CCxE – включить выход соответствующего канала.
После этого включаем весь таймер установкой бита CEN в регистре CR1 (Control Register 1).
Все, ШИМ пошел, на экране осциллографа должна появиться красивая картинка, а сервы занять противоположные положения. При желании можно поставить бряк после всех инициализаций и менять значения при помощи встроенного в Кейл средства для просмотра и редактирования регистров процессора и периферии, сразу наблюдая изменение скважности сигнала на экране осциллографа и положения вала сервопривода.
Давайте теперь в целях самообразования сделаем программу чуть более интересной – будем изменять значения угла от максимума до минимума. Для этого вспомним, что в состав ядра ARM Cortex-M3 входит так называемый SysTick Timer – это 24-битный таймер, предназначенный для глобальной синхронизации и генерации прерываний, допустим, при реализации операционной системы. Инициализируется таймер при помощи функции SysTick_Config (uint32_t Ticks). Эта функция является частью CMSIS, которая более «фундаментальна» чем Standard Peripherals Library, поэтому воспользуемся ею.
Если интересны внутренности этой функции, можно перейти к ее описанию в недрах CMSIS (файл core_cm3.h, строка 1137). В целом, функция не делает ничего особо сложного, только проверяет значение передаваемого в нее параметра Ticks на предмет превышения 24 бит, после чего устанавливает регистры:
SysTick->LOAD в значение Ticks – это вершина счетчика таймера, с такой периодичностью будут вызываться прерывания.
SysTick->VAL в 0 – это текущее значение счетчика
• Битов CLKSOURCE, TICKINT, ENABLE регистра SysTick->CTRL в 1.

Бит CLKSOURCE отвечает за источник тактового сигнала для таймера. Вообще говоря, спецификация на ядро не описывает каким должен быть второй сигнал (первый всегда подключен к системному клоку), поэтому от производителя к производителю эффект от этого бита может меняться. В STM32F второй клоковый сигнал подключен к SystemCoreClock/8. Установив бит в 1 выбираем источником системный клок.
Бит TICKINT включает генерацию прерывания (а точнее, эксепшена) по переполнению таймера. Устанавливаем в 1, ради него все и затевалось)
Бит ENABLE включает таймер.
Кроме описанных действий функция SysTick_Config еще и выставляет приоритет прерыванию в значение 240, весьма низкий, учитывая что приоритеты начинаюся с 0 (вообще-то с -3, но приоритеты меньше 0 неконфигурируемы).
Так как текущие настройки ШИМа означают 256 шагов от 0 до 180 градусов, настроим таймер на частоту
SystemCoreClock/256, чтобы этот путь серва проходила за 1 секунду:

 	
SysTick_Config(SystemCoreClock/256);

Константа SystemCoreClock определена в system_stm32f10x.c, строка 114, и равна числу тактовых сигналов ядра за 1 с, то есть 24000000.
Осталось описать обработчик прерывания по таймеру и работа будет завершена!

 	
int8_t	  ChannelDir[2]={1,-1};
volatile uint16_t  *DutyCycle[2]={TIM2->CCR3,&TIM2->CCR4};

void SysTick_Handler()
{
	uint8_t i;
	for(i=0;i<2;i++)
	{
		*DutyCycle[i]+=ChannelDir[i];
		if(*DutyCycle[i]<0x50)
			   ChannelDir[i]=1;
		if(*DutyCycle[i]>0x150)
				ChannelDir[i]=-1;
	}
}

Так как каналов у нас два, напишем обработчик с расчетом на оба канала сразу. Так как пространство памяти у нас едино, мы можем свободно обращаться к регистрам как к обычным ячейкам памяти, поэтому сразу объявляем указатель на два регистра:

 	
volatile uint16_t  *DutyCycle[2]={&TIM2->CCR3,&TIM2->CCR4};

Дальше все очень просто – организуем цикл по двум каналам, добавляем или вычитаем 1 из текущего значения скважности (в зависимости от направления) и по достижении сервой крайнего положения меняем направления.

Все, компиляем, и если все сделано правильно, то наслаждаемся зрелищем типа того, что представлено мной на видео ниже.



Полный код проекта выглядит так:
 	
#include "stm32f10x.h"
int8_t	  ChannelDir[2]={1,-1};
volatile uint16_t  *DutyCycle[2]={&TIM2->CCR3,&TIM2->CCR4};
void SysTick_Handler()
{
	uint8_t i;
	for(i=0;i<2;i++)
	{
		*DutyCycle[i]+=ChannelDir[i];
		if(*DutyCycle[i]<0x50)
			   ChannelDir[i]=1;
		if(*DutyCycle[i]>0x150)
				ChannelDir[i]=-1;
	}
}

int main()
{
	RCC->APB2ENR	|= RCC_APB2ENR_IOPAEN;	
	RCC->APB1ENR	|= RCC_APB1ENR_TIM2EN;	

	GPIOA->CRL  |=GPIO_CRL_MODE2;
	GPIOA->CRL	&=~GPIO_CRL_CNF2_0;
	GPIOA->CRL	|=GPIO_CRL_CNF2_1;

	GPIOA->CRL  |=GPIO_CRL_MODE3;
	GPIOA->CRL	&=~GPIO_CRL_CNF3_0;
	GPIOA->CRL	|=GPIO_CRL_CNF3_1;

	TIM2->PSC = 0x00A7;
	TIM2->ARR = 0x0FFF;
	TIM2->CCR3 = 0x050;
	TIM2->CCR4 = 0x0150;
	
	TIM2->CCMR2 |= TIM_CCMR2_OC3M_1|TIM_CCMR2_OC3M_2;
	TIM2->CCER  |= TIM_CCER_CC3E;

	TIM2->CCMR2 |= TIM_CCMR2_OC4M_1|TIM_CCMR2_OC4M_2;
	TIM2->CCER  |= TIM_CCER_CC4E;

	TIM2->CR1 |= TIM_CR1_CEN;
	SysTick_Config(SystemCoreClock/256);

  	while(1);
}


На этом у меня пока все. Если вас эта тема заинтересовала, то в следующих статьях постараюсь рассмотреть что-нибудь поинтереснее, допустим, работу с дисплеем от мобильного телефона.

UPD:
Чтобы далеко не ходить, полезные ссылки:
@Ariman
карма
352,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (65)

  • +43
    Здравствуйте. Меня зовут Вася и я… Мне сложно об этом говорить… Я делал девайсы на ардуине. Но после того, как я прочитал книгу доктора Аримана «STM32: жизнь без страха», моё представление о мире полностью перевернулось. Моя жизнь наполнилась красками, я сбросил оковы 8-битных вычислений и открыл для себя путь к просветлению. Я обрёл внутреннее равновесие и уверенность в своих девайсах, о котором я не мог и мечтать, используя ардуину. Спасибо!
  • +36
    Дочитал до середины и поставил плюс. Хабр должен быть таким, а не скопищем новостей про всякую ерунду.
    • +2
      После статьи даже захотелось глубже изучить программирование микроконтроллеров
      Полностью вас поддерживаю. Хабр таки должен быть сайтом с нормальными статьями, а не блогом ализара
      • +2
        Если вы пока недостаточно с ним знакомы, то все же стоит начать с AVR / PIC, как ни крути ARMы тяжеловаты для понимания без базы.
        • 0
          Я щас знакомлюсь с AVR с помощью стенда EV8031 (вот такой opensys.com.ua/ev8031/ev8031_sm.jpg)
          Правда последнее время что-то интерес начал угасать. Но статья подстегивает :)
          • 0
            С AVR ИМХО лучше железки делать самому все-таки.
            Во-первых, это полезный навык, практика в схемотехнике еще никому не мешала, особенно при работе с контроллерами.
            А во-вторых, когда придет время осваивать более мощные контроллеры, такие как те же STM32F, или ПЛИС, возможностей попрактиковаться резко станет меньше — корпуса не располагают.
            Поэтому пока есть возможность я бы посоветовал собирать кастомные девайсы.

            А что до интереса — лучший способ это как раз таки придумать девайс, которым будет интересно заниматься, и начать его реализовывать. Начиная от схемотехники и заканчивая кодом.
            • 0
              Знаю. Но вот со схемотехникой что-то не сложилось. Как с навыками так и с желанием, что печально :(
            • 0
              +1 к реальному проекту.
              Просто мигать светодиодами — не интересно.
              Какую-нибудь игрушку с дистанционным управлением и расширенными возможностями, элементы «умного дома» (для начала — датчики температуры и влажности + плюс управление освещением или питанием каких-нибудь девайсов).
              Во-первых реальные задачи интереснее реализовать.
              Во-вторых попутно изучаются другие аспекты, помимо собственно программирования МК: протоколы взаимодействия с внешними устройствами, нюансы использования тех или иных девайсов, разработка управляющих модулей…
              Интересно и полезно. :)
          • 0
            Ух ты. В олимпиаде учавствовали?

            Вообще, идеи этого стенда были заложены более 10 лет назад. На данный момент он конечно устарел.
            • 0
              Нет, они у нас в универе в качестве учебного пособия. Вот иногда и пользую для практики, когда есть время.
  • –6
    Двач ты уже ночной?
  • +1
    Черт. Я так с вашими статьями все деньги солью на непонятные шняги! (Ушел на алибабу исследовать цены на сервы. А то старые шаговики из 5" флоповодов заканчиваются)
    • +2
      Я брал на Dealextreme, алибабу пока не затрагивал, хотя примеривался к тамошним дисплейчикам)
      ДилЭкстрим штука опасная, заглянешь купить чего-нибудь на 2 бакса, опомнишься когда накупил на 100)
      Вроде все копеечное и все хочется купить)
      • 0
        Да ебей и алибаба не хуже. Я за этот месяц понабрал столько, что уже стыдно перед женой.
        При этом я с железом не вожусь, возится отец, я только ПО к результату пишу…
        • +1
          На ебей напрягает обилие лотов от левых товарищей, которые неизвестно в каком состоянии придут и придут ли вообще, плюс тот факт что можно не заметить, подобрать себе что-то, а потом наткнуться на надпись «доставка 50 баксов» или вовсе «в Россию не доставляем», бывало уже(
          Почему-то многие китайские товарищи в Россию не хотят везти…
          • 0
            Ни разу до сих пор с отказом доставки не встречался. По крайней мере, из Гонконга кто.
            Ну и качество — если 99.8 с возрастом в несколько лет — да нет никаких проблем :)

            Но вообще, алибаба рулит для восточного рынка, надёжней ебея.
            • 0
              Ну я не про отказ, скорее, а про приписку мелким шрифтом «Not available for Russia», в последнее время часто у китайцев встречал, не знаю с чем это связано.
              • 0
                > не знаю с чем это связано.

                С почтой, вестимо. :(
            • 0
              Вот только Алибаба !=Ebay если тебя там кинет продавец то фиг чо потом отсудишь. Особенно если сделка была не за PayPal
              • 0
                Escrow.
                Кстати, они хотят отказаться от пейпала вскоре полностью.
  • 0
    А что за осицлограф?
    • +1
      Siglent SDS1102CM, цифровой, два канала, до 100 МГЦ, память 2 метра.
      Заказывал на уже упомянутом Dealxtreme. Обошелся мне в 12к рублей примерно, не жалею что купил, с осцилом совсем другая жизнь)

      По началу примеривался там же к общеизвестному RIGOL DS1052E, но их, похоже, сняли с производства — месяц ждал поступления на склад, так и не дождался, заменил в заказе на Siglent.
      • 0
        А как с таможней? Он же по цене уже превышает предельные 10к для почты россии…
        • +1
          Хм… 10к? Я слышал о сумме в 1000 евро, ее нельзя превышать. Про 10к ничего не слышал, проблем не было.
        • +2
          Сейчас лимит 1кЕ так что проходит влет.
          • 0
            Ооо! Спасибо! Это упрощает жизнь.
      • 0
        Ого! На деалкстреме он $345.60 аж, меньше 10 — тогда проблем с таможней нет.
        Запросил еще цену на алибабе у Siglent'а напрямик. Может, в 300 уложится :)
        Будет отцу подарок на ДР.
        • 0
          Блин, это Ригол 350$. А сиглент 440…
        • +1
          Есть еще DealExcel.com они чисто по инструменту. Я там логик анализатор заказывал. Местами дешевле чем DX
          • 0
            Спасибо, добавил в закладки.
            Но тут Ригол те же 345, а Сигела просто нет.
          • 0
            Ну все, плакали мои денежки) Сейчас чего-нибудь закажу…
    • 0
      Siglent (та же опера что и Rigol или Atten) пока еще нонейм, но уверенно идет в массы.
  • 0
    Кста, можешь добавить еще ссылку сюды:
    we.easyelectronics.ru/blog/STM32/

    Тут народ ряд статей по стм32 задвинул. Правда я не знаю выдержит ли оно хабраэффект :)
    • 0
      Хабраэффект это фантастика :))
    • 0
      Сделано)
  • 0
    Уже давно хочу взять себе подобный контроллер, но отпугивает то, что придется изучать для себя новый язык программирования (а это время, которого не хватает). Подскажите, что то типа питона туда встает? Юзабельно?
    • 0
      питон встает, но в жутко урезанном виде и жрет дофига ресурсов. учите си, пригодится… или попробуйте Cython прикрутить, вдруг чо получится
    • +1
      Настоятельно рекомендую все же С освоить. Тем более что в чистом С, без плюсов, все довольно просто. Единственной более-менее сложной для понимания темой в нем считаются указатели.

      А вы с 8-битными уже разобрались? Ну там, AVR, PIC? Не стоит сразу с ARMа начинать, ИМХО.
      • +1
        Если честно, в руках даже не держал ) просто хочется чего нибудь взять попробовать, присматриваюсь к Arduino. Хочется просто взять и начать работать…
        • 0
          Ну ваше право. Но честно говоря, рекомендовал бы начать с нуля, больше пользы будет. Это потребует больше времени, но почему бы не посвятить этому долгие вечера, раз уж тема заинтересовала?)

          «Долгий» путь — это скачать/купить книжку по тем же AVRкам, нагуглить статьи, купить саму AVRку, кварц, макетку, периферию (ну что там для начала, светодиоды, сервы те же). Собрать программатор. Собрать девайс на AVR. Потом только начать кодить, изучая С параллельно. Это даст куда более фундаментальные знания, т.к. заниматься контроллерами без схемотехники это как-то… неправильно, по моему)
          • +4
            >>Хочется просто взять и начать работать…
            >… Это даст куда более фундаментальные знания, т.к. заниматься контроллерами без схемотехники это как-то… неправильно, по моему)
            Товарищи электронщики, вы это бросьте, а. «Фундаментальные знания» — это не то, с чего нужно начинать знакомство с МК программисту. Куда проще будет взять так нелюбимую вашей епархией Arduino, и сразу начать кодить, а схемотехнику и т.п. изучать позже — иначе человеку может просто надоесть безрезультатно ковыряться в железе, отлавливая хардварные баги. Приведу аналогию — изучать Linux нужно с Ubuntu, а не с LFS, равно как и литературу со сказок, а не с Достоевского.
            • 0
              Ну дык и схемотехнику можно начать с закона ома, светодиода, резистора и тиньки, а не с каких-нибудь страшных силовых или ВЧ установок)
              Я не говорю что ардуино это аццкое зло и т.п., но ведь можно провести аналогию с языками высокого уровня — сразу попав в нежные объятия фреймворка дотнета или явы очень многие так и не пытаются понять как это работает внутри, и потом искренне удивляются когда слышат про организацию памяти, регистры, или хотя бы про то, во что превращается их код после компилляции. Это тоже не дело.

              Как раз в том то и прелесть мелких 8-битных контроллеров, даже девятиклассники спокойно паяют дома схемки с нуля, так почему бы с этого не начать) Я же не призываю сразу проектировать устройства на АРМ11 с нуля. AVR/PIC дают отличную возможность попрактиковаться в схемотехнике как раз с быстрым результатом, без слишком долгой мороки, они отлично вписываются в макетные платы типа той, что я привел в статье, благодаря дип-корпусам. Зачем же себя этого лишать?)
              • 0
                Я говрорил не о том, чтобы себя этого лишать, а о принципе «от простого к сложному»: Arduino -> AVR -> ARM ->…
                Задроты дойдут и до последнего (?) шага, а любители просто поиграться могут остановиться и на первом.
                • 0
                  Ну-ну, так-таки и задроты)
                  Впрочем, это их право, кто как хочет тот так и учится. Я лишь рекомендую близкий мне путь. Призываю только не забывать что помимо ардуин есть много хороших железок и имеет смысл обдумать когда их целесообразно применять)

                  Кстати, до второго курса универа сам был чистым прикладником, писал под винду. Потом наткнулся на статейку про бегущие огоньки на AVR, очень порадовало что «целый компьютер в такой маленькой штучке», и железо меня захватило) Ардуины тогда еще не так были распространены, поэтому паял все с нуля, ничуть не жалею.

              • 0
                > Как раз в том то и прелесть мелких 8-битных контроллеров, даже девятиклассники спокойно паяют дома схемки с нуля

                Именно в 9м классе вся эта пайка и осталась ;-).

                По поводу статьи — спасибо! Но как разителен переход от AVR к ARM: если с первым можно вполне просто бодаться на асме с шестнадцатеричными константами, но для ARMа реально встает необходимость API и кросс-платформенных библиотек по управлению переферией, потому что дергать по 20 битов в 4 регистрах для управления одним пином весьма нудно не только на асме, но и на C.

                Кстати, в этом тоже часть шарма и популярности AVR — устав от тормозных джав и дотнетов, и от сложных драйверов ядра, народ хочет что-то, что можно попрограммить на голом асме. Arduino — это как современный Спектрум, простой и добрый ;-).
    • 0
      Я вот тоже боялся нового языка, но на практике чистый Си оказался не таким и сложным. Что может напугать питониста, так это указатели, но там все не так печально, так что проще учите нативный язык.
      Уже месяц как заболел программированием аврок, оч увлекательный процесс, особенно если поставить себе реально полезную задачу.
    • 0
      > а это время, которого не хватает

      Купите себе побольше времени ;)
  • 0
    А где за разбитую ардуину новый stm дают? У меня как раз одна лишняя есть.
    • 0
      Да вот то ли ST то ли NXP проводили подобную акцию, об этом еще статья тут, на хабре, проскакивала.
      Там много разных видео было, начиная от разбивания молотком и заканчивая прожариванием плат на катушке Тесла)
    • 0
      Со злости?
  • +1
    АРМ намного круче, спору нет. Но он расчитан на более профессиональную подготовку и подразумевает наличие некоторого опыта и понимания как АРМов, так и электроники в целом. Даже Си-шный код в глазах новичка кажется чем-то страшным. А вот Ардуино как раз для начинающих и расчитан. Я даже скажу, что очень мало людей доходят до того момента, когда им не хватает мощости АВРок и есть реальная необходимость пересесть на АРМ.
    А что касается статьи, тут вам огромное спасибо. Не часто встретишь на Хабре что-нибудь действительно близкое душе и сердцу :)
    • 0
      Это так, я бы не советовал пытаться начать сразу с АРМов, да. Но в то же время даже работая с АВРками я бы настоятельно рекомендовал людям самим проектировать схемы, пока есть возможность. Под АРМмы, ПЛИСы уже намного труднее изготовить плату, а под АВР можно как следует набить руку на схемах, разводке плат — в общем на всем цикле разработки.
      И отточить навыки в С, т.к. без него просто несерьезно этим заниматься. А Ардуина этого лишает.
      Не спорю, с ней удобнее, но по мне так намного полезнее вникнуть в схематику и собрать себе отладочную самому, пока такая возможность есть.
      Иначе потом будет очень сложно отказаться от Ардуин и начать проектировать девайсы самому.
      • 0
        То есть по сути, эволюция в обучении должна происходить как-то так:
        Arduino -> AVR -> ARM. Но честно говоря, я не особо испытываю любви к Ардуино. Когда просят провести пробный экскурс в микроконтроллеры, то начинаю с обычного мигания светодиода в Proteus'е и плавно-плавно перехожу ко всяким прерываниям и таймерам. Как по мне — это оптимальный вариант начала работы с МК. Ни тебе чип покупать не надо, ни отладочной платы, ни стенд. Даже спалить ничего невозможно :). Хотя это в свою очередь лишает таких прелестей, как дребезг контактов, транспортные задержки, шумы и прочие прелести отладки реальных схем.
        • 0
          Да, протеус штука полезная. Но от пункта с ардуиной я бы отказался) По себе знаю что при работе с AVRками это все более чем реально собрать с нуля дома — и как раз упомянутые вами «прелести отладки» дают очень полезный опыт. Очень неплохо использовать Протеус в связке с реальными схемами — проверить код в протеусе, чтобы убедиться, что он работает, а потом переносить на реальное железо.
          • 0
            Собственно, про пункт с Ардуино, то что вы написали, то и имелось ввиду :)
  • 0
    Немного оффтоп, но мне сейчас припомнилась статья.
    • 0
      Там срач в комментах насчет ардуин, я опасался что тут тоже такое начнется, но, по счастью, обошлось)
      Жаль я слишком поздно начал STMками заниматься, вдруг сейчас бы уже на харлее ездил? Это все диплом отвлек, одни неприятности от него...)
  • 0
    Кстати, хотел бы поинтересоваться насчет тех сервоприводов, которые упоминаются в статье. Можно ли их использовать для создания модели человеческой руки (нужна для научных исследований)? Можно в принципе не человеческую руку, а клешню (сгибание локтя, поворот клешни, сжимание/расжимание).
    • 0
      А что вы подразумеваете под «можно»? Если соберете механику — почему бы и нет?

      Приводы ограничены по скорости, по нагрузке и точности позиционирования. Вопрос в том, какие значения этих параметров для вас окажутся подходящими.
      Параметры серво, которые использовал я, согласно данным из интернета:

      Weight: 13.4g
      Dimension: 22.8*12.2*28.5mm
      Stall torque: 1.8kg/cm (4.8V) — 2.2kg/cm (6.0V)
      Operating speed: 0.10sec/60degree(4.8v) — 0.08sec/60degree(6.0V)
      Operating voltage: 4.8-6.0V
      • 0
        Stall torque — крутящий момент?
        • 0
          Момент, который его застопорит, ага.
          • 0
            Но из этих данных мне не ясно — какой максимальный вес он способен поднять (если подцепить катушку с ниткой и он эту нитку будет наматывать, поднимая груз). У него стальной сердечник? Шестерни крутить сможет?
            • 0
              Сильно пропорционально зависит от радиуса катушки. Разделите момент на радиус катушки — получите максимальный вес.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.