37
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ МОСКОВСКИЙ АВИАЦИОННЫЙ ИНСТИТУТ (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ УНИВЕРСИТЕТ) Дисциплина: Проектирование устройств на программируемой элементной базе Учебное пособие по лабораторной работе №2 Учебное пособие по лабораторной работе №1 Применение языка СИ для программирования портов дискретного ввода-вывода микроконтроллеров STM32 в среде KEIL m VisionУтверждено на заседании каф 404 ____________ 2015 г. Москва Самиздат каф 404 МАИ 2015

(НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

  • Upload
    others

  • View
    23

  • Download
    0

Embed Size (px)

Citation preview

Page 1: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

МОСКОВСКИЙ АВИАЦИОННЫЙ ИНСТИТУТ (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ УНИВЕРСИТЕТ)

Дисциплина:

Проектирование устройств

на программируемой элементной базе

Учебное пособие по лабораторной работе №2

Учебное пособие по лабораторной работе №1

Применение языка СИ для программирования

портов дискретного ввода-вывода

микроконтроллеров STM32

в среде “KEIL m Vision”

Утверждено на заседании каф 404 ____________ 2015 г.

Москва

Самиздат каф 404 МАИ

2015

Page 2: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

2

УДК: 621.???????)

Авторы

А.Н. Шишков,

Ознакомление с языком программирования СИ

Учебное пособие к лабораторным работам по дисциплине «Проектирование

устройств на программируемой элементной базе»./ А.Н. Шишков, — М.: Изд-во

МАИ, 2015. —?? с.: ил.

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

Предназначено для студентов, обучающихся по специальности «,,,» в качестве пособия при выполнении лабораторных работ.

Рецензенты:

ISBN © Московский авиационный институт (государственный технический университет), 2015

Page 3: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

3

Содержание

1 Структура программы на языке СИ для микроконтроллеров STM32 ..................................... 5

2 Типы данных, переменные и массивы ........................................................................................ 6

3 Функции ......................................................................................................................................... 9

4 Операторы .................................................................................................................................... 10

5 Препроцессор и комментарии .................................................................................................... 15

6 Стандартные библиотеки языка С ............................................................................................. 16

7 Описание микроконтроллера STM32F051R8T6 ...................................................................... 20

8 Стандартная библиотека CMSIS ............................................................................................... 22

9 Отладочная плата STM32F0DISCOVERY ............................................................................... 24

10 Среда программирования Keil μVision ................................................................................... 28

11 Описание проекта LEDproject1 ................................................................................................ 34

12 Порядок выполнения лабораторной работы .......................................................................... 35

13 Содержание отчёта:................................................................................................................... 36

14 Контрольные вопросы .............................................................................................................. 37

Page 4: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

4

Использованные сокращения

МК- микроконтроллер

ФМ -функциональный модуль

LED –light emissiom diode (светодиод)

Page 5: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

5

Введение

К 2015 году микроконтроллеры с процессором Cortex практически полностью захватили

рынок цифровой техники благодаря своей низкой стоимости и высокому быстродействию.

Компания STMicroelectronics выпускает линейки микроконтроллеров STM32, которые обладают

очень большим набором современных функциональных модулей. Именно благодаря наличию

функциональных модулей микроконтроллеры очень выгодно использовать в своих разработках.

Но, без прикладного программного обеспечения эти микроконтроллеры бесполезны. Поэтому,

каждому современному инженеру приходится не только разрабатывать электрические схемы, но и

писать прошивки для микроконтроллеров.

Как известно, управление процессором и функциональными модулями осуществляется

через регистры. Регистры – это простейшие ячейки памяти, которые имеют совой адрес. Поэтому,

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

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

которой есть специальные команды для работы с регистрами. На заре развития микроэлектроники

все программы писались именно на ассемблере. Со временем программы достигли больших

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

переносить программное обеспечение с одной платформы на другую было очень проблематично.

Такие языки как FORTRAN, Basic и др. не имели такого гибкого инструментария, который

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

годов был разработан язык СИ, в котором были учтены все недостатки других высокоуровневых

языков программирования.

С годами язык СИ зарекомендовал себя как кросс – платформенный Assembler. Благодаря

ему код стал более читаемым и легко переносимым с одной платформы на другую. На СИ и по сей

день пишут все драйвера.

Данное руководство не является полным описанием языка СИ. Материала, изложенного в

данном руководстве достаточно только для выполнения лабораторных работ по курсу ПУ на ПЭБ.

1 Структура программы на языке СИ для микроконтроллеров STM32

По традиции первая программа на Си для микроконтроллеров зажигает светодиод. Мы не

будем нарушать эту традицию.

#include "stm32f0xx.h"

void main(void)

{

//Включение тактирования порта С (со светодиодами)

RCC->AHBENR = RCC_AHBENR_GPIOCEN;

GPIOC->MODER = GPIO_MODER_MODER8_0; //PC8 - выход

GPIOC->OSPEEDR = GPIO_OSPEEDER_OSPEEDR8; //Максимальная частота

GPIOC->OTYPER = ~ GPIO_OTYPER_OT_8; //push-pull

GPIOC->PUPDR = ~ GPIO_PUPDR_PUPDR8_0; //Без подягивающего резистора

GPIOC->ODR = GPIO_ODR_8; //зажечь светодиод на выводе РС8

}

Page 6: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

6

Директива #include "stm32f0xx.h" подключает заголовочный файл stm32f0xx.h, который

обеспечивает работу с периферийным модулем GPIO и другими функциональными модулями

семейства микроконтроллеров CORTEX M0. В этом заголовочном hex файле определены имена

всех регистров функциональных модулей. Так в частности 16- ти битный порт “C” дискретного

ввода/вывода определён как структура, состоящая из набора регистров. Определён указатель на

эту структуру с именем GPIOC. Значение этого указателя (т.е. адрес структуры) также определён в

файле stm32f0xx.h в соответствии с реальным адресом группы регистров порта С в используемом

микроконтроллере.

Меняя имя файла в директиве #include "хххххх.h" можно настраивать компилятор на

конкретный образец микроконтроллера.

void main(void) – имя основной программы, оно всегда присутствует и не может изменяться;

Описатель типа void означает отсутствие значения. Т.е функции main() нельзя передавать

аргументы и она ничего не возвращает.

{ } – скобки, ограничивающие тело программы;

Производится программирование регистров настройки периферийного модуля GPIO для

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

плате.

Каждый оператор завершается символом «точка с запятой», который является атрибутом

оператора, указывающим на его конец.

Таким образом, любая программа должна содержать заголовочный файл stm32f0xx.h и

функцию main().

2 Типы данных, переменные и массивы

2.1 Основные типы

Таблица 1– Типы данных

Тип Ключевое слово Ключевое слово в Keil

