суббота, 15 августа 2015 г.

Изучаем STM32. Урок 4. Изучаем таймеры. Начальные сведения

Добрый день. Сегодня набросаю первую статейку по таймерам в STM32. Вообще таймеры в STM32 настолько круты, что даже Шварцнегер нервно курит по крутости))) И изучать их придётся не в одной, и не в двух и не в трёх статьях. Но для начала не будем забивать себе сильно головы, а просто изучим первые простые таймеры и поработаем с ними.

В STM32 вообще существует три вида таймеров
1) базовые (basic timers)
2)общего назначения (general-purpose timers)
3)продвинутые (advanced-control timers)


Продвинутые таймеры самые крутые и в себе сочитают возможности двух предыдущих групп, плюс к этому ещё множество дополнительных функций типа работа с трёхфазными моторами и т.д. и т.п. До них нам ещё далеко, поэтому в данной части мы будем рассматривать работу с базовыми (basic timers).
Для начала давайте рассмотрим, какие есть таймеры на нашем процессоре STM32F407VG (вы смотрите про свои процессоры с которыми работаете)). В моём процессоре 14 таймеров — 12 — 16ти битных и 2 32 битных

 
 
Как мы видим на картинках к шине АРВ1 подключены таймеры TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM12
А к шине АРВ2 — TIM1, TIM8, TIM9, TIM10, TIM11
Теперь давайте рассмотрим картинку настройки нашего тактирования в программе CubeMX. Систему тактирования я ещё отдельно опишу, так как без неё никуда, но просто пока покажу как можно затактировать наши таймеры используя внутренний источник тактирования HSI.
Вот наша стандартная настройка тактирования без всяких перемножителей частот и т.д. Её мы и будем использовать.

 
А вот вариант ускорения работы)) Но советую шаловливыми ручёнками туда сильно не лазить, а то может уложить процессор на лопатки)) Это всё мы потом изучим и рассмотрим.
 
  
 
 
Итак, открываем Reference Manual на F4 серию микроконтроллеров, и начинаем курить мануал. ДА, в STM32 не всё так просто, поэтому товарищи учите английский, и читайте мануалы, потому что без этого будете долго искать что к чему. Я раньше как то очень тяжко к чтению документации относился (видать потому что задачи были простыми и мне хватало обычных примеров из интернета). Ну а теперь читаем… читаем…читаем…
Продолжим…
Итак таймеры 6 и 7 являются базовыми таймерами. Сидят они на шине АРВ1 как мы видим на картинке из reference manual.

 
Базовые таймеры 6 и 7 — 16ти битные, имеют настраиваемый предделитель от 0 до 65535. Для этих таймеров есть вот такие регистры доступные для чтения\записи.
Counter Register (TIMx_CNT) — счётчик
Prescaler Register (TIMx_PSC) — предделитель
Auto-Reload Register (TIMx_ARR) — регистр перезагрузки


 
 
 
Не будем сильно углубляться в подробности работы, так как там страниц 10 описания доступных нам регистров и т.д, нам хватит трёх — написанных выше
Итак, что это за регистры и для чего они нам нужны. Да вот для чего. Решили мы тут срочно помигать светодиодом, удивить товарищей AVR-щиков например, и говорим — а давай кто быстрее настроит мигание одним светодиодом с периодом пол секунды, а вторым с периодом в секунду тот и выиграл. (кстати можно проделать подобный эксперимент))))
Для того чтобы это нам реализовать нужно всего 5 шагов — 1
1) Запустить CubeMX и создать проект под наш контроллер.
2)в CubeMX выставить работу таймеров
3) сгенерировать проект и открыть его в Keil uVision
4)проинициализировать таймеры (по одной строчке на таймер)
5)прописать в прерывании каждого таймера код постоянного изменения состояния ножки к которой подключен светодиод.
Итак, давайте это рассмотрим более подробно. Первым делом запускам нашу программу CubeMX
и настраиваем наши 2 вывода PD12 и PD13 на вывод (ножки куда подключены светодиоды). Устанавливаем для них режим GPIO_Output, и режим Output Push_Pull.
Далее слева активируем наши базовые таймеры 6 и 7.


 
теперь переходим в вкладку конфигурации. Как мы помним, мы не стали ничего менять в настройках частот для нашего процессора, поэтому у нас все шины тактируюся частотой -16МГц. Теперь исходя из этого, и исходя из того что нам нужно получить, давайте настроим наши значения предделителей и регистра автоперезагрузки.


  
 
 
Как мы помним, нам нужно чтобы один светодиод мигал с частотой 1Гц (период 1000мсек), а второй с частотой 2Гц (период 500 мсек) . Как нам это получить — да очень просто. Так как предделитель на СТМ32 можно ставить любой, то мы просто вычислим его значение
Итак частота у нас 16 000 000 тиков в секундку, а нужно 1000 тиков в секунду. Значит 16 000 000 \ 1 000 = 16 000. Это число минус 1 и вписываем в значение предделителя . То есть число у нас получается 15999.
Теперь наш таймер тикает с частотой 1000 раз в секунду. Далее, мы должны указать когда же нам нужно прерывание по переполнению. Для этого мы записываем нужное нам число в Counter Period (autoreload register).
То есть нам нужно получить одно прерывание в секунду, а как мы помним наш таймер тикает 1 раз в милисекунду. В одной секнуде — 1000 мсек — значит это значение и вписываем в регистр автоперезагрузки.
Для того, чтобы получить прерывание раз в пол секунды — записываем соответсвенно — 500.
  
 
Как видите проще некуда…
далее, не забываем активировать прерывания для данных таймеров в вкладке NVIC Settings, устанавливая галочку. Всё это дело проделываем и для второго таймера.
 
