Главная страница
qrcode

А.В.Пуговкин И.А.Куан Н.К. Ахметов А.В. Бойченко. Методическое пособие по программированию микроконтроллеров. ТУСУР. Методическое пособие по программированию микроконтроллеров Учебно-методическое пособие


НазваниеМетодическое пособие по программированию микроконтроллеров Учебно-методическое пособие
АнкорА.В.Пуговкин И.А.Куан Н.К. Ахметов А.В. Бойченко. Методическое пособие по программированию микроконтроллеров. ТУСУР.pdf
Дата07.06.2019
Размер2.56 Mb.
Формат файлаpdf
Имя файлаA_V_Pugovkin_I_A_Kuan_N_K_Akhmetov_A_V_Boychenko_Metodicheskoe_p
оригинальный pdf просмотр
ТипМетодическое пособие
#52982
страница2 из 3
Каталог
1   2   3
5.
Лабораторная работа №1. Повторение языка Си
Цель работы:
Повторение основ программирования на языке Си. Разработка первых программ.
Теоретические сведения
Компиляция
Си (
англ.
C) — это язык высокого уровня.
Программа, написанная на языке Си, является текстовым файлом с расширением «.с». Такая программа преобразуется с помощью компиляции в программу низкого уровня, состоящую из машинных кодов.
Компиляция состоит из следующих этапов:
1. Препроцессирование. Препроцессор добавляет к исходному файлу
*.cили*.cppзаголовочные файлы *.h, *.hppиконстанты. Получается единый текстовый файл.
2. Трансляция. Единый текстовый файл передается транслятору. На выходе транслятора возникает файл с ассемблерным текстом.
3. Ассемблирование.Ассемблерный текст передаётся программе, которая преобразует его в объектный файл*.obj.
4. Линковка.Линковщик объединяет все поданные ему объектные файлы с библиотечными файлами и формирует один большой файл.
Заголовочные файлы
Структура сокращенной программы на языке Си может быть такой:
#include "stdafx.h"
//подключение заголовочных файлов intmain()
//заголовок основной программы
{
//тело основной программы
}
Функция main– главная функция, с которой начинается выполнение программы. Директива #includeподключает библиотеки.
37
Типы данных
В языке С имеется следующий набор стандартных типов данных:

целыечисла (int, long, unsigned int, unsigned long, bool);

вещественные числа с плавающей точкой (float, double, longdouble);

указатели;

символьные переменные (char);