Символьный char uint8_t

Целочисленный short uint16_t

Целочисленный int uint32_t

С плавающей запятой float -

С плавающей запятой двойной точности double -

Пустой void -

Таблица 2– Целочисленные типы данных

Тип данных Размер, байт Диапазон

char 1 -127 – 127

unsigned char 1 0 - 255

short 2 -32 768 – 32 768

unsigned short 2 0 – 65 535

int 4 -2 147 483 647 - 2 147 483 647

unsigned int 4 0 – 4 294 967 295

long 4 -2 147 483 647 - 2 147 483 647

unsigned long 4 0 – 4 294 967 295

Таблица 3– Вещественные типы данных

Тип данных Размер, байт Нижняя граница диапазона Верхняя граница диапазона

float 4 3.4Е-38 3.4Е+38

double 8 1.7Е-308 1.7Е+308

long double 10 3.4Е-4932 3.4Е+4932

Page 7: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

7

2.2 Переменные

Переменная – это место в оперативной памяти микроконтроллера, где можно размещать

хранимое значение, а затем извлекать его оттуда.

Переменные должны быть объявлены до их использования. Общая форма объявления имеет

вид:

тип имя_переменной;

Например, чтобы объявить flag переменной типа int, необходимо записать следующее:

int flag;

Переменную можно инициализировать, записав после ее имени знак равенства и начальное

значение. Например, следующее объявление позволяет присвоить переменной flag начальное

значение 0:

int flag = 0;

2.3 Массивы

Массив - это набор элементов, способных хранить данные одинакового типа. Массив можно

представить в виде ряда ячеек для хранения данных в ОЗУ микроконтроллера. Каждая из таких

ячеек называется элементом массива.

Массивы могут быть объявлены с использованием любого типа данных. Общая форма

объявления одномерного массива:

тип имя_массива[размер];

Здесь тип определяет данных для каждого элемента массива, а размер указывает количество

элементов в массиве. Например, чтобы объявит символьный массив buff из 10 элементов,

запишите следующее:

char buff[10];

Эта запись создает массив, содержащий 10 элементов, причем номер первого элемента – 0, а

последнего – 9.

Массивы можно объявлять, используя допустимый тип данных, в том числе созданные

программистом структуры.

Массивы можно инициализировать с помощью списка инициализаторов, заключенных в

фигурные скобки, как показано ниже.

char buff[10] = {“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “k”, “l”};

char buff[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

В Си размерность массива должна быт задана константным значением. Другими словами,

размерность массива фиксируется на этапе компиляции и не может быть изменена при

выполнении программы.

2.4 Определение новых имен типов данных с помощью ключевого слова typedef

С помощью ключевого слова typedef можно создавать новое имя для уже существующего

типа данных. Общая форма записи:

typedef тип новое_имя_типа

Например, следующая программная инструкция сообщает компилятору, что uint8_t – это

еще одно имя для типа unsigned char.

Page 8: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

8

typedef unsigned char uint8_t; // это определение в файле stdint.h в библиотеке CMSIS

После этого следующее объявление совершенно законно и создает строковую переменную с

именем text.

uint8_t text;

2.5 Структуры

Несмотря на то, что язык Си предоставляет широкий спектр стандартных типов данных,

иногда бывает удобно объединить переменные в более сложные конструкции, чем это

предусмотрено языком программирования. Для этих целей в языке Си существуют специальные

средства, позволяющие программистам конструировать свои типы данных. К этим средствам

относятся структуры.

Структура – это одна или несколько переменных одного или различных типов, которые

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

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

(структуру) трактовать не как множество отдельных элементов, а как единое целое.

Объявляют структуру с помощью ключевого слова struct, за которым следует

идентификатор, являющийся именем типа структуры, и список полей или членов структуры,

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

заканчивается точнкой с запятой:

struct имя_структуры {тип имя_поля;

тип имя_поля;

…..

};

Пример объявления структуры

struct time { int minute;

int hour;

};

После того как объявлен структурный тип, компилятор «знает», что в программе создан

некоторый собственный тип данных. Однако пользоваться этим типом нельзя до того, пока не

объявлена переменная структурного типа.

Для того, чтобы получить возможность использования структуры, следует сначала объявит

переменную структурного типа. Это можно сделать двумя способами:

1) struct time watch;

2) struct time { int minute;

int hour;

}watch;

Второй способ одновременно объявляет структуру (структурный шаблон) и выделяет

память под переменную структурного типа.

В момент создания структурной переменной компилятор резервирует под нее место в

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

программы.

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

том числе массивы или другие структуры.

Page 9: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

9

3 Функции

3.1 Объявление и определение функции

Функция – это логически завершенный и определенным образом оформленный фрагмент

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

большие вычислительные задачи на более мелкие и дают возможность пользоваться уже

написанными подпрограммами, в том числе и другими разработчиками.

Чтобы написать новую функцию, её сначала необходимо объявить.

Объявление функции сообщает компилятору ее имя. Тип возвращаемого значения и

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

исполняемого кода.

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

выполнен при её вызове, т.е. определить функцию.

Определение функции предоставляет компилятору исполняемый код функции. Ни одна

функция не может вызывать другую, если та не была заранее объявлена. Именно здесь содержится

исполняемый код.

Основная форма записи функций:

тип_результата имя_функции( список_параметров )

{

// Тело функции

return возвращаемое_значение;

}

Тип данных, возвращаемый функцией, задается с помощью элемента тип_результата. Под

элементом список_параметров подразумевается список разделенных запятыми переменных,

которые могут принимать любые аргументы, передаваемые функции. Например, следующая

функция принимает один целый параметр с именем time:

void delay_ms(int time);

При обнаружении последней фигурной скобки работа функции завершается, и управление

автоматически передается вызывающей процедуре. Однако с помощью инструкции return можно

выполнит принудительный («преждевременный») возврат в вызывающую процедуру.

Все функции, за исключением тех, которые объявлены с помощью ключевого слова void,

возвращают значение. Тип возвращаемого значения должен совпадать с объявлением типа

функции (тип_результата). Сам же результат выполнения функции возвращается посредством

инструкции return.

3.2 Прототипы функций

Программа, содержащая функции, может не содержать их прототипов. При этом

необходимо, чтобы ее определение находилось до первого обращения к ней.

3.3 Локальные и глобальны переменные

Любые переменные, объявленные внутри функции (в том числе и внутри функции main ),

называются локальными и существуют в памяти микроконтроллера, только пока функция активна.

Переменные, объявленные вне функций (в том числе и вне функции main), называются

глобальными.

Page 10: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

10

3.4 Функция main()

С функции main() начинается выполнение программы. Программа не должна имеет больше

одной функции main(). По окончании работы функции main() работа программы завершается.

