Библиотека матричной клавиатуры для stm32f4 discovery

Библиотека матричной клавиатуры для STM32F4 Discovery

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

Начнем с подключения всех необходимых библиотек, объявления переменных, а так же присвоения структурам GPIO_InitTypeDef и TIM_TimeBaseInitTypeDef более простых имен GPIO и TIM соответственно.

Далее необходимо произвести конфигурирование порта, к которому будет подключена наша клавиатура, таймера, который будет использоваться для опроса клавиатуры , а так же написать код для обработчика запроса на прерывание от используемого таймера:

В этой части программы мы заполняем стандартные структуры GPIO_InitTypeDef и TIM_TimeBaseInitTypeDef необходимыми параметрами, чтобы задать для таймера и порта ввода вывода требуемый режим работы. В обработчике запроса на прерывание от второго таймера (функция TIM2_IRQHandler ) мы обращаемся к функции Keyboard(), листинг которой представлен ниже:

Алгоритм, который реализуется данной частью кода в общем виде описан в предыдущей статье с той лишь разницей, что теперь выводы, относящиеся к столбам клавиатуры являются питающими ( PA4 — PA6 ), а выводы строк сканируются на наличие высокого потенциала ( PA0 — PA3 ). Цикл for(Sdvig = 16; Sdvig 0b10000 (16), затем 0b100000 (32), затем 0b1000000 (64), а команда GPIO_Write(GPIOA, Sdvig) выставляет на порту, к которому подключена клавиатура значение этой переменной, то есть «сдвигает» напряжение логической единицы от пина PA4 до PA6 и нам остается только определить, на каком из первых четырех контактов находится высокий потенциал при нажатии кнопки.

Так как нам необходимо зафиксировать изменение только на младших выводах, то уместно применить операцию побитного логического умножения (так называемую «маску»), чтобы не фиксировать изменения на выводах 4, 5, 6. Это позволит упростить следующие логические выражения, и выполнять последующий код только после того, как будет нажата какая — либо клавиша.

Если на одном из первых четырех выводов зафиксировано напряжение логической единицы (значение переменной Temp будет отличаться от 0), мы проверяем значение переменной y (флаг, разрешающий обрабатывать нажатие следующей кнопки), в случае, если оно равно 0, переходим к циклу for (Temp; Temp == Temp2; Vkl++), который в течении 10ти итераций проверяет, остается ли нажатой кнопка, и затем переходит к выполнению функции Key_Number(). 10 итераций необходимы для прекращения дребезга контактов, а так же предохраняет от ложной регистрации нажатий. Переменная у, является флагом, единичное значение которого запрещает регистрировать любые другие нажатия клавиш и сигнализирует о том, что нажатая до этого кнопка еще не отпущена. Программа будет «ждать» до тех пор, пока мы не отпустим уже нажатую кнопку и только тогда значение переменной у станет равным 0.

В функции Key_Number() мы выполняем операцию поразрядного логического сложения для переменных Temp и Sdvig, что позволяет получить значение, выставленное в порт, и однозначно определить, какая клавиша нажата в данный момент. В данном случае нет возможности использовать команду типа GPIO_Read*******, так как первые четыре вывода работают на вход, а остальные на выход и в итоге, при попытке чтения, мы получаем ложные данные. Если нажаты одновременно несколько клавиш, то программа будет ждать момента, когда они будут отпущены.

Основным недостатком данной библиотеки является сложность настройки «под себя». Клавиатура всегда должна быть подключена только к одному порту и пины должны идти подряд, но можно очень легко изменить порт, к которому подключается клавиатура на любой другой. При большом желании можно «поднять» пины, то есть изменить PA0 — PA6 на, например, PA7 — PA13, но при этом необходимо будет изменить условие для цикла for(Sdvig = 16; Sdvig в функции Key_Number() результаты case`ов.

Для демонстрации работы библиотеки был использован дисплей WH1602d, а так же,найденная на просторах интернета, библиотека для его подключения (пины для подключения дисплея перечислены в самом начале прикрепленного ниже проекта). Также в проекте была немного дополнена функция Key_Number(), функцией вывода данных на дисплей. К статье прикреплены файлы самой библиотеки, а так же файлы демонстрационного проекта. При разработке использовалась среда CooCox CoIDE v 1.7.6.

Подключение матричной клавиатуры к STM32F4Discovery

Линейка микроконтроллеров STM32 представляет собой достаточно интересный объект для изучения. Часто можно услышать мнение, что работа с ним сложна для начинающего и лучше браться за что – нибудь более простое. В этой статье мы постараемся показать, что микроконтроллеры STM32 не так страшны.

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

При работе, описанной в данной статье, использовалась отладочная плата STM32F4Discovery и матричная клавиатура, в нашем случае, имеющая 7 выводов. Среда разработки CoIDE 1.7.6.

Для того, чтобы разобраться в программе, реализующей данную операцию, необходимо иметь минимальные знания и навыки работы с портами ввода/вывода и системными таймерами. С существующими методами подключения клавиатуры можно познакомиться по ссылке [1].

Перед тем, как приступать к написанию программы, определимся с условными обозначениями:

  1. Выводы, к которым подключается клавиатура, разделены на две группы: сканирующие и питающие (рисунок 1). Сканирующие выводы работают на вход. Все питающие выводы по умолчанию установлены в нулевое состояние, но после первого сброса таймера TIM2 на выводе PA3 будет установлено напряжение логической «1», поэтому с некоторым приближением можно сказать, что на питающих выводах в момент времени, близкий к начальному, выставлена комбинация «1-0-0-0».
  2. По тексту программы обозначения выводов будут соответствовать рисунку 1, т.е. значения выводов PA0, PA1, PA2 при их опросе записываются в переменные a, b, c соответственно, для дальнейших операций с ними.
  3. Питающие выводы PA3 – РА4 имеют обозначения от 1 до 4, именно под такими номерами они упоминаются в тексте программы.


Рисунок 1 – Подключение клавиатуры

Перейдем к описанию алгоритма действия программы. После включения питания запускаются два таймера (TIM2 и TIM3), которые работают циклически, т.е. при завершении счета выполняются некоторые действия (эти действия прописаны в функциях обработчиках прерываний от таймеров TIM2 и TIM3) и отсчет начинается заново. По окончании первого отсчета таймера TIM2 на выводе РА3 появляется уровень логической «1», который каждый раз, при окончании счета этого таймера, смещается на одну позицию вниз. При этом микроконтроллер всегда «знает», на каком выводе в данный момент находится уровень напряжения логической «1», эта информация хранится в переменной out_state. Операцию по «сдвигу» логической «1» выполняет функция TIM2_IRQHandler (обработчик прерывания от таймера 2).

Таймер TIM3 при окончании каждого цикла сканирует состояние выводов РА0-РА2, записывая полученные результаты в переменные a, b и c. Затем, микроконтроллер сравнивает на каком из питающих выводов находится напряжение логической «1» (переменная out_state) и какой из выводов РА0 – РА2 имеет высокий логический уровень (переменные a, b, c). Эти действия выполняет функция TIM3_IRQHandler (обработчик прерывания от таймера 3).

При нажатии, например, кнопки «3», высокий логический уровень должен быть установлен на выводе РА3 и зарегистрирован на выводе PA0. При выполнении данного логического выражения микроконтроллер «поймет», что была нажата клавиша «3» и при нажатии этой кнопки выполнит предписанное ему действие, в нашем случае погасит все светодиоды, а затем зажжет зеленый светодиод.

Используемая процедура сравнения позволяет различать между собой одновременное нажатие одной, двух, трех и более клавиш (при доработке функции TIM3_IRQHandler) и присвоение такому событию определенного действия.

В данном примере, для того чтобы понять правильно или нет написана программа, использованы различные комбинации светодиодов, расположенных на плате, клавиша 5 – выключает все светодиоды.

Очень важно разобраться, какие выводы на клавиатуре соответствуют нажатым клавишам. Необходимо выделить строки и столбцы (деление на строки и столбцы в данном случае весьма условно, так как это зависит от формы и положения клавиатуры. Примем по умолчанию, что столбцы – это линия «3-6-9-#» и т.д., а строки – «3-2-1» и т.д.), т.к. столбцы соединяются со сканирующими выводами, строки – с выводами питания. Для правильного определения выводов на матричной клавиатуре необходимо подключить один из щупов мультиметра, находящегося в режиме прозвонки, к любому крайнему контакту, а второй щуп подключать к остальным контактам, одновременно нажимая на клавиши, расположенные в одном столбце. Если при нажатии на любую клавишу два вывода не прозваниваются – это значит, что они оба принадлежат к одной группе (строчных или столбиковых выводов). После того, как все выводы будут разбиты на две группы, можно переходить к определению порядка их размещения внутри групп. При этом, при фиксированном подключении к одному столбиковому выводу, необходимо менять контакты из второй группы нажимая одновременно с этим только клавиши, принадлежащие к одному столбцу.

Читайте также  Балансир для зарядки литиевых аккумуляторов

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

Теперь поговорим об инициализации используемой периферии. В этом проекте используются порты A и D, как порты ввода-вывода, а так же таймеры TIM2 и TIM3. Листинг программы снабжен подробными комментариями по пунктам настройки периферии.

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

К сожалению, данная программа лишена простой возможности настройки кода под себя, но, если разобрать код построчно, то Вы сможете реализовать подключение клавиатур различного размера и функционала, как цифровых, так и символьных. Кроме этого изменяя код обработчика таймера TIM2, можно привязывать к клавишам определенные функции или вывод символов на экран (данный проект находится в разработке).

Статья подготовлена с использованием методических указаний [2].

Быстрый старт с микроконтроллерами STM32F4. Создание проекта.

Давно, даже очень давно, не было новых статей на нашем статье, так что пришло время наверстывать Сегодня мы положим начало изучению STM32F4. И, наверное, начнем с создания нового проекта для этих контроллеров, хотя не хотел я, честно говоря, про это писать статью, так как новый проект тут создается, в принципе, так же как и для STM32F103 (про это тут). Но все-таки бывает, что именно с STM32F4 возникают некоторые трудности, так что, все-таки, рассмотрим этот процесс в подробностях!

Так что, запускаем Keil, создаем новый проект – Project – New uVision Project. Сохраняем новый проект в какой-нибудь папке, и затем нам предложат выбрать используемый микроконтроллер. Что ж, выбираем, пусть это будет STM32F407VG:

Готово, в появившемся диалоговом окне тыкаем «Да» и к нам в проект добавится первый файл – startup_stm32f4xx.s. Также как и раньше, мы будем использовать библиотеки CMSIS и Standard Peripheral Library, но, естественно, уже для контроллеров STM32F4xx. Так что надо их обязательно скачать и добавить нужные файлы в наш пока еще пустой проект. Кстати не раз слышал от разных людей, что попадаются какие то «не такие» библиотеки для F4, и проект даже простейший не собирается. Сам я с таким не сталкивался, тем не менее, вот проверенные библиотеки, которые я сам использую:

  • Скачать STM32F4 SPL – Standard Peripheral Library
  • Скачать STM32F4 CMSIS – CMSIS

Либо можно использовать новую библиотеку HAL Driver, которая пришла на смену вышеупомянутым и работает в связке с STM32CubeMx.

Итак, скачали, все готово, теперь добавляем файлы в проект. На картинке видно, какие понадобятся:

Ну вот и закончена подготовка, теперь создадим новый .c файл, в котором и будет наш код. Идем в File – New, в Keil’е открывается пустой файл, жмем File – Save as и сохраняем его под именем test.c, например. Не забываем при сохранении указать расширение файла (.c). Файл создали, отлично, но надо его еще и в проект наш добавить. Ну, собственно, в этом ничего сложного нету В этот файл запишем тестовую пустую программу:

Почти все уже готово, осталось заглянуть в настройки проекта – Project – Options for target… Открывается окошко с множеством вкладок, нас тут интересуют лишь несколько. Открываем вкладку C/C++ и в поле Define прописываем:

  • USE_STDPERIPH_DRIVER,STM32F4XX

Ну и внизу в поле Include Paths надо добавить пути абсолютно ко всем файлам, включенным в проект. После выполнения этого шага можно давить на F7 (Build), и проект соберется без ошибок и предупреждений. Как видите, ничего сложного!

Но вообще я лично делаю несколько иначе. Смотрите в чем минус такого подхода. Вот мы скачали себе куда-то библиотеки CMSIS и SPL, добавили файлы из этих папок, прописали пути к файлам, все круто. НО! Проект не соберется на другом компьютере, поскольку пути все абсолютные, то есть указывают на конкретные папки на вашем компьютере. И на другой машине придется фактически заново выполнять действия по созданию нового проекта. Это огромнейший минус. Поэтому я обычно создаю отдельную папку для нового проекта, в ней создаю подпапки для CMSIS, SPL и других используемых библиотек и в эти папки запихиваю все файлы, которые мне понадобятся в каждом конкретном проекте. Вот, например, создадим папку STM32F4_Test для нашего нового проекта и в ней следующие папки:

В папки CMSIS и SPL я засунул все необходимые файлы, которые мы добавляли, создавая проект, в начале статьи. Теперь запускаем Keil, создаем новый проект и сохраняем его в нашу подпапку Project, чтобы все файлы проекта лежали в одном месте и не устраивали хаос.

Проект создан, теперь, как и раньше просто добавляем в него все файлы из папок STM32F4_CMSIS и STM32F4_SPL. В папку Source запихиваем наш тестовый .c файл с функцией main() и его тоже добавляем в проект. Осталось настроить настройки =) Все то же самое – в поле define прописываем:

  • USE_STDPERIPH_DRIVER,STM32F4XX

В Include Paths:

Собираем проект – ошибок нет, полет нормальный! В принципе в итоге получили то тоже самое, но теперь проект будет без проблем сразу собираться на любом другом компьютере, а это очень удобно и полезно ) Абсолютно все файлы проекта теперь лежат рядом, в одной папке, а пути стали относительными и их не придется менять.

На этом то, собственно все, в ближайшее время что-нибудь поделаем для программирования STM32F4, обязательно, так что до скорого!;)

Полный проект из примера статьи – empty_project

STM Урок 3. Библиотека SPL. Подключаем кнопку

Урок 3

Библиотека SPL. Подключаем кнопку

Сегодня мы с вами продолжим работу с библиотекой SPL, которую мы подключили на прошлом занятии. Хотя это прошло слегка нестандартным способом, но тем не менее нам это удалось. Вообщем, библиотеку мы подключили, но практически с её функциями мы пока не работали.

Проект для сегодняшнего занятия был сделан из предыдущего занятия. Как это делается, мы все уже видели. Назван проект был TEST003.

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

Теперь можно начинать написание нового кода.

Подключим к плате светодиодную матрицу, состоящую из 10 светодиодов.

Также мы не забываем в цепь каждого светодиода включить токоограничивающий резистор. У меня резисторы исользуются номиналом в 680 ом. Вот схема подключения (нажмите на картинку для увеличения изображения)

Чтобы нам работать с портом, нам. как известно, необходимо запустить его тактирование. Хотя мы это уже делали, но делали мы это не с помощью библиотеки В справочном файле, находящемся в папке со скачанной библиотекой мы попробуем найти, каким образом мы это сможем сделать.

Вот так выглядит данная функция в справке.

Почему мы выбрали именно данную шину? Это объясняется и в Reference Manual на контроллер, а также есть и в справке дальше в объяснении функции. Практически все порты ввода-выводы находятся именно на этой шине

У данной функции 2 аргумента. Первый – это указатель на саму периферию AHB1 и порт ввода-вывода, который мы собираемся начинать тактировать ну или заканчивать, а второй параметр – это команда, она и отвечает за включение или отключение тактирования (ENABLE или DISABLE). Давайте добавим данную функцию в наш код. Откроем файл main.h и вставим код в функцию port_ini. Пока код будем вставлять поверх старого, чтобы ничего не забыть

void port_ini(void)
<
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//включим тактирование порта D

Теперь порт у нас тактируется. Затем нужно нам включить всё остальное.

Сначала инициализация ножек порта. Для этого нам нужна будет структура. Тут есть один нюанс. Данная структура должна быть объявлена до включения тактирования. Вот такая вот структура

Объявим структуру. Имя может быть любое. Но надо привыкать присваивать переменным, структурам, массивам такие имена, чтобы они сами о себе говорили. Тогда у нас будет меньше шансов не понять свой код в дальнейшем и запутаться в нём. Особенно, если этот код мы хотим кому-то показать

void port_ini(void)
<
GPIO_InitTypeDef InitD; //для светодиодов

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//включим тактирование порта D

В любой структуре перед её использованием нужно заполнить поля. Давайте этим займёмся.

Первое поле будет GPIO_Pin. В том же файле справки есть варианты данного поля

Данное поле говорит о том, какие именно ножки порта мы будем использовать. Перечисляются они через операцию «ИЛИ»

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//включим тактирование порта D

//светодиоды
InitD.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|
GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;

Таким образом мы объявляем для инициализации в поле структуры определённые ножки порта.

Следующее поле структуры – GPIO_Mode, это также структура, и здесь у нас есть вот такие вот варианты выбора

Читайте также  Кабель для скрытой проводки в квартире

Я думаю данные варианты сами о себе прекрасно говорят.

В нашем случае потребуется конфигурация порта на выход

InitD.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|
GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
InitD.GPIO_Mode = GPIO_Mode_OUT;

Следующее поле – GPIO_OType.

Здесь тоже ничего сложного. Выбираем тип Pull Push, открытый коллектор нам не нужен

InitD.GPIO_Mode = GPIO_Mode_OUT;
InitD.GPIO_OType = GPIO_OType_PP;

Следующее поле – GPIO_Speed:

Есть также синонимы.

#define GPIO_Speed_2MHz GPIO_Low_Speed
#define GPIO_Speed_25MHz GPIO_Medium_Speed
#define GPIO_Speed_50MHz GPIO_Fast_Speed
#define GPIO_Speed_100MHz GPIO_High_Speed

Выбираем 2 МГц. Нам спешить некуда

InitD.GPIO_OType = GPIO_OType_PP;
InitD.GPIO_Speed = GPIO_Speed_2MHz;

И последний параметр (поле) структуры – это GPIO_PuPd, который отвечает за подтягивание резистора к ондой из шины питания.

Мы никуда подтягиваться не будем

InitD.GPIO_Speed = GPIO_Speed_2MHz;
InitD.GPIO_PuPd = GPIO_PuPd_NOPULL;

Теперь, когда мы нашу структуру или перечисление заполнили, то нам необходимо, используя данную структуру, инициализировать порт.

Вот функция. Файл справки тот же

Первый параметр – это порт, а второй – указатель на нашу только что заполненную структуру, причем именно указатель.

InitD.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD,&InitD); //инициализация ножек порта

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

Давайте теперь перейдём в main() и в бесконечном цикле исправим код следующим образом

while(1)
<
GPIO_SetBits(GPIOD, GPIO_Pin_0);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_0);
GPIO_SetBits(GPIOD, GPIO_Pin_1);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_2);
GPIO_SetBits(GPIOD, GPIO_Pin_3);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_3);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_5);
GPIO_SetBits(GPIOD, GPIO_Pin_6);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
GPIO_SetBits(GPIOD, GPIO_Pin_7);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);
GPIO_SetBits(GPIOD, GPIO_Pin_8);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_8);
GPIO_SetBits(GPIOD, GPIO_Pin_9);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_9);

>

Скомпилируем код и прошьём контроллер. Светодиоды у нас зажигиются по очереди, то есть код наш работает.

Теперь исправим немного код в бесконечном цикле, чтобы предыдущий светодиод у нас гас не сразу, а на следующем цикле, и бежать тогда у нас буду одновременно два огонька

<
GPIO_SetBits(GPIOD, GPIO_Pin_0);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_9);
GPIO_SetBits(GPIOD, GPIO_Pin_1);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_3);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_2);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_3);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_6);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_5);
GPIO_SetBits(GPIOD, GPIO_Pin_7);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
GPIO_SetBits(GPIOD, GPIO_Pin_8);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);
GPIO_SetBits(GPIOD, GPIO_Pin_9);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_8);
>

Прошьём и посмотрим результат.

Вообщем, научились мы управлять ножками портов на выход. Теперь попробуем отследить состояние порта, которое будет зависеть от подключенной на плате синей кноки. Данная кнопка подключена к ножке 0 порта A, то есть к PA0

Но так как кнопка подключена уже не к порту D, то порт A мы должны также инициализировать, сначала включим для него тактирование, так как тактирование портов у нас отключено из соображений энергоэффективности. Сначала создадим структуру

GPIO_InitTypeDef InitA0; //для кнопки
GPIO_InitTypeDef InitD; //для светодиодов

Запустим тактирование порта, таким же образом проинициализируем поля структуры, соответственно используюя там инициализацию на вход (GPIO_Mode_IN) и в конце вызовем функцию инициализации ножки 0 порта

GPIO_Init(GPIOD,&InitD); //инициализация ножек порта

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//включим тактирование порта A

//кнопка
InitA0.GPIO_Pin = GPIO_Pin_0;
InitA0.GPIO_Mode = GPIO_Mode_IN;
InitA0.GPIO_OType = GPIO_OType_OD;
InitA0.GPIO_Speed = GPIO_Speed_2MHz;
InitA0.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&InitA0); //инициализация ножек порта

>

А отслеживать состояние ножки мы будем при помощи вот такой функции, похожей также и на ту, с помощью которой мы управляем портами, включенными на выход

Вернёмся в main() в бесконечный цикл и обернём наш код в бесконечном цикле в условие

while(1)
<
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) //кнопка нажата
<

GPIO_SetBits(GPIOD, GPIO_Pin_0);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_9);
GPIO_SetBits(GPIOD, GPIO_Pin_1);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_0);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_3);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_2);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_3);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_6);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_5);
GPIO_SetBits(GPIOD, GPIO_Pin_7);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
GPIO_SetBits(GPIOD, GPIO_Pin_8);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);
GPIO_SetBits(GPIOD, GPIO_Pin_9);
delay(1000000);
GPIO_ResetBits(GPIOD, GPIO_Pin_8);
>
else GPIO_ResetBits(GPIOD,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|
GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
>

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

ARM-микроконтроллеры STM32F. Быстрый старт c STM32-Discovery

При изучении любого незнакомого дела, особенно когда речь идет о микроконтроллерах, возникает вопрос — «С чего начать». Ведутся поиски статей по ключевым словам «Getting Started», неизбежно появляется дилема выбора среды разработки и программатора-отладчика. Чтобы помочь вам определиться с ответами на возникшие вопросы, я поделюсь своим опытом в освоении 32-битных контроллеров семейства STM32F от ST Microelectronics.

Выбор контроллера

Вариантов по сути дела было два — STM32F или NXP (LPC1xxx). На микроконтроллеры STM32F мой выбор пал по нескольким причинам.

Во-первых, дешёвая отладочная плата STM32VL-Discovery. Некоторые из вас, кто занимается электроникой, наверняка успели урвать халявную Discovery, бесплатно раздаваемую при участии в конкурсе от EBV-Electronik. Тем, кто не успел подать заявку или вообще не знал о такой возможности, расстраиваться не стоит — плата стоит порядка 500 рублей. Цена более чем доступная.

Во-вторых, сами контроллеры довольно дешёвые. Простейший камень STM32F100C4T6 c 16 килобайтами на борту стоит меньше 40 рублей (!), при этом по характеристикам и периферии уделывает любую «Мегу», которая, кстати, всё равно стоит дороже. Цена на камни старшей линейки с аппаратным USB (STM32F103) тоже вполне гуманна, порядка 120 рублей.

В-третьих, контроллеры активно начинают набирать интерес у электронщиков, статьи по освоению STM32 появляются в интернетах одна за другой. Если так пойдет и дальше, популярность вполне может достигнуть уровня контроллеров Atmel.

Единственное по сравнению с тем же Atmel неудобство для радиолюбителя, это мелкий корпус. Про DIP можете забыть. Единственный доступный корпус — это LQFP с шагом ножек 0.5 мм. Тем не менее, плату при определенной сноровке изготовить ЛУТом не составит труда (об этом мы уже читали), так что мелкий корпус минусом я не считаю. На фото слева — моя плата для корпуса LQFP48.

Пара слов об отладочной плате STM32VL-Discovery: на борту у неё программатор-отладчик ST-Link и отлаживаемый (target) контроллер STM32F100RBT6 (128 кб флеша, 8 кб оперативы). Все выводы разведены на штырьки, имеется два светодиода и кнопка. Разъём SWD отладчика выведен наружу, так что плату можно использовать и как обычный ST-Link. Это нам на руку, не понадобится покупать программатор.

Выбор среды разработки

Здесь не всё так однозначно, как с атмеловской AVR Studio. Вариантов несколько:

  • IAR. Коммерческая. Ограничение по объёму исполняемого кода. Нафиг.
  • Keil. То же самое. Нафиг.
  • Atollic TrueStudio. Основана на Eclipse, но, тем не менее, является коммерческой. В бесплатной Lite-версии ограничения по объёму кода нет, но регулярно выскакивает рекламка «Приобретайте версию PRO». Нафиг.
  • Чистый Eclipse с плагином ARM и компилятором ARM-GCC. Вроде вот оно, кроссплатформенное счастье, но откуда ни возьмись появляется еще более подходящая кандидатура:
  • CooCox IDE (CoIDE). Тоже основана на Eclipse, но бесплатна. Включает в себя всё для работы с ARM, позволяет не отходя от кассы докачивать необходимые библиотеки. Умеет работать с различнями отладчиками (правда не с ST-Link, но это обходится установкой GNU Debugger’a). Единственный минус — сборка есть только под винду. Линуксятникам придется ставить Eclipse и настраивать его руками. Как обычно. Ну да ничего, нам не привыкать.

Что ж, мой выбор сделан. Вы можете его оспорить, предложить писать в блокноте, компилировать мейкфайлами или вообще остановитесь на коммерческих решениях, выступив против священного GCC. Но лично я считаю CoIDE просто идеальной средой разработки, по крайней мере, для быстрого старта. Начните с неё. А там видно будет.

Собственно, Getting Started!

Итак, нам понадобятся:

  1. Плата STM32VL-Discovery
  2. Утилита STM32 ST-Link Utility
  3. Среда разработки CoIDE последней версии (на данный момент это 1.3.0).

Запускаем CoIDE. Нам любезно предлагают выбрать производителя контроллера, затем и сам чип. Выбираем STM32F100RBT6, именно он находится на Discovery. Далее мы видим страницу выбора подключаемых библиотек, которая и сыграла решающую роль при выборе среды разработки:

Здесь есть и библиотека CMSIS для ядра ARM Cortex M3, и STM32 Peripheral Library (библиотека для работы с периферией от ST Microelectronics), а так же собственные разработки CooCox для выбранного микроконтроллера. Нам достаточно лишь отметить галочкой требуемые библиотеки и дело в шляпе. Для простейшей светодиодной моргалки — а именно так выглядит «Hello World» на микроконтроллерах — нам понадобятся CMSIS Core, CMSIS Boot, RCC (управление тактированием периферии) и GPIO (управление портами ввода-вывода общего назначения).

Без лишних пояснений напишу код простейшей программы:

Компилируем (F7), наблюдаем появившиеся в директории Debug исполняемые файлы — bin, hex, elf.

Прошивка контроллера

Программу мы подготовили, теперь займёмся её загрузкой в чип. Подключаем плату (об установке драйверов пояснять не стану), запускаем ST-Link Utility. Контроллер в Discovery подключен по SWD, поэтому первое, что надо сделать, это переключить режим работы программатора-отладчика с JTAG на SWD:

Далее всё прозрачно: меню Target -> Program & Verify… выбираем файл hex, жмём Program и прошивка завершена. Остается только нажать на плате Discovery кнопку Reset — ту, что с черным колпачком — и порадоваться моргающему светодиоду.

Читайте также  Слаботочный кабель открытой проводки

Поздравляю. Ваша первая программа написана, скомпилирована, прошита в чип и успешно работает. Начало положено, а далее дело за вами: лезем в шаблонный код, как обычно что-то изменяем, дополняем, изучаем новые периферийные устройства, подключаем новые библиотеки. И не забываем читать Reference Manual, в нём масса полезной информации.

Обновление: Начиная с версии 1.3.0 среда разработки CooCox IDE поддерживает ST-Link, поэтому программирование и отладку можно осуществлять прямо из CoIDE, без использования ST-Link Utility. Выбор адаптера через меню Debug -> Debug Configuration (ST-Link, порт SWD). Загрузка программы в контроллер через меню Flash -> Program Download.

На этом всё. Желаю успехов в освоении микроконтроллеров ST Microelectronics.

STM32 – микроконтроллер для начинающих после Arduino

Микроконтроллер STM32 – популярная и очень востребованная платформа, позволяющая создавать профессиональные решения для автоматизации в самых различных областях. В отличие от доступного Arduino, STM32 требует более глубокого погружения в детали, она сложнее для начинающих, для нее меньше учебников на русском. В этой статье мы постараемся дать базовую информацию о платформе, ее истории, подскажем, где можно скачать программы и библиотеки, как написать первый скетч.

Что такое STM32

STM32 – это платформа, в основе которой лежат микроконтроллеры STMicroelectronics на базе ARM процессора, различные модули и периферия, а также программные решения (IDE) для работы с железом. Решения на базе stm активно используются благодаря производительности микроконтроллера, его удачной архитектуре, малом энергопотреблении, небольшой цене. В настоящее время STM32 состоит уже из нескольких линеек для самых разных предназначений.

История появления

Серия STM32 была выпущена в 2010 году. До этого компанией STMicroelectronics уже выпускались 4 семейства микроконтроллеров на базе ARM, но они были хуже по своим характеристикам. Контроллеры STM32 получились оптимальными по свойствам и цене. Изначально они выпускались в 14 вариантах, которые были разделены на 2 группы – с тактовой частотой до 2 МГц и с частотой до 36 МГц. Программное обеспечение у обеих групп одинаковое, как и расположение контактов. Первые изделия выпускались со встроенной флеш-памятью 128 кбайт и ОЗУ 20 кбайт. Сейчас линейка существенно расширилась, появились новые представители с повышенными значениями ОЗУ и Flash памяти.

Достоинства и недостатки STM32

  • Низкая стоимость;
  • Удобство использования;
  • Большой выбор сред разработки;
  • Чипы взаимозаменяемы – если не хватает ресурсов одного микроконтроллера, его можно заменить на более мощной, не меняя самой схемы и платы;
  • Высокая производительность;
  • Удобная отладка микроконтроллера.
  • Высокий порог вхождения;
  • На данный момент не так много литературы по STM32;
  • Большинство созданных библиотек уже устарели, проще создавать свои собственные.

Минусы STM32 не дают пока микроконтроллеру стать заменой Ардуино.

Сравнение STM32 с Arduino

По техническим характеристикам Ардуино проигрывает STM32. Тактовая частота микроконтроллеров Ардуино ниже – 16 МГц против 72 МГц STM32. Количество выводов GRIO у STM32 больше. Объем памяти у STM32 также выше. Нельзя не отметить pin-to-pin совместимость STM32 – для замены одного изделия на другое не нужно менять плату. Но полностью заменить ардуино конкуренты не могут. В первую очередь это связано с высоким порогом вхождения – для работы с STM32 нужно иметь базис. Платы Ардуино более распространены, и, если у пользователя возникает проблема, найти решение можно на форумах. Также для Ардуино созданы различные шилды и модули, расширяющие функционал. Несмотря на преимущества, по соотношению цена/качество выигрывает STM32.

Семейство микроконтроллеров STM32 отличается от своих конкурентов отличным поведением при температурах от -40С до +80 С. Высокая производительность не уменьшается, в отличие от Ардуино. Также можно найти изделия, работающие при температурах до 105С.

Обзор продуктовых линеек

Семейство STM32 имеет широкий ассортимент изделий, различающихся по объему памяти, производительности, потреблению энергии и другим характеристикам.

Серии STM32F-1, STM32F-2 и STM32L полностью совместимы. Каждая из серий имеет десятки микросхем, которые можно без труда поменять на другие изделия. STM32F-1 была первой линейкой, ее производительность была ограничена. Из-за этого по характеристикам контроллеры быстро догнали изделия семейства Stellaris и LPC17. Позднее была выпущена STM32F-2 с улучшенными характеристиками – тактовая частота достигала 120 МГц. Отличается высокой процессорной мощностью, которая достигнута благодаря новой технологии производства 90 нм. Линейка STM32L представлена моделями, которые изготовлены по специальному технологическому процессу. Утечки транзисторов минимальны, благодаря чему приборы показывают лучшие значения.

Важно отметить, что контроллеры линейки STM32W не имеют pin-to-pin совместимости с STM32F-1, STM32F-2 и STM32L. Причина заключается в том, что линейку разрабатывала компания, которая предоставила радиочастотную часть. Это наложило ограничения на разработку для компании ST.

STM32F100R4

Микросхема STM32F100R4 имеет минимальный набор функций. Объем флэш памяти составляет 16 Кбайт, ОЗУ – 4 Кбайт, тактовая частота составляет 12 МГц. Если требуется более быстрое устройство с увеличенным объемом флэш-памяти до 128 Кбайт, подойдет STM32F101RB. USB интерфейс имеется у изделия STM32F103RE. Существует аналогичное устройство, но с более низким потреблением – это STM32L151RB.

Программное обеспечение для работы с контроллером

Для ARM архитектуры разработано множество сред разработки. К самым известным и дорогостоящим относятся инструменты фирм Keil и IAR System. Программы этих компаний предлагают самые продвинутые инструментарии для оптимизации кода. Также дополнительно существуют различные системы – USB стеки, TCP/IP-стеки и прочие. Применяя системы Keil, пользователь получает хороший уровень технической поддержки.

Также для STM32 используется среда разработки Eclipse и построенные на ней системы Atollic TrueStudio (платная) и CooCox IDE (CoIDE) (бесплатная). Обычно используется последняя. Ее преимущества перед другими средами разработки:

  • Свободно распространяемое программное обеспечение;
  • Удобство использования;
  • Имеется много примеров, которые можно загрузить.

Единственный недостаток среды разработки CooCox IDE – сборка есть только под Windows.

STM32 Discovery

Начать изучение микроконтроллера STM32 лучше с платы Discovery. Это связано с тем, что на этой плате есть встроенный программатор. Его можно подключить к компьютеру через USB кабель и использовать как в качестве программируемого микроконтроллера, так и для внешних устройств. Плата Discovery имеет полную разводку пинов с контроллера на пины платы. На плату можно подключать различные сенсоры, микрофоны и другие периферийные устройства.

Что потребуется для подключения STM32 к компьютеру

Чтобы начать работу, потребуются следующие компоненты:

  • Сама плата STM32 Discovery;
  • Datasheet на выбранную модель;
  • Reference manual на микроконтроллер;
  • Установленная на компьютер среда разработки.

В качестве примера первая программа будет рассмотрена в среде CooCox IDE.

Первая программа

Обучение следует начинать с простейшего – с Hello World. Для начала нужно установить CooCox IDE на компьютер. Установка стандартная:

  • Скачивается программа с официального сайта;
  • Там нужно ввести адрес своей электронной почты и начать загрузку файла с расширением .exe;
  • Нужно открыть CooCox IDE вкладку Project, Select Toolchain Path;
  • Указать путь к файлу;
  • Снова открыть среду разработки и нажать View -> Configuration на вкладку Debugger;
  • Теперь можно записывать программу.

Когда программа установлена, ее нужно открыть. Следует перейти во вкладку Browse in Repository и выбрать ST – свой микроконтроллер.

Далее на экране появится список библиотек, которые можно подключить. Для первой программы потребуются системные CMSIS core и CMSIS Boot, библиотека для работы с системой тактирования RCC, GPIO для работами с пинами.

Сама программа пишется как и для Ардуино, нужно знать основы языка Си.

В окошке Project следует открыть main.c. В коде в самом начале следует подключить библиотеки кроме CMSIS (они уже автоматически подключены). Добавляются они следующим образом:

Затем добавляется тактирование порта в главной функции main. Какой контакт за что ответственен, можно просмотреть в даташите к микроконтроллеру.

Для настройки параметров выводов следует прописать ее название и поставить точку. Во всплывающем меню будут указаны все характеристики. Их можно исправлять.

После этого нужно сделать зацикливание в while, чтобы светодиод мигал, пока не отключится питание.

Когда программа написана, ее можно загружать в контроллер. Если есть отладочная плата, ее нужно подключить через USB кабель и нажать Download Code To Flash. Если плата отсутствует, потребуется переходник, который нужно подключить к порту компьютера. Контакт BOOT 0 подключается к плюсу питания контроллера, а затем включается само питание МК. После этого начнется прошивка.

Чтобы загрузить программу в микроконтроллер, нужно следовать указаниям от приложения. Сначала прописывается код порта, к которому подключен микроконтроллер. Также указывается скорость. Советуется брать небольшое значение, чтобы не было сбоев. Программа найдет микроконтроллер, и нужно будет нажать кнопку «далее». Во вкладке Download to device нужно в поле Download from file выбрать написанную программу и нажать «далее».

После этого нужно отключить питание контроллера STM32, закрыть Flash Loader Demonstrator, выключить переходник. Теперь можно снова включить микроконтроллер в обычном режиме. Когда программа будет загружена, светодиод начнет мигать.

Работа в других программах проходит подобным образом. Также выбираются нужные библиотеки, и прописывается код. У платных утилит функционал больше, и можно создавать более сложные проекты.