Я думаю, что практически во всех конструкциях радиолюбителей можно смело мигрировать с зоопарка из PIC, AVR и MSP на ARM. Сам я сделал это уже давно, и активно призываю всех кто ещё не поддался веяниям времени — срочно ознакомиться с ARM-контроллерами компании ST. Микроконтроллер STM32F050F4P6 — достойный представитель младшего семейства таких МК. Он будто создан для максимального облегчения такой миграции.

Его киллер-фичи:

  • 32-битное ядро
  • 48МГц скорость работы
  • 16кБ флеша
  • 15 ног ввода-вывода
  • 12-битный быстрый (1 MSPS!) АЦП о 10 каналах
  • DMA-контроллер
  • 9 таймеров, из них один 32-битный, и один таймер с расширенными функциями
  • Стандартные интерфейсы — I2C, SPI, USART
  • Микропотребление
  • Удобный корпус SSOP-20. Он даже похож на DIP, только SMD.

Самое главное для миграции — его входы/выходы толерантны к 5 вольт! И это всё  — представитель самой простой серии МК ST.

Терраэлектроника предлагает его по 28 рублей за штуку в рамках акции. Вдумайтесь! 48МГц 32-битный ARM-микроконтроллер с 1MSPS АЦП — за 28 рублей! Плюс к этому Компел/Терраэлектроника постоянно проводят семинары по применению микроконтроллеров и прочих изделий ST с приглашением иностранных представителей STMicroelectronics, и на которых можно задавать вопросы и общаться с другими инженерами.

Попробовав и изучив этот контроллер, можно перейти на более сложные МК, такие как STM32F200 или даже F400 — в них уже можно найти более быстрое тактирование (вплоть до 168МГц у STM32F407), интерфейсы CAN и USB, и многое другое. Также в этих линейках стандартные интерфейсы всегда присутствуют в количестве нескольких штук: каждая микросхема семейства STM32F200 имеет по 6 UART, 3 SPI, 3 I2C, 2 CAN и 1 ЦАП. Конечно, все эти интерфейсы не получится задействовать одновременно — нередко они делят общие контакты, но в условиях стеснённого корпуса иначе и нельзя сделать.

ST сделали очень широкую линейку продуктов «на все случаи жизни», среди которых всегда можно найти компромисс между потреблением и мощностью, количеством контактов ввода-вывода и занимаемым местом, количеством интерфейсов и ценой, объёмом памяти и гибкостью DMA.

Вернёмся к описанному микроконтроллеру. Кроме того, что я перечислил, он имеет модуль вычисления CRC, множество вариантов схем тактирования, температурный сенсор, часы реального времени, мощные контакты ввода-вывода с возможностью прямого включения светодиодов. Самое главное — он имеет мощное ядро, которое при низкой стоимости и малом потреблении обеспечивает огромную производительность вычислений сравнительно с всеми AVR и PIC. Я уж не говорю о (прости, господи) ардуино.

Нет смысла приводить пример разработки изделия на нём, потому что можно купить макетную плату, и отрабатывать умения на ней. На плате к вашим услугам 2 пользовательских светодиода, кнопка, гребёнка на которую выведены все контакты процессора и bredboard-плата с дырочками, а самое главное — программатор/дебаггер ST-LINK/V2, позволяющий вести отладку в реальном времени. К нему прилагаются примеры применения, охватывающие практически все возможные применения кристалла:

  • работа с таймерами
  • порты ввода-вывода
  • управление питанием
  • ЦАП одиночные отсчёты
  • Генерация сигналов на ЦАП
  • АЦП

и другое.

Даташит на STM32F050F4P6.

Использование ножек GPIO

Попробуем использовать ножки GPIO. Все проекты я веду в среде IAR с применением стандартной библиотеки, однако сейчас перехожу на собственную библиотеку itacone.

Версия для библиотеки StdPeriph

Подключаем модуль stm32f0xx_gpio.c.

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_ResetBits(GPIOC, GPIO_Pin_8);

volatile int i, n_on=10000000, n_off=n_on;
while(1)
{
  GPIO_SetBits(GPIOC, GPIO_Pin_8);
  i=0; while(i++<n_on);
  GPIO_ResetBits(GPIOC, GPIO_Pin_8);
  i=0; while(i++<n_off);
}

Версия для библиотеки itacone

#include <itacone.h>

PC8.mode(OUT).low();

while(1) PC8.toggle().delayMs(100);

Версия с прямым обращением к регистрам

RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
GPIOC->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0;
GPIOC->BSRR |= GPIO_BSRR_BS9;

volatile int i, n_on=10000000, n_off=n_on;
while(1)
{
  GPIOC->BSRR |= GPIO_BSRR_BS9;
  i=0; while(i++<n_on);
  GPIOC->BRR |= GPIO_BRR_BR9;
  i=0; while(i++<n_off);
}

По-моему, всё очень просто.