Функция main() не имеет прототипа.

4 Операторы

4.1 Арифметические операторы

Оператор Действие

- Вычитание, унарный минус

+ Сложение

* Умножение

/ Деление

% Деление по модулю

-- Декремент

++ Инкремент

Операция инкремента прибавляет к операнду единицу, а операция декремента вычитает из

операнда единицу:

i++ эквивалентно i=i+1;

i -- эквивалентно i = i-1.

4.2 Операторы отношений и логические операторы

Оператор Значение

> Больше

>= Больше или равно

< Меньше

<= Меньше или равно

== Равно

!= Не равно

Логические операторы

Оператор Значение

&& И

| | ИЛИ

! НЕ

4.3 Побитовые и сдвиговые операторы

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

определены только для целочисленных операндов (переменными). Не следует путать побитовые и

логические операции языка Си.

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

Побитовые и сдвиговые операторы сведены в таблицу

Оператор Значение

& И

| ИЛИ

^ Исключающее ИЛИ

~ Инверсия

>> Сдвиг вправо

<< Сдвиг влево

Page 11: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

11

Результаты выполнения побитовых операций приведены в таблице 5

Таблица 5-Таблица истинности для операторов ~, &, | и ^

A B ~B A & B A | B A ^ B

0 0 1 0 0 0

0 1 0 0 1 1

1 1 1 1 0

1 0 0 1 1

Операторы сдвига сдвигают все биты на заданное количество разрядов. При сдвиге биты с

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

Число, стоящее справа от оператора, указывает количество сдвигаемых разрядов. Общая

форма записи имеет вид:

Значение >> количество_ сдвигаемых_ разрядов

Значение << количество_ сдвигаемых_ разрядов

Примечание.

Сдвиг вправо эквивалентен делению на 2, а сдвиг влево – умножению на 2. Для всех

микроконтроллеров операция сдвига выполняется намного быстрее, чем умножение или деление.

Пример. Значение переменной х сначала умножается, а затем делится на 2.

int x;

x=10;

x = x << 1; //умножить на 2

x = x >> 1; //делим на 2

4.4 Адресные операторы

Адресными называют операторы & и *.

Оператор получения адреса &.

Оператор & возвращает адрес объекта, перед которым он стоит. Например, если переменная

Z расположена в ОЗУ по адресу 0x20001000, то после выполнения оператора

Y = &Z;

в переменную Y будет помещено значение 0x20001000.

Оператор разыменования адреса *.

Оператор * использует текущее значение стоящей после него переменной в качестве адреса,

по которому могут быть записаны или получены некоторые значения.

Пример:

X = &Z; /* помещаем адрес переменной Z в переменную Х */

*X = 500; /* используем адрес, содержащийся в переменной Х */

Значение 500 будет помещено в переменную Z. Оператор * можно трактовать как фразу «по

адресу». В данном примере вторую строку можно прочитать следующим образом: «размещаем

значение 500 по адресу Х». Поскольку переменная Х содержит адрес переменной Z, то значение

500 фактически сохраняется в переменной Z. О переменной Х говорят, что она указывает на

переменную Z.

Page 12: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

12

Указатель – это объект (переменная), содержащий адрес другого объекта (переменная,

массив, структура и тд.) в памяти (ОЗУ или ПЗУ). Об объекте, который содержит адрес другого

объекта, говорят, что он указывает на адрес другого объекта в памяти.

Таким образом, переменная X будет указателем на адрес переменной Z.

4.5 Операторы присвоения

Использование этого представления связано с ускорением работы программы. Например,

выполнение оператора а=а+5 приводит к двукратному определению адреса переменной а: для

нахождения исходного значения и для занесения полученного результата. Эту избыточность

можно ликвидировать, записав а+=5. Здесь адрес определяется всего один раз, так как оператор

интерпретируется как «к содержимому переменной а прибавит 5»

Полный набор операций с присваиванием: *=, /=, +=, -=, %=, <<=, >>=, &=, ^=, |= .

Оператор Эквивалент

X = X * 25 X *= 25

X = X / 25 X /= 25

X = X + 25 X += 25

X = X - 25 X -= 25

X = X % 25 X %= 25

X = X << 25 X <<= 25

X = X >>25 X >>= 25

X = X & 0xFF X &= 0xFF

X = X ^ 0xFF X ^= 0xFF

X = X | 0xFF X |= 0xFF

4.6 Оператор доступа к членам объектов

Оператор . (точка) и оператор -> (стрелка) используются для доступа к отдельным членам

структур и объединений. Оператор «точка» применяется к реальному объекту, а оператор

«стрелка» используется с указателем на объект.

4.7 Приоритеты операторов

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

наивысший приоритет – 16, самый низкий – 1.

Page 13: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

13

Приоритет Оператор Описание Направление

16 :: Разрешение видимости Слева направо

15

(имя типа) {init} составной литерал (C99)

Слева направо

++ положительное приращение

-- отрицательное

Sizeof размер

~ побитовое НЕ

! логическое НЕ

- + изменение знака, плюс

& адрес

* опосредование (разыменование)

(имя типа) приведение типа

14 Слева направо

13

*

/

%

мультипликативные операции Слева направо

12 +

- аддитивные операции Слева направо

11 << сдвиг влево

Слева направо >> сдвиг вправо

10

< меньше

Слева направо > больше

<= Меньше или равно

>= Ольше или равно

9 ==

!=

Равенство Слева направо

неравенство

8 & побитовое И Слева направо

7 ^ побитовое исключающее ИЛИ Слева направо

6 | побитовое ИЛИ Слева направо

5 && логическое И Слева направо

4 || логическое ИЛИ Слева направо

3 ? : условие Слева направо

2

=

присваение Слева направо

+=

-=

*=

/=

%=

<<=

>>=

&=

^=

|=

1 , последовательное вычисление Слева направо

Page 14: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

14

4.8 Оператор if – else

if - оператор условного перехода.

Позволяет проверить условие (например, равны ли две переменные) и, в зависимости от

результата выполнить тот или иной участок кода.

Выражение в круглых скобках может быть любым, но обычно оно содержит операторы

отношения.

if( выражение )

{ //подпрограмма №1

}

else

{ //подпрограмма №2

}

Если выражение в круглых скобках истинно, то перейти к выполнению подпрограммы №1,

ели ложно, то к подпрограмме №2

4.9 Оператор while

Оператор цикла с предварительным условием (с предусловием).

Выполнят повторяющиеся действия до тех пор, пока выражение в круглых скобках не

станет ложью.

while (условие входа в цикл)

{ оператор_1;

оператор_2;

……….

оператор_ N;

}

Если в круглых скобках стоит 1, то цикл будет выполняться бесконечно.

Page 15: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

15

5 Препроцессор и комментарии