типvoid.
Диапазоны значений стандартных типов данных приведены в таблице ниже.
Таблица 5.1 – Типы переменных
Тип
Диапозон значений
Размер(байт)
Bool true и false
1
Char
–128 .. 127 1 unsigned char
0 .. 255 1 int
–32 768 .. 32 767 2 unsigned int
0 .. 65 535 2 long
–2 147 483 648 .. 2 147 483 647 4 unsigned long
0 .. 4 294 967 295 4 float
3.4e–38 .. 3.4e+38 4 double
1.7e–308 .. 1.7e+308 8 long double
3.4e–4932 .. 3.4e+4932 10
38
Операторы
Операторы предназначены для осуществления действий и для управления ходом выполнения программ.
Условный оператор:
if (условие) (оператор1).
Более сложная форма условного оператора содержит ключевое слово else
(иначе): if
(условие) (оператор1); else
(альтернативный оператор).
Оператор выполнения цикла
с предусловием (пока): while
(условие) [тело цикла].
Оператор выполнения цикла
с постусловием (выполняется, пока): do
[тело цикла] while
(условие).
Оператор выполнения цикла, содержащий слово for
, заголовок и тело цикла: for
(начальные значения; условие; оператор) [тело цикла].
Цикл for используется тогда, когда количество повторений цикла заранее известно или может быть вычислено.
Оператор безусловного перехода:
goto
[метка].
Оператор выхода из цикла и перехода к следующему оператору: break.
Оператор
завершения текущего шага цикла и перехода к новому шагу (не выходя из цикла):
сontinue.
Оператор возврата из функции:
return.
39
Указатели
Указатель — это переменная, содержащая адрес другой переменной.
Применение указателя определяется следующими присвоениями: рх = &х;
//присвоение переменной рх адреса переменной х.
у = *рх;
//присвоение переменной у величины,адрес которой содержится в переменной рх.
Подпрограммы
Подпрограмма (процедура, функция) – это именованная часть программы, к которой можно обращаться из других частей программы.
Функция имеет следующее оформление: имя функции, аргументы функции и тело функции в фигурных скобках. Перед именами функции и именами аргументов ставятся их типы.
Краткий пример функции vyxod может быть таким: floatvyxod (int n, floadvhod) { тело функции }.
Массивы
Массив - это конечная совокупность данных одного типа. Способы представления массивов поясним конкретными примерами: int x[10];
//массив, состоящий из 10 целых чисел
(вектор) int a[2][5];
//двумерный массив или матрица, состоящая из 2 строк и 5 столбцов
В языке Си понятие массива тесно связано с понятием указателя. Имя массива само является указателем на первый элемент массива. Доступ к членам массива можно получать как через имя массива и индекс, так и через указатель на элемент массива и индекс.
Структура
(
struct
)
Структура - это совокупность данных одинакового или различного типа, обозначенная одним именем. Данные еще называют элементами.
40
В качестве примера структуры можно взять учетную карточку одного сотрудника предприятия. Элементами такой структуры являются: табельный номер сотрудника, его имя, пол, дата рождения, адрес. Некоторые из этих элементов сами могут оказаться структурами. Например, имя, дата рождения, адрес состоят из несколько частей – элементов другого уровня других структур.
Часто объявляютвначале шаблон структуры, который затем используют для создания структур. Для примера с учетной карточкой шаблон структуры может быть таким: struct аnketa
{ inttab_nom;// табельный номер charfio [30]; //
фамилия, имя, отчество charpol [3]; //
пол char data ;//
датарождения charadres;
};
Ключевое слово struct сообщает компилятору об объявлении шаблона структурыcименем аnketa. Для того, чтобы создать структуру, например, с именем аnketa_1,следует написать structаnketaаnketa_1;
Созданную структуру с именем аnketa_1 называют структурной переменной или просто переменной. Когда объявлена структурная переменная, компилятор выделяет необходимый участок памяти для размещения всех ее элементов. При объявлении структуры можно одновременно объявить одну или несколько переменных, например, structanketaаnketa_1, аnketa_2, аnketa_3;
По-другому, следом за закрывающей правой фигурной скобкой, заканчивающей список элементов, может следовать список структурных переменных: struct аnketa
{…} аnketa_1, аnketa_2;
41
Доступ к структурной переменной осуществляется с помощью оператора «точка»: имя_структуры.имя_элемента;
Логическиеоператоры сдвига
Оператор сдвига влево: «<<». Когда оператор сдвига влево ( << ) выполняется над некоторым значением, все биты, составляющие это значение, сдвигаются влево. Связанное с этим оператором число показывает количество бит, на которое значение должно переместиться. Биты, которые сдвигаются со старшего разряда, считаются потерянными, а на место младших битов всегда помещаются нули.
Оператор сдвига вправо: «>>». Операция сдвига вправо ( >> ) сдвигает разряды левого операнда вправо на количество позиций, указываемое правым операндом. Выходящие за правую границу разряды теряются. Для типов данных без знака (unsigned) освобождаемые слева позиции заполняются нулями. Для знаковых типов данных результат зависит от используемой системы. Освобождаемые позиции могут заполняться нулями либо копиями знакового (первого слева) разряда.
Структура программы
Так как при программировании микроконтроллера мы будем часто прибегать к структурам и библиотекам, то в качестве повторения напишем программу, в которой будем заполнять и выводить на экран элемент типа структура. При этом саму структуру опишем в отдельном файле.
В программе опишем структуру sklad, которая будет хранить данные о хранящихся на складе овощах.
Проект будет состоять из трёх файлов:
Main.c – содержит функцию main().
Sklady.h – содержит описание структуры и заголовки функций для работы с ней.
42
Sklady.c – содержит описание функций для работы со структурой.
Файл «sklady.h»
Структуры описываются следующим образом: structsklad
{ int carrot; int potato; int tomato; char * adress;
};
Гдеsklad – имяструктуры. В фигурных скобках перечислены члены структуры. Переменные типа int будут хранить количество овощей на складе.
Указатель на char по факту является строкой и будет хранить адрес склада.
Чтобы более удобно выводить хранящиеся в структуре данные, напишем для этого специальную функцию со следующим заголовком: voidprintsklad(structsklad * sample);
В качестве аргумента функция берет указатель на элемент объявленной нами структуры.
Файл «Sklad.c»
В начале этого файла необходимо подключить файлы «sklady.h» и
«stdio.h». Последний позволяет использовать функцию printf, которая будет выводить значения переменных в консоль. Для работы вывода данных необходимо в настройках IAR указать, что вывод сообщений от printf передается в окно TerminalIO через библиотеку семихостинга (диалог Options проекта
->GeneralOptions
->LibraryConfiguration
->Librarylowlevelinterfaceimplementation ->stdout/stderr ->Viasemihosting).
В этом файле опишем объявленную ранее функцию printsklad(), которая будет выводить адрес склада и количество килограмм каждого овоща на складе: voidprintsklad(structsklad * sample)
{
43 printf("На складе по адресу
%s содержится:\n",(*sample).adress); printf("Морковки: %d кг\n",(*sample).carrot); printf("Картофеля: %d кг\n",(*sample).potato); printf("Помидоров: %d кг\n",(*sample).tomato);
}
Функция printf работает по следующему принципу: текстовые сообщения передаются в кавычках (" "), далее, через запятую, идёт имя переменной, которая будет выводиться в данном сообщении. Сообщение пишется целиком, в место, где должно быть значение переменной вписывается специальный спецификатор (для целых чисел - %d, для символьных строк -
%s).
Вывести на экран значения всех полей структуры нельзя, возможно лишь получать значения определённых членов структуры с помощью оператора
«точка», например “sample.tomato”, где sample – имя элемента структуры, а tomato – имя переменной-члена структуры.
Так как функция принимает в качестве аргумента адрес структуры, при обращении к ней необходимо использовать оператор “*”, чтобы получить значение по адресу.
Файл «main.c»
В данном файле объявим элемент описанной ранее структуры: structskladsLen;
Заполним значения полей структуры: sLen.carrot=200; sLen.potato=100; sLen.tomato=50; sLen.adress="Lenina";
И передадим её адрес в описанную ранее функцию с помощью оператора “&”: printsklad(&sLen);
44
Ход работы
Задание на лабораторную работу
1. Ознакомиться с теоретическими сведениями.
2.Написать, отладить и запустить программу.
3. Выполнить индивидуальное задание.
Текст программы
Файл «sklady.h»: structsklad
{ int number; int carrot; int potato; int tomato; char * adress;
}; voidprintsklad(structsklad * sample);
Файл «sklady.c»:
#include "sklady.h"
#include "stdio.h" voidprintsklad(structsklad * sample)
{ printf("На складе по адресу %s содержится:\n",(*sample).adress); printf("Морковки: %d кг\n",(*sample).carrot); printf("Картофеля: %d кг\n",(*sample).potato); printf("Помидоров: %d кг\n",(*sample).tomato);
}
Файл «main.c»:
#include "sklady.h" int main()
45
{ structskladsLen; sLen.carrot=200; sLen.potato=100; sLen.tomato=50; sLen.adress="Lenina"; printsklad(&sLen); return 0;
}
Индивидуальные задания
1.
Перевоз овощей с двух складов на третий.
Дописать к имеющейся программе функцию, которая будет возвращать элемент структуры, содержащий сумму имеющихся овощей на двух складах, передаваемых функции в качестве аргументов.
2.
Количество имеющегося картофеля.
В имеющейся программе объявить массив из 5 складов и посчитать количество имеющегося на них картофеля.
3.
Сортировка овощей.
Дописать к имеющейся программе функцию, которой будут передаваться адреса 3-х элементов структуры. В результате на первом складе должна быть только сумма морковки с трёх складов, на втором – картофеля, на третьем – помидоров.
46
6.
Лабораторная
работа
№2.
Портыввода/вывода(General-
purposeinput/output, GPIO).
Цель работы:Изучить работы портов микроконтроллера на примере программы мигания светодиодами.
Теоретические сведения
1986BE92x_StdPeriph_Driver — стандартная библиотека ввода-вывода, созданная компанией Фитон24 на языке Си для микроконтроллеров семейства
Cortex-M производства Миландр. Содержит функции, структуры и макросы для облегчения работы с периферийными блоками микроконтроллеров. Библиотека документирована, включает примеры по каждому периферийному устройству, полностью поддерживает
CMSIS
(CortexMicrocontrollerSoftwareInterfaceStandard) и предоставляется компанией
Миландр бесплатно.
CMSIS — стандартная библиотека для всех микроконтроллеров семейства Cortex-М.
Для работы с портами ввода/вывода используютсябиблиотека
MDR32F9Qx_port.h, которая описывает следующие регистры:
– MDR_PORTA
– MDR_PORTB
– MDR_PORTC
– MDR_PORTD
– MDR_PORTE
– MDR_PORTF
Исходя из спецификации к отладочной плате светодиоды находятся на порте С (Таблица 2.1).
Кнопка UP находитсяна порте В, а кнопка DOWNна порте Е (Рисунок
6.1).
47
Рисунок 6.1 – Схема положения светодиодов и кнопок
В начале необходимо включить тактирование используемых портов (т.к на регистры портов должна поступить тактовая частота, иначе проект не будет работать) в данном случаеB,C,E.
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);
Затем необходимо настроить порты ввода-вывода(см. спецификация1986ВЕ9X.pdf, стр.177,таблица 120)
Рисунок 6.2 – Функции портов
48
Исходя из таблицы, мы видим, что у портов микроконтроллера есть аналоговая и цифровая функция.
Аналоговая отвечает за блоки АЦП, ЦАП.
Цифровая функция порта разделена на несколько видов. Основная, альтернативная и переопределенная отвечают за взаимодействие внутренних периферийных компонентов с выводами МК.
Для данной лабораторной работынеобходима колонка таблицы, которая отвечает за использование портов как «Порт IO»
Микроконтроллер имеет 6 портов ввода/вывода. Порты 16-разрядные и их выводы мультиплексируются между различными функциональными блоками, управление для каждого вывода отдельное. Для того, чтобы выводы порта перешли под управление того или иного периферийного блока, необходимо задать для нужных выводов выполняемую функцию и настройки.
Таблица 6.1 - Описание регистров портов ввода-вывода
Название
Описание
MDR_PORTA
Порт А
MDR_PORTB
Порт B
MDR_PORTC
Порт C
MDR_PORTD
Порт D
MDR_PORTE
Порт E
MDR_PORTF
Порт F
RXTX[15:0]
MDR_PORTx->RXTX
Данные порта
OE[15:0]
MDR_PORTx->OE
Направление порта
FUNC[31:0]
MDR_PORTx->FUNC
Режим работы порта
ANALOG[15:0] MDR_PORTx->ANALOG
Аналоговый режим работы порта
PULL[31:0]
MDR_PORTx->PULL
Подтяжка порта
PD[31:0]
MDR_PORTx->PD
Режим работы выходного драйвера
49
Название
Описание
PWR[31:0]
MDR_PORTx->PWR
Режим мощности передатчика
GFEN[31:0]
MDR_PORTx->GFEN
Режим работы входного фильтра
PORT_Pin – выбор выводов для инициализации
РегистрOE - определяет режим работы порта (направление передачи
данных):