Итак — настроили, теперь можно смело генерировать наш проект. Сгенерировали, хорошо. осталось совсем чуток до момента мигания светодиодиками.
Открыли наш проект. У нас впринципе всё настроено и готово, только нужно запустить наши таймеры, так как хоть CubeMX всё за нас и делает — этим он уже не занимается. Итак- инициализируем
наши таймеры вот такими строчками

HAL_TIM_Base_Start_IT(&htim6);
HAL_TIM_Base_Start_IT(&htim7);



  
 
 
И далее переходим к файлу stm32f4xx_it.c

 
именно в нём и находятся наши обработчки прерывания для наших таймеров
Вот обработчик прерывания для таймера 7

void TIM7_IRQHandler(void)
{
/* USER CODE BEGIN TIM7_IRQn 0 */

/* USER CODE END TIM7_IRQn 0 */
HAL_TIM_IRQHandler(&htim7);
/* USER CODE BEGIN TIM7_IRQn 1 */

/* USER CODE END TIM7_IRQn 1 */
}


Вписываем в обработчик прерывания то что мы хотим делать — а мы хотим в каждом прерывании менять состояние наших ножек к которым подключены свтеодиоды.
Используем вот такую конструкцию — HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
 
Собственно всё. Нажимаем F7, смотрим чтобы не было ошибок — и можем заливать всё это дел в наш подопытный процессор.
Ну и можем уже наслаждаться интересными перемигиваниями светодиодов.
Видео добавлю чуть позже, ну а пока как обычно правильна картинка. Ну и не забываем про благодарность))

 

пятница, 7 августа 2015 г.

Изучаем STM32. Урок 1. Работаем с CubeMX и CooCox IDE

Добрый вечер. Пока потянуло немного на писанину напишу ещё один урок. В данном уроке мы сконфигурируем наш микроконтроллер расположенный на плате Discovery, и помигаем светодиодом нажимая на кнопку.
Так как в одной записи нельзя вставить более 20 картинок. Урок будет разбит на части.
Итак. на нашей плате расположены 4 светодиода подключённые анодами к ножкам PD12,PD13,PD14,PD15
и кнопка подключена к выводу PA0. Причём кнопка при нажатии замыкается на +3.3В (напряжение питания).
Итак открываем программу STM32Cube MX и выбираем наш процессор который у нас есть. Далее будут картинки в последовательности и немного где нужно описания. Поэтому если где то что то не подписано, то просто действуйте согласно картинкам 
открываем КубеМХ 
Нажимаем — новый проект
  
выбираем в списке нужный нам контроллер
 
 
поваляется наш процессоор с подписанными ножками. Справа, у нас расположена вся периферия процессора. А нажимая на ножки на картинке, мы будем выбирать что это ножка должна делать.
Итак первым делаем настраиваем ножки PD12,PD13,PD14,PD15 на выход GPIO_Output

Далее нам нужно настроить ножку PA0 на вход -выбираем GPIO_Input
 
У нас получается вот такая картинка
 
тут у нас всё .
далее вверху переходим на вкладку Clock_Configuration, Она нам не нужна на данном этапе, просто посмотрите на схемку. Это система тактирования нашего процессора. В данном случае у нас идёт тактирование от внутреннего источника тактирования — HSI.
 