5.1 Препроцессор

Препроцессор предназначен для изменения текста исходного кода во время компиляции.

При каждом запуске компилятора сначала запускается препроцессор, который ищет

инструкции препроцессора, начинающиеся символом решетки (#). Задачей этих инструкций

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

исходного кода, который пользователю обычно не виден.

Сам компилятор читает не настоящий файл исходного кода, а результат работы

препроцессора, и именно его компилирует в исполняемый файл.

#define

Директива #define позволяет задать строку подстановки.

Форма записи:

#define ИМЯ_МАКРОСА ПОСЛЕДОВАТЕЛНОСТЬ_ СИМВОЛОВ

Сообщает компилятору: каждый текстовый фрагмент, определенный как ИМЯ_МАКРОСА,

заменить элементом ПОСЛЕДОВАТЕЛНОСТЬ_ СИМВОЛОВ.

Пример.

#define BAUDRATE 115200UL

В этой строке препроцессору предписано заменить слово BAUDRATE строкой 115200UL в

любом месте программы. Замене подлежат символы в самом тексте исходного кода.

#include

Сообщает компилятору, что необходимо переключиться с текущего файла и прочитать и

скомпилировать исходный файл, указанный в опрераторе. Логически это равносильно к

вставлению при компиляции указанного файла в место оператора #include. Используя этот

оператор компилируется один программный модуль из нескольких текстовых файлов. Основное

применение этого оператора- использование типовых определений функций среды

программпирования и архитектуры (регистров функциональных модулей) МК.

Угловые скобки, в которых заключено имя файла, означают, что этот файл нужно искать во

всех папках, отведенных для хранения подобных файлов.

Пример:

#include “stm32f0xx.h” – подключает файл с определением архитектуры семейства Cortex

M0 фирмы STM ( наименование моделей МК начинается с букв STM32F0, например МК,

используемый в наших ЛР STM32F050 )

#include “math.h” - подключает файл с определением стандартных математических функций,

которые имеет в своём составе среда программирования (файлы библиотек обьектных кодов

функций)

Все фунции разбиты на группы и описаны в разных файлах. Описание всех имеющихся

функций в одном файле перегрузило бы помпилятор и существенно замедлило бы его работу.

Программист в начале текста модуля(программы) подключает только те группы функций,

которые он использует далее по тексту в текущем модуле (программе)

5.2 Комментарии

Комментарии представляют собой текст, который игнорируется компилятором, но

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

пояснения кода.

Page 16: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

16

В языке Си используются два типа комментариев: с двойной наклонной чертой ( // ) и

сочетанием наклонной черты и звездочки ( /* ).

Комментарий в одну строчку начинается с символов //. Компилятор игнорирует все, что

следует за символами / / до конца строки.

Комментарии в несколько строк начинаются символом /* и заканчиваются */. Компилятор

игнорирует все, что начинается за символом /*, до того момента, пока не встретится символ

завершения комментариев: звездочки и наклонной черты (*/ ).

Пример:

int main(void)

{

//Включение тактирования порта С (со светодиодами)

RCC->AHBENR = RCC_AHBENR_GPIOCEN;

/* Это комментарий, который продолжается до тех пор,

пока не встретится символ конца комментария

в виде звездочки и наклонной черты */

GPIOC->MODER = GPIO_MODER_MODER8_0; //PC8 - выход

GPIOC->OSPEEDR = GPIO_OSPEEDER_OSPEEDR8; //Максимальная частота

GPIOC->OTYPER = ~ GPIO_OTYPER_OT_8; //push-pull

GPIOC->PUPDR = ~ GPIO_PUPDR_PUPDR8_0; //Без подягивающего резистора

GPIOC->ODR = GPIO_ODR_8; //зажечь светодиод РС8

}

6 Стандартные библиотеки языка С

6.1 Краткое описание

В Си нет ключевых слов, которые обеспечивают ввод – вывод данных, обрабатывающих

строки, где выполняются математические вычисления или другие полезные процедуры. Все эти

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

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

оттуда компоновщиком LINK при сборке загрузочного файла программы. В заголовочных файлах

описаны функции, сгруппированные по назначению. В описании каждой функции указано

сколько аргументов у функции и какого типа каждый аргумент, и какое значение (какого типа)

возвращает сама функция при возврате. Описание функций позволяет компилятору отслеживать

правильность вызова этих функций в тексте программы (количество и тип аргументов).

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

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

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

написания прошивок для микроконтроллеров STM32.

Заголовочный файл Назначение

<math.h> Математические функции

<stdio.h> Ввод – вывод файлов, строк

<string.h> Функция обработки строк

Page 17: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

17

6.2 Стандартные функции языка С

6.2.1 Функция printf()

int print(char *buf, const char *format, …); Функция print производит форматный вывод в стандартный поток вывода. В качестве

стандартного потока вывода обычно при программировании МК считается один из

последовательных интерфейсов или экран и это описано в конкретном компиляторе. Поток можно

переопределить, написав свою фунцию putchar(char byte) вывода одного байта в стандартный

поток вывода, которую вызывает функция printf().

6.2.2 Функция sprintf

#include "stdio.h"

int sprint(char *buf, const char *format, …); Выходной поток записывается в массив, адресуемый указателем buf.

Строка формирования, на которую указывает format, состоит из элементов двух типов. К

элементам первого типа относятся символы, которые выводятся на экран. Элементы второго типа

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

Команда форматирования начинается с символа процента, за которым следует код формата.

Количество аргументов должно совпадать с количеством команд форматирования, причем

совпадение обязательно и в порядке их следования.

Команды форматирования перечислены ниже

Код Формат

%а Шестнадцатеричное целое число в формате 0хh.hhhhp+d

%А Шестнадцатеричное целое число в формате 0Xh.hhhhP+d

%с Символ типа char

%d Десятичное число целого типа со знаком

%i Десятичное число целого типа со знаком

%e Экспоненциальное представление (строчная буква е)

%E Экспоненциальное представление (прописная буква E)

%f Десятичное число с плавающей точкой

%о Восьмеричное целое число без знака

%s Строка символов

%u Десятичное число целого типа без знака

%х Шестнадцатеричное целое число без знака (буквы нижнего регистра)

%Х Шестнадцатеричное целое число без знака (буквы верхнего регистра)

%р Выводит на экран значение указателя

%% Выводит символ %

Функция sprint() возвращает значение значение равно числу символов, помещенных в

массив.

Для вывода текста в языке Си разрешено использовать ряд специальных символов.

Пример:

chan=11;

sprintf(txt_buf, "Измеренное напряжение канала %Х равно U=%d В\n\r", chan,

u[chan]*kalibr/100);

SendUSART((uint8_t *)txt_buf);

Page 18: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

18

функция sprintf запишет в буфер текстовую строку с управляющими символами перевода на

новую строку и возврат каретки в начало строки; функция SendUSART отправит содержимое

буфера по USART. В результате на экране будет произведен вывод строки :

Измеренное напряжение канала В равно U=217 В " и перевод каретки на

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

использование символов.

Строчное описание упр. символа Значение

\b Возврат на одну позицию

\f Подача страницы (для перехода к началу

следующей страницы)

\n Новая строка

\r Возврат каретки

\t Горизонтальная табуляция

\” Двойная кавычка

\’ Одинарная кавычка (апостроф)

\\ Обратная косая черта

\v Вертикальная табуляция

\a Звуковой сигнал (звонок)

\N Восьмеричная константа, где N – восьмеричная

константа

\xN Шестнадцатеричная константа, где N –

шестнадцатеричная константа

\? Вопросительный знак

6.2.3 Функция sscanf

#include <stdio.h>

int sscanf(const char *buf, const char *format, …)

Функция sscanf() считывает данные из массива, адресуемого параметром buf исохраняет

информацию в переменных, заданных аргументами, перечисленными в списке аргументов. Она

может считывать все встроенные типы данных и автоматически преобразовывать их в

соответствующий внутренний формат.

Функция sscanf() возвращает число, равное количеству переменных, которым реально были

присвоены значения. К ним не относятся поля, опущенные вследствие использования

модификатора команды формата *. Нулевое значение свидетельствует о том, что ни одному полю

не было присвоено значение, а значение EOF сигнализирует об ошибке, обнаруженной до первого

присвоения.

Управляющая строка, задаваемая параметром format, состоит из символов трех категорий:

спецификаторов формата;

«пробельных» символов (пробелы, символы табуляции и пустой строки);

символов, отличных от «пробельных».

Все переменные, используемые для приема значений с помощью функции sscanf должны

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

переменные (или именами массивов).

Спецификаторы формата – им предшествует знак процента (%) – сообщаю, какого типа

значение будет считано следующим. Спецификаторы читаются слева направо. Эти коды

приведены в следующей таблице

Page 19: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

19

Код Значение

%а Считывает значение с плавающей запятой

%А Аналогично коду %а

%с Считывает один символ

%d Считывает десятичное целое число

%i Считывает целое число в любом формате (десятичное, восьмеричное,

шестнадцатеричное)

%e Считывает вещественное число

%о Считывает восьмеричное число

%s Считывает строку

%u Считывает десятичное целое число без знака

%х Считывает шестнадцатеричное число

%р Считывает указатель

%% Считывает знак процента

%[ ] Просматривает набор символов

Например функция sscanf переписывает десятичное число в символьном виде из массива

buff в переменную voltage в двоичном виде.

sscanf(buff,"%d",&voltage);

Page 20: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

20

7 Описание микроконтроллера STM32F051R8T6

7.1 Основные характеристики

Компания STMicroelectronics выпускает на базе ядра ARM® Cortex линейку 32-х битных

микроконтроллеров STM32.

Эти микроконтроллеры нашли широкое применение как в радиолюбительской, так и в

промышленной технике. С годами они зарекомендовали себя как надежные и

высокопроизводительные.

В данном цикле лабораторных работ изучается модель STM32F051R8T6. От других

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

памяти.

Основные характеристики STM32F051R8T6:

Разрядность -32 бита

Ядро ARM® Cortex™-M0 (семейство) с производительностью 0.9 DMIPS/МГц

Тактовая частота до 48 МГц

Объем внутренней Flash — памяти от 16 кБайт до 64 кБайт

Объем памяти ОЗУ SRAM от 4 кБайт до 8 кБайт

Диапазон напряжения питания от 1.8 В (2.0 В) до 3.6 В

Четыре режима работы со сверхнизким энергопотреблением, в том числе режим Stop

(ток потребления 5.8 мкА) и режим Standby с работающими часами реального

времени (ток потребления 2.8 мкА)

Интегрированные модули высокоскоростных последовательных интерфейсов:

2 х USART со скоростью передачи данных до 6 Мбит/с

2 х SPI со скоростью передачи данных до 18 Мбит/с (размер кадра от 4 бит до 16-

бит)

2 х I2C со скоростью передачи данных до 1 Мбит/с (fast-mode plus)

HDMI CEC

Интегрированные периферийные модули:

16-битный таймер с 3-фазной схемой ШИМ для управления электродвигателем

5 x 16-битных таймеров со схемой ШИМ

16-битный базовый таймер

32-битный таймер со схемой ШИМ

Порты ввода / вывода с частотой переключения состояний до 12 МГц

Последовательный отладочный интерфейс (SWD).

96-битный уникальный код продукта.

Диапазон рабочих температур от -40°C до +105°C.

Доступен в корпусах LQFP64, LQFP48 и UFQFPN32.

7.1.1 Регистры портов

Количество 16 –ти разрядных портов зависит от количества выводов у конкретной модели

МК. В данной ЛР МК STM32F051R8T6 имеет 64-х выводный корпус (буква R в типе МК) и

соответственно порты A,B,C ( по 16 бит),D (1 бит) ,F (6 бит). У микроконтроллеров линейки

STM32 имеется возможность настроить режим работы каждого вывода порта в отдельности. Для

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

вывода микросхемы. Список регистров и их краткое описание приведены ниже.

Page 21: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

21

GPIOx_MODER – устанавливается тип вывода. Вывод может быть выходом или входом.

Если через конкретный вывод работает некоторый функциональный модуль микроконтроллера, то

этот вывод нужно установить в режим альтернативной функции.

GPIOx_OTYPER – устанавливается тип, если вывод работает в качестве выхода. Вывод

может быть с открытым стоком или коллектором.

GPIOx_OSPEEDR – устанавливается скорость работы вывода.

GPIOx_PUPDR – программирование Pull-up, Pull-down резисторов

GPIOx_IDR – входной регистр порта. Если вывод находится в режиме входа, то при низком

или высоком уровне на выводе в регистре будет логический 0 или 1 соответственно.

GPIOx_ODR – выходной регистр порта. Если вывод находится в режиме выхода, то запись

логического 0 ли 1 создает низкий или высокий уровень напряжения соответственно.

GPIOx_BSRR – установить/сбросить значения регистра ODR.

Запись 1 в младшие биты 0-15 устанавливает соответствующий бит ODR в 1

Запись 1 в старшие биты 16-31 устанавливает соответствующий бит (0-15) ODR в 0 ( аналог

GPIOx_BRR)

GPIOx_LCKR – блокировка настроек регистров GPIO. При установки соответствующего

бита для конкретного порта приведет к блокировке настроек этого порта и в дальнейшем нельзя

будет изменить настройки порта.

GPIOx_AFRL, GPIOx_AFRH – выбор альтернативной функции. Если вывод в режиме

альтернативной функции, то в эти регистры записывается номер альтернативной функции для

конкретного функционального модуля.

GPIOx_BRR – сбрасывает биты регистра GPIOx_ODR

Более подробное описание регистров приведено в [1] на страницах 159 – 165.

Подключение тактирования к порту А, к которому подключена кнопка В1 на отладочной

плате STM32F0DISCOVERY (смотри описание далее), и к порту С со светодиодами производится

с помощью регистра RCC_AHBENR функционального модуля тактирования (подробнее

рассмотрим в лаб. работе №2). В этом регистре за порты А и С отвечают биты 17 и 19

соответственно.

7.1.2 Последовательность инициализации

Для начала работы с портами микроконтроллера необходимо выполнить минимальный

набор настроек, соблюдая следующую последовательность:

1. включить тактирование;

2. запрограммировать тип вывода;

3. запрограммировать скорость работы вывода;

4. если вывод работает как выход, то установить его тип;

5. запрограммировать вывод с подтягивающим резистором или без.

Пример:

RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //Включение тактирования порта А (с

кнопкой)

GPIOA->MODER &=~ GPIO_MODER_MODER0_0; //PA0 - вход

GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0; //Максимальная частота

GPIOA->OTYPER &=~ GPIO_OTYPER_OT_0; //push-pull

GPIOA->PUPDR &=~ GPIO_PUPDR_PUPDR0_0; //Без подягивающего резистора

Page 22: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

22

8 Стандартная библиотека CMSIS

CMSIS (Cortex Microcontroller Software Interface Standard) - библиотека, созданная

компанией ARM на языке Си для микроконтроллеров, работающих на ядре Cortex. Она содержит

весь необходимый инструментарий для работы с периферией и другими модулями

микроконтроллера.

На рисунке 1 показано место CMSIS, которое она занимает в разработке прошивок.

Рисунок 1

Библиотека состоит из нескольких файлов. Структура CMSIS приведена на рисунке 2

Рисунок 2

core_m0.c – описание встроенных функций;

core_m0.h – доступ к периферии ядра;

stm32f0xx.h – заголовочный файл. Здесь объявлены указатели на структуры и сами

структуры для программирования регистров периферии и всех модулей микроконтроллера.

system_stm32f0xx.с – описание функций начальной инициализации переферии, в том

числе и функция инициализации системы тактирования;

system_stm32f0xx.h - объявление функций начальной инициализации переферии, в том

числе и функция инициализации системы тактирования;

startup_stm32f030.s – вектора прерываний;

Page 23: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

23

Рассмотрим более подробно файл stm32f0xx.h.

Например, рассмотрим объявление указателя на структуру модуля системы тактирования

Reset and clock control (RCC):

#define RCC ((RCC_TypeDef *) RCC_BASE)

В свою очередь RCC_TypeDef это сама структура, которая отображена на адресное

пространство по адресу RCC_BASE:

typedef struct

{

__IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */

__IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x04 */

__IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x08 */

__IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x0C */

__IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x10 */

__IO uint32_t AHBENR; /*!< RCC AHB peripheral clock register, Address offset: 0x14 */

__IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x18 */

__IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x1C */

__IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x20 */

__IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x24 */

__IO uint32_t AHBRSTR; /*!< RCC AHB peripheral reset register, Address offset: 0x28 */

__IO uint32_t CFGR2; /*!< RCC clock configuration register 2, Address offset: 0x2C */

__IO uint32_t CFGR3; /*!< RCC clock configuration register 3, Address offset: 0x30 */

__IO uint32_t CR2; /*!< RCC clock control register 2, Address offset: 0x34 */

} RCC_TypeDef;

В структуре объявлены 32-х битные поля, соответствующие регистрам периферийного

модуля.

Сам адрес RCC_BASE это тоже #define, разворачиваемый с помощью других #definе-oв:

#define RCC_BASE (AHBPERIPH_BASE + 0x00001000)

#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)

#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */

Что бы проверить согласованность библиотеки с документацией откройте справочное

руководство (Reference manual) "RM0091. STM32F0x1/STM32F0x2/STM32F0x8 advanced ARM-

based 32-bit MCUs ". В разделе 2.2.2 Memory map and register boundary addresses, в таблице мы

видим, что периферийный модуль Reset and clock control занимает кусок адресного пространства

с 0x40021000 до 0x400213FF. Собственно если вычислить дефайны: 0x40000000 + 0x00020000

+ 0x00001000 = 0x40021000.

Теперь о самих регистрах: к примеру возьмем регистр APB2ENR, отвечающий за

включение тактирования разных периферийных модулей на шине APB2 (раздел 7.4.7 того же

документа). Как видно адрес регистра "Address: 0x18". Под адресом регистра, тут понимается

смещение в байтах относительно начала базового адреса периферийного модуля, то есть

относительно 0x40021000. Фактический же адрес будет равен 0x40021000 + 0x18

= 0x40021018. Теперь взглянем на структуру RCC_TypeDef: как мы видим перед полем APB2ENR

есть еще 6 штук полей размером в 32бита (тип uint32_t). Каждое поле занимает 4 байта, а всего их

6. Следовательно смещение регистра APB2ENR от начала структуры равно 6 * 4 = 24 = 0х18, что

как раз таки и наблюдается в RM.

Каждый периферийный модуль, описанный в Reference Manual, соответствует указателю на

структуру в библиотеке CMSIS. Поля структуры отвечают за регистры этого периферийного

модуля.

Page 24: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

24

9 Отладочная плата STM32F0DISCOVERY

9.1 Описание конструкции отладочной платы

Для быстрого освоения семейства МК производители выпускают оценочные,

демонстрационные, отладочные платы. На этих платах установлен исследуемый МК и

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

функциональные модули (ФМ) МК. Обычно на оценочных и демонстрационных платах

установлена минимальная обвязка МК (питание и тактовый генератор, 1-2 кнопки, 1-2

сведодиода, разьем для подключения питания и программатора). Свободные выводы МК

выведены на разьёмные соединители, к которым пользователь может подключать различные

контроллеры, адаптеры, устройства. На отладочных платах установлен средний или

максимальные набор устройств, позволяющий использовать практически все интерфейсные ФМ

МК (USART, SPI, ADC, DAC, I2S, и др.) На отладочных платах часто установлены LCD

TouchScreen дисплеи, контроллеры Ethernet, RS232, RS485, CAD, USB интерфейсов.

Начать освоение программирования для микроконтроллеров STM32F051 удобно на

демонтрационной плате STM32F0DISCOVERY, т.к. на ней установлен:

- программатор ST-LINK-V2;

- микроконтроллер с разъемами для подключения периферийных устройств к выводам

микроконтроллера,

- два светодиода и две кнопки.

Вид сверху отладочной платы приведен на рисунке 1

На отладочной плате установлены следующие элементы, подключеннные к

микроконтроллеру STM32F051R8T6: четыре светодиода:

LD1 (красный) – питание 3 В;

LD2 (красный/зеленый) – соединение по mini – USB;

LD3 (красный) – подключен к выводу PC9;

LD4 (голубой) – подключен к выводу PC8;

две кнопки:

B1 – пользовательская- подключена к выводу РА8;

B2 – reset (подключена к выводу RESET).

На рисунке 3 пунктирной линией выделен встроенный программатор/отладчик ST-

LINK/V2. Для удешевления тактовый Х2 и часовой Х3 кварцевые резонаторы не запаяны. На

вход тактового генератора МК подаётся внешний сигнал 8МГц с программатора/отладчика

Питание платы осуществляется двумя способами: через mini - USB или при отсутствии USB

через внешний источник питания. Напряжение питание от внешнего источника 3 В и 5 В. Мы

будем использовать питание через USB, т.к. USB интерфейс в данной работе используется для

программирования и отладки

Все порты ввода/вывода микроконтроллера вынесены на внешние штыревые разъемы по

краям платы.

Page 25: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

25

Рисунок 3

Page 26: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

26

9.2 Структура отладочной платы

Структурная схема отладочной платы приведена на рисунке 4.

Рисунок 4

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

переферией (ST-LINK/V2, кнопки, светодиоды и разъемы). Микроконтроллер подключен к

отладчику через SWD – интерфейс.

Принципиальная электрическая схема приведена на рисунке 5.

Для упрощения на данной схеме внутрисхемный программатор/отладчик ST-LINK/V2

показан в виде некоего черного ящика, из-за большого числа электрических соединений.

Полная электрическая принципиальная схема приведена в [2]

Page 27: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

27

Рисунок 5

Так-как катод диода подключен к проводнику GND (общий, земля) а другой к выводу МК,

то для зажигания светодиодов на вывод порта необходимо подать плоложительное напряжение

больше открывания светодиодов (1,5-1,7В), Напряжение лог. 1 равно 3.3в при напряжении

питаниия МК 3.3В. Для ограничения тока последовательно со светодиодами включены резисторы

R30,R31. Таким образом обеспечив на выводах PC8,PC9 логическую 1 мы зажжём светодиоды, а

лог 0 на этих выводах погасит их.

Кнопка пользователя В1 подключает вывод РА0 через R28 к цепи питания VDD, те к лог 1.

При не нажатой кнопке через R29 на вывод РА0 подается напряжение 0, т.е лог. 0. Резистор R32 и

C22 обеспечивают защиту входа от помех.

Таким образом лог 1 на выводе (входе) РА0 соответствует нажатой кнопке, а лог 0

соответствует не нажатой кнопке.

Page 28: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

28

10 Среда программирования Keil μVision

10.1 Краткое описание

Для разработки новых прошивок выгодно использовать среду программирования Keil, так

как в неё входит компилятор, дизасемблер и имеется возможность отладки черед аппаратный

JTAG - отладчик. Также эта среда поддерживается разработчиком и для неё регулярно выходят

новые обновления.

Keil μVision поддерживает язык СИ, поэтому в лабораторных работах все прошивки будут

написаны на этом языке.

В данном цикле лабораторных работ применяется пятая версия Keil.

10.2 Создание проекта

Для каждого нового проекта рекомендуется создавать отдельную папку для хранения

исходных файлов и подключаемых библиотек.

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

Project->New µVision Project…

В открывшемся окне, изображенном на рисунке ,выберите папку проекта, введите название

проекта и нажмите «Сохранить»

Рисунок 6

Далее среда Keil предложит выбрать тип микроконтроллера, для которого будете

программировать. В окне, изображенном на рисунке, выберите микроконтроллер STM32F051R8 и

нажмите «ОК».

Page 29: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

29

Рисунок 7

Начиная с пятой версии Keil предлагает подключить библиотеки. Выбор библиотек

осуществляется в окне, изображенном на рисунке . В этом окне установите галочки CMSIS-

>CORE и Device->Startup и нажмите «ОК».

Рисунок 8

Page 30: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

30

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

названием, например, user. В этой папке создайте файл main.c, в котором будет записан текст

программы. Затем, в Keil создайте папку с тем же названием, дважды кликните по ней левой

кнопкой мыши и подключите файл main.c. Результат проведенных операций показан на рисунке 9

Рисунок 9

Далее необходимо изменить некоторые стандартные настройки проекта. Для этого

выполните следующие действия: Project->Options for Target ‘Target1’…, выберите вкладку Debug.

Во вкладке Debug выберите Use, ST-Link Debugger, как показано на рисунке 10

Рисунок 10

Перейдите во вкладку Utilities, нажмите кнопку «Setting», которая показана на рисунке 11

Page 31: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

31

Рисунок 11

В открывшемся окне, изображенном на рисунке, нажмите кнопку «Add»

Рисунок 12

В открывшемся окне, изображенном на рисунке, выберите первую строчку «STM32F0xx

64kB Flash», нажмите кнопку «Add».

Page 32: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

32

Рисунок 13

Далее нажимайте «ОК», закрывая все предыдущие окна, показанные на рисунках

10.3 Открытие готового проекта

Чтобы открыть готовый проект, выполните следующие действия:

Project->Open Project… , выберите проект (файл с расширением .uvprojx), нажмите кнопку

«Открыть».

Другой способ – из проводника двойной клик на файл проекта (файл с расширением

.uvprojx).

10.4 Компиляция проекта

Для компиляции проекта выполните следующие действия: Project->Build target или нажмите

кнопку F7.

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

удачной компиляции приведен на рисунке 14

Рисунок 14

Page 33: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

33

10.5 Загрузка прошивки в МК

Выбрать пункт текстового меню Flash->Download или нажать кнопку панели инстументов

«LOAD»

10.6 Отладка программы

Среда разработки Keil имеет возможность отлаживать прошивку через аппаратный JTAG -

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

Перед началом отладки откомпилируйте проект без ошибок, затем запишите его во flash –

память микроконтроллера. Для этого нужно выполнить следующие действия: Debug->Start/Stop

Debug Session или нажмите Ctrl+F5.

После этой операции Keil перейдет в окно отладки.

Для установки точки останова программы выполните: Debug-> Insert/Remove Breakpoint или

нажмите F9.

Для запуска прошивки под отладчиком выполните следующее: Debug->Run или нажмите

F5.

Чтобы остановить выполнения программы под отладчиком нажмите: Debug->Stop.

Для выполнения пошаговой отладки программы под отладчиком используйте: Debug->Step

Over или нажмите F10.

Page 34: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

34

11 Описание проекта LEDproject1

Прошивка написана на языке СИ. Для более голубоокого понимания кода рекомендуется

почитать дополнительную литературу.

Проект состоит из файла main.c и подключаемых к нему модулей. В проекте подключаются

следующие модули:

system_stm32f0xx.с – функции начальной инициализации, в том числе и функция

инициализации системы тактирования;

startup_stm32f030.s – вектора прерываний;

stm32f0xx.h –библиотека CMSIS, в которой описаны структуры для программирования

регистров микроконтроллера.

В файле main.c записан текст программы, в котором описана функция main(). С этой

функции начинается работа программы. В функции main() производится подключение

тактирования к портам А и С, затем устанавливаются настройки на конкретные выводы. После

этого программа переходит в основной цикл, который выполняется вечно, пока микроконтроллер

не перезагрузится. В этом цикле производится опрос кнопки B1 и выбор одного из режимов

моргания светодиодов. Нажатие на кнопку запоминается в переменной BUT. При нажатой

кнопке BUT=4 оба светодиода горят постоянно, при отпущенной (BUT=0) - оба светодиода

мигают синхронно.

При входе в main() в микроконтроллере уже сконфигурирована таблица прерываний и

система тактирования.

Page 35: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

35

12 Порядок выполнения лабораторной работы

1 Изучите теоретическую часть (разделы 1-7)

2 После изучения теоретической части перейдите к практической части.

3 Подключите отладочную плату к компьютеру через USB.

4 Скопируйте папку проекта LED_project1 на свой диск (Z:))