ввод PORT_OE_IN (0);

вывод PORT_OE_OUT (1)
Регистр FUNC - определяет режим работы вывода порта:

Порт PORT_FUNC_PORT (0);

Основная функция PORT_FUNC_MAIN (1);

Альтернативная функция PORT_FUNC_ALTER (2);

Переопределенная функция PORT_FUNC_OVERRID (3)
Регистр MODE - определяет режим работы контроллера:

аналоговый PORT_MODE_ANALOG(0);

цифровой PORT_MODE_DIGITAL(1)
Регистр SPEED- определяет скорость работы порта:

зарезервировано (передатчик отключен) PORT_OUTPUT_OFF
(0);

медленный фронт (порядка 100 нс) PORT_SPEED_SLOW (1);

быстрый фронт (порядка 20 нс) PORT_SPEED_FAST (2);

максимально быстрый фронт
(порядка
10 нс)
PORT_SPEED_MAXFAST (3);
Для инициализации используется структура типа PORT_InitTypeDef, поэтому необходимо объявить переменную данного типа: staticPORT_InitTypeDefPortInit;
//Объявляемструктурудляконфигурациипорта
50
Функция настройки порта будет выглядеть следующим образом: voidLedPinGfg (void)
{
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);
//Включаем тактирование порта С
PortInit.PORT_Pin = PORT_Pin_1;
//Устанавливаем номер вывода порта
PortInit.PORT_OE = PORT_OE_OUT;
//Направление передачи данных - на выход
PortInit.PORT_FUNC= PORT_FUNC_PORT;
//Режимработы - порт
PortInit.PORT_MODE = PORT_MODE_DIGITAL;
//Режимработы - цифровой
PortInit.PORT_SPEED = PORT_SPEED_SLOW;
//Скоростьработы медленныйрежим
PORT_Init(PORTC, &PortInit);
// ПередаемструктурупортуС
}
Функции состояния вывода:
PORT_SetBits()- установить на передаваемом в аргументе выводе единицу.
PORT_ResetBits() - установить на передаваемом в аргументе выводе ноль.
Ход работы
Структура программы:

Включаем тактирование периферии

Настраиваем порты ввода-вывода

Начинаем выполнять основной код программы
51
Исходный код программы:
#include "1986be9x_config.h"
#include "1986BE9x.h"
#include "1986BE9x_port.h"
#include "1986BE9x_rst_clk.h"
// Объявляем структуру для конфигурации порта staticPORT_InitTypeDefPortInit; voidLedPinGfg (void)
{
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE
);
//Включаем тактирование порта С
PortInit.PORT_Pin = PORT_Pin_1;
//Устанавливаем номер вывода порта
PortInit.PORT_OE = PORT_OE_OUT;
//Устанавливаем направление передачи данных - на выход
PortInit.PORT_FUNC= PORT_FUNC_PORT;
//Режимработы - порт
PortInit.PORT_MODE= PORT_MODE_DIGITAL;
//Режимработы – цифровой
PortInit.PORT_SPEED = PORT_SPEED_SLOW;
//Скоростьработы медленныйрежим
PORT_Init(PORTC, &PortInit);
//ПередаемструктурупортуС
} intmain (void)
{
LedPinGfg ();
// инициализация порта С
while (1) {
PORT_SetBits(PORTC, PORT_Pin_1);
//включениесветодиода for (uint32_t i=0; i<1000000; i++) {}
//задержка
PORT_ResetBits(PORTC, PORT_Pin_1);
//отключениесветодиода for (uint32_t i=0; i<1000000; i++) {}
}
}
1   2   3

перейти в каталог файлов


связь с админом