Далее переходим на вкладку Configuration
В этой вкладке настраиваются все параметры прерываний, таймеров, портов и так далее. В этом уроке нам нужно просто настроить порты ввода-вывода.
 
первым настроим порт вводка PA0. Настроим его безо всяких подтяжек, так как все подтяжки к питанию и массе у нас расположены в самой схеме.
 
Далее настраиваем порты вывода к которым подключены светодиоды.
В этом случае мы должны в выпадающем списке GPIO Pull_UP\PulL_Down — выбираем Pull_UP, так как нам нужно то на светодиод подавать напряжение, они то анодами подключены к контроллеру. Настраиваем так все наши 4 порта вывода.
 
Далее, ради интереса можем зайти в вкладку NVIC и посмотреть — в ней мы будем настраивать прерывания и т.д. в следующих проектах.
 
ну и вверху можем нажать на последнюю вкладку — Power Consumption Calculator. В этой вкладке мы можем рассчитывать параметры энергопотребления и т.д. Она нам пока не интересна.
 
Итак, далее мы должны настроить параметры экспорта нашего проекта. Вверху нажимаем кнопочку Project Settings и попадаем в вкладку настройки параметров
 
Выбираем экспорт в формате TrueStudio (кому нужно можно выбрать экспорт в Keil либо Iar)
Далее переходим в вкладку Code Generator, и в ней выбираем Copy only necesary library files
 
Ну собственно теперь нам осталось дать имя проекту и сделать экспорт. По окончанию экспорта, выскочит сообщение в котором мы можем открыть папку с нашим с генерированным проектом.На этом с CubeMX закончили. Переходим к среде разработки Coocox (Кокос в простонародье)))
Открываем Кокос
 
далее вверху выбираем — создать новый проект — Create New Project
 
Далее выбираем CHIP (ведь мы будем работать с процессором)
 
Далее в списке выбираем нужный нам процессор. В моём случает это STM2F407VG6T
 
После этого ствавим галчку напртив CMSIS BOOT. Вместе с ней установится галочка и напротив M4 CMSIS Core — вот её нам нужно снять.
 
Далее в левой части, нам нужно удалить два файла которые начинаются на system и также после этого удаляем файл main.c (он нам не нужен)
 
После этого, нам нужно скопировать папки сгенерированные нашим CubeMX в папку с проектом Кокоса. Копируем три папки.
И далее выделяем эти три папки и перетягиваем их в Кокос (добавляем в проект). Стрелочкой указано куда.
 
Получаем вот такой вид файлов нашего проекта
Далее начинаем раскрывать наш список файлов в папке
Driver->CMSIS->Device->ST->STM32f4xx->Source->Templates-gcc
и удаляем файл startup_.
 
далее сворачиваем пару папок и переходим вот по такому пути
Driver->CMSIS->Device->ST->STM32f4xx->Include и открываем файл отмеченный на картике указателем мыши. В нашем основном окне этот файл откроется. Листаем вниз и ищем наш процессор, и выделяем его как на картинке и нажимаем копировать — это нужно чтобы добавить это название в конфигурацию проекта
 
Далее, нажимаем на корневой файл проекта правой кнопкой мыши и выбираем Configuration
 
У нас откроется вот такое окно
 
Нажимаем в правой части ADD и добавляем скопированое значение в поле как на картинке
 
Получаем пот такой вид
 

Итак далее переходим на вкладку LINK, и в ней выбираем в поле Options — Use BASE C Library
 
ну вот собственно и всё. можем открывать фал main.c и нажать кнопочку F7, и пронаблюдать сборку проекта без ошибок. После этого делаем тройное сальто назад, двойное вперёд, бубин откладываем и ставим чайник)))
 
Ну чтож, давайте набросаем пару строк кода для того чтобы помигать нашим светодиодом
Создаём переменную

uint8_t button;

и пишем вот такие строчки кода
button = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
if (button == 0)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
}
а кто хочет гирлянду впишите вот такой код — светодиодиики будут бегать по кругу
if (button == 0)
{
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(100);
}


ну и подключаем нашу плату к компьютеру и нажимаем Download Code to Flash
 
Ну вот собственно и конец урока 1 в котором мы от начала до конца создали проект и помигали светодиодом.
Ну — и как всегда жмём палец вверх и ждём новых уроков)))