5 Откройте папку проекта и кликните на файл проекта LED_project.uvprojx, открыв таким

образом существующий проект в среде программирования Keil

6 . Изучите интерфейс, среды Кейл

7 Изучите текст программы проекта. Откомпилируйте его, загрузите проект в

микроконтроллер через Keil и запустите (см подраздел 9.4, 9.5). Убедитесь что новая прошивка

работает. Запишите в отчёт словесное описание алгорима работы программы.

8 Найти определение новых типов данных,имён, констант и структур:

uint8_t, GPIOC, MODER, GPIO_ODR_8, GPIO_ODR_9, IDR, GPIO_IDR_0, delay_ms, LED3_green,

LED4_blue, B1;

Записать для каждого имени: имя файла, где описана константа, её тип и разрядность и значение.

9 Измените проект LED_project так, чтобы режим мигания светодиодов соответствовал

выданному варианту, приведённому в таблице 1

Таблица 1- Варианты

Варианта В1 нажата В1 не нажата

1 Оба мигают синхронно Голубой потушен, зеленый мигает

2 Голубой горит, зеленый мигает Голубой потушен, зеленый мигает

3 Зеленый потушен, голубой мигает Оба мигают синхронно

4 Оба мигают асинхронно Голубой горит, зеленый мигает

5 Оба мигают синхронно Оба мигают асинхронно

6 Зеленый горит, голубой мигает Голубой потушен, зеленый мигает

7 Зеленый горит, голубой мигает Оба мигают асинхронно

8 Голубой горит, зеленый мигает Зеленый потушен, голубой мигает

9 Голубой потушен, зеленый мигает Оба мигают асинхронно

10 Оба мигают синхронно Голубой горит, зеленый мигает

11 Зеленый потушен, голубой мигает Оба мигают синхронно

12 Голубой потушен, зеленый мигает Зеленый горит, голубой мигает

14 Оба мигают асинхронно Зеленый горит, голубой мигает

15 Оба потушены Голубой горит, зеленый мигает

16 Оба горят постоянно Зеленый потушен, голубой мигает

исходный Оба горят постоянно Оба мигают синхронно

10 Скомпилируйте измененный проект, загрузите прошивку с помощью среды Keil и

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

преподавателю макет работающей вашей программой.

11 Защитите отчёт и ответте на контрольные вопросы преподавателя, получив оценнку.

12 Завершите работу OC Windows (выключить питание).

13 Отключить отладочную плату и преподавателю

Page 36: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

36

13 Содержание отчёта:

13.1 Описание работы программы до модификации

13.2 Изменённый проект в профиле пользователя с программой в соответствии с заданием

13.3 Демонстрация преподавателю работающей программы на отладочной плате в

соответствии со своим вариантом задания

Page 37: (НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙЙ ...frela-mk.narod.ru/olderfiles/1/lr1.pdf3.1 Объявление и определение функции Функция

37

14 Контрольные вопросы

14.1 Что такое препроцессор?

14.2 Что такое компилятор ?

14.3 Что такое компоновщик Link?

14.4 Назначение оператора #include

14.5 Какие основные арифметические операторы есть в языке СИ

14.6 Какие операторы организации циклов и условных переходов есть в СИ?

14.7 Какие операторы ввода вывода есть в языке СИ

14.8 Откуда компилятор «знает» марку МК и описание ядра МК?

14.9 Откуда компилятор «знает» архитектуру (набор ФМ, адреса и состав всех регистров

ФМ) МК для которого создаётся проект?

14.10 Откуда берутся функции ввода/вывода, которые вызываются из программы?

14.11 Особенности и назначение функции main()

14.12 Назначение модуля дискретного ввода/вывода GPIO?

14.13 Сколько разрядов в каждом порту GPIO у МК STM32F051?

14.14 Сколько портов GPIO имеется у МК STM32F051, в отладочной плате?

14.15 Возможности модуля дискретного ввода/вывода GPIO?

14.16 Какие регистры есть у модуля дискретного ввода/вывода GPIO?

14.17 Можно ли с помощью модуля дискретного ввода/вывода GPIO измерить (ввести)

уровень напряжения?

14.18 Сколько светодиодов и какие имеются на отладочной плате, используемой в лаб. работе?

14.19 Сколько кнопок и какие имеются на отладочной плате, используемой в лаб. работе?

14.20 С помощью каких аппаратных средств происходит передача файла прошивки в МК?

14.21 Какие интерфейсы в МК используются для «заливки» прошивки и отладки? Какой

интерфейс использовали вы в лаб. работе?

14.22 Что означает описатель типа void?

14.23 Сколько аргументов и какого типа надо передать функции BBB и что возвратит эта

функция, если она описана как «void BBB(int c, long d, char*mas);» ?

14.24 Что такое указатель?

14.25 Какие адресные операторы есть в СИ?

14.26 Почему GPIOC->ODR |= LED3_green|LED4_blue; зажигает светодиоды?

14.27 Почему GPIOC->ODR ^= LED3_green|LED4_blue; инвертирует свечение LED?

14.28 Равнозначны ли строки :

#define LED3_green GPIO_ODR_8

#define LED3_green GPIO_IDR_8

#define LED3_green 0x100

#define LED3_green 256