Главная страница
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
qrcode

Методичка_ТулГУ_1986ВЕ91Т. Основы программирования 32-разрядных микроконтроллеров 1986ВЕ91Т компании Миландр


НазваниеОсновы программирования 32-разрядных микроконтроллеров 1986ВЕ91Т компании Миландр
АнкорМетодичка ТулГУ 1986ВЕ91Т.pdf
Дата23.05.2017
Размер2.03 Mb.
Формат файлаpdf
Имя файлаMetodichka_TulGU_1986VE91T.pdf
оригинальный pdf просмотр
ТипЛабораторная работа
#21020
страница3 из 5
КаталогОбразовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
1   2   3   4   5
счет событий в одном направлении TIMER_CntMode_EvtFixedDir
счет событий с автоматическим реверсированием TIMER_CntMode_EvtChangeDir */
uint16_t TIMER_CounterDirection;
/*!< Определяет направление счета:
суммирующий счетчик TIMER_CntDir_Up
вычитающий счетчик TIMER_CntDir_Dn */
uint16_t TIMER_EventSource;
/*!< Определяет источник событий (тактирования) для таймера.
не определен (тактируется от тактовой частоты)
TIMER_EvSrc_None
Таймер 1 (переключается по обновлению таймера 1)
TIMER_EvSrc_TM1
Таймер 2 (переключается по
обновлению таймера 2)
TIMER_EvSrc_TM2
Таймер 3 (переключается по обновлению таймера 3)
TIMER_EvSrc_TM3
Событие в канале 1
TIMER_EvSrc_CH1
Событие в канале 2
TIMER_EvSrc_CH2
Событие в канале 3
TIMER_EvSrc_CH3
Событие в канале 4
TIMER_EvSrc_CH4
Событие на входе
ETR
TIMER_EvSrc_ETR */ uint16_t TIMER_FilterSampling;
/*!< Определяет частоту сэмплирования входных данных(FDTS).
Частота сэмплирования равна частоте таймера
TIMER_FDTS_TIMER_CLK_div_1
Частота сэмплирования равна частоте таймера/2
TIMER_FDTS_TIMER_CLK_div_2
Частота сэмплирования равна частоте таймера/3
TIMER_FDTS_TIMER_CLK_div_3
Частота сэмплирования равна частоте таймера/4
TIMER_FDTS_TIMER_CLK_div_4 */ uint16_t TIMER_ARR_UpdateMode; /*!<
Разрешение мгновенного обновления ARR
ARR будет перезаписан в момент записи в ARR
TIMER_ARR_Update_Immediately
ARR будет перезаписан при завершении счета CNT
TIMER_ARR_Update_On_CNT_Overflow
*/
uint16_t TIMER_ETR_FilterConf;/*!<
Определяет конфигурацию фильтра на входе
ETR
. Более
подробно можно посмотреть в файле MDR32F9Qx_timer.h определение @ref
IMER_FilterConfiguration */ uint16_t TIMER_ETR_Prescaler; /*!<
Определяет предделитель тактовой частоты на входе ETR
Более подробно можно посмотреть в файле MDR32F9Qx_timer.h определение @ref TIMER_ETR_Prescaler*/
uint16_t TIMER_ETR_Polarity; /*!<
Определяет полярность
ETR
сигнала.
определение в @ref TIMER_ETR_Polarity */
uint16_t TIMER_BRK_Polarity; /*!<
Определяет полярность BRK сигнала.
определение в @ref TIMER_BRK_Polarity */
} TIMER_CntInitTypeDef;
Прерывания или IRQ - это исключения, вызываемые периферийными устройствами или программными запросами. Все прерывания асинхронны по отношению к выполняемым инструкциям, то есть микропроцессор завершает текущую операцию и автоматически вызывает соответствующую процедуру обработки прерывания.
Задания:
Задание 1
Изменить интервал переключения светодиодов на 500мс.
Задание 2
Изменить процедуру обработки прерывания таким образом, чтобы интервалы переключение светодиодов для четных и нечетных светодиодов были различными.
24

Лабораторная работа № 4. Изучение цифро-аналогового преобразователя
Цель работы:
Изучение основных особенностей работы с цифро-аналоговым преобразователем
(ЦАП) при программировании для микроконтроллеров (МК) ARM. Разработка программы для генерации синусоиды.
Приборы и материалы:
1.
Отладочная плата MDR1986VE91T Rev 4.
2.
Программатор J-Link ARM.
3.
Блок питания 5В, 1.4А.
4.
ПК с установленной средой программирования Keil uVision.
5.
Осциллограф.
6.
Коаксиальный кабель для соединения двух BNC выходов.
Порядок работы:
1.
Собрать аппаратную часть по рекомендациям лабораторной работы № 2 2.
Открыть проект MDRProject в среде программирования Keil uVision.
3.
Подключить в менеджере Manage run-time environment к проекту библиотеки DAC,
PORT, RST_CLK
, необходимые для работы с ЦАП.
4.
Стереть имеющийся в файле main.c исходный код и добавить в начало заголовочные файлы, необходимые в данном проекте:
#include
#include
#include
#include
5.
Добавить функцию инициализации порта для ЦАП
PORT_InitTypeDef PORTEInit;
//Объявление структуры
void DACPortInit(){
PORT_StructInit(&PORTEInit); //
Загрузка умолчаний
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTE, ENABLE); //
Тактование
/* Настройка
DAC
1 (стр.11 спецификации) */
PORTEInit.PORT_Pin = PORT_Pin_9; //
Пин
9
PORTEInit.PORT_OE = PORT_OE_OUT; //
Порт
E
PORTEInit.PORT_MODE = PORT_MODE_ANALOG; //
Режим Аналоговый
PORT_Init(MDR_PORTE, &PORTEInit); //
Настройка порта
}
6.
Добавить функцию инициализации ЦАП void DACInit(){
RST_CLK_PCLKcmd(RST_CLK_PCLK_DAC, ENABLE);
//Тактование
DAC1_Init(DAC1_AVCC);
//Настройка
DAC
1 на работу с
AVCC
DAC1_Cmd(ENABLE); //
Активация
DAC1
}
Первая строчка функции DACInit() подает тактовый сигнал на периферийное устройство ЦАП. Функция DAC1_Init() позволяет настроить источник опорного напряжения для ЦАП1. Последняя строчка разрешает работу ЦАП1. Если предполагается использование внешнего источника, необходимо передать в функцию значение DACn_REF, где . В противном случае, для использования напряжения питания МК в качестве опорного, необходимо передать в функцию значение DACn_AVCC.
7.
Добавить в файл исходного кода функцию main().
25
float a; int main() {
RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK, ENABLE);
DACPortInit();
DACInit(); while(1){ for (a=0; a<360; a+=5)
DAC1_SetData((sinf(a*PI/180)*SCALE + SCALE)/2);
}
}
В приведенном выше фрагменте кода выполняется вызов функции DAC1_SetData() с аргументами, которые вычисляются по функции синуса от равномерно увеличивающегося аргумента. Так как синус находится в пределах от -1 до 1, его необходимо масштабировать в отрезок от 0 до максимального значения. Так как ЦАП 12-битный, максимальное значение равно 0xFFF (12 двоичных единиц). Таким образом, для перевода значений аргумента функции DAC1_SetData() в вольты, необходимо использовать формулу , где V
cc
является напряжением питания МК (3,3В). С учётом сказанного, необходимо добавить определения констант после подключения библиотек.
#define PI 3.14159265
#define MAX 2 /*Volt*/
#define SCALE (0x7FF * MAX) / 3.3 8.
Скомпилировать исходный код и загрузить его в МК
9.
Переключить перемычку DAC_OUT_SEL в положение EXT_CON (рисунок 5.1).
Рисунок 4.1 - Перемычка DAC_OUT_SEL
10.
Соединить BNC вывод DAC_OUT со входом осциллографа.
11.
Настроить вертикальный и горизонтальный масштаб осциллографа до получения синусоид, аналогичных изображенным на рисунке 4.2.
26

Рисунок 4.2 – Осциллограммы работы алгоритма
Обратите внимание на ступенчатую структуру синусоиды. Это происходит из-за того, что шаг изменения аргумента синуса 5 градусов, что слишком велико для достижения гладкости синусоиды.
Задания:
Задание 1
Вывести на осциллограф симметричную пилообразную функцию (рисунок 4.3).
Рисунок 4.3 – Симметричная пилообразная функция
Задание 2
Вывести на осциллограф параболу в диапазоне . В промежутках между периодичным выводами парабол, поддерживать значение напряжения на уровне 3В. Пример результирующей осциллограммы представлен на рисунке 4.4.
Рисунок 4.4 – Парабола
27

Приложение:
Полный текст программы
#include
#include
#include
#include
#define PI 3.14159265
#define MAX 3 /*Volt*/
#define SCALE (0xFFF * MAX) / 3.3
PORT_InitTypeDef PORTEInit; void DACPortInit(){
PORT_StructInit(&PORTEInit); //Load defaults
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTE, ENABLE);
PORTEInit.PORT_Pin = PORT_Pin_9;
PORTEInit.PORT_OE = PORT_OE_OUT;
PORTEInit.PORT_MODE = PORT_MODE_ANALOG;
PORT_Init(MDR_PORTE, &PORTEInit);
} void DACInit(){
RST_CLK_PCLKcmd(RST_CLK_PCLK_DAC, ENABLE);
DAC1_Init(DAC1_AVCC);
DAC1_Cmd(ENABLE);
} float a; int i; //4 task 2 int main() {
RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK, ENABLE);
DACPortInit();
DACInit(); while(1){
//Jumper to EXT_CON!!!
//* //Base part for (a=0; a<360; a+=5)
DAC1_SetData((sinf(a*PI/180)*SCALE + SCALE)/2);
//*/
/* //Task 1 for (a=0; a<0xFFF; a+=5) DAC1_SetData(a); for (a=0xFFF-1; a>1; a-=5) DAC1_SetData(a);
//*/
/* //Task 2 for (a=-0x7FF; a<0; a+=5)
DAC1_SetData(a*a/(0x7FF*0x7FF)*SCALE); for (a=0; a<0x7FF; a+=5) DAC1_SetData(a*a/(0x7FF*0x7FF)*SCALE);
DAC1_SetData(SCALE); for (i=0; i<0xFFFF; i++);
//*/
}
}
28

Лабораторная работа № 5. Изучение аналого-цифрового преобразователя
Цель работы:
Изучение основных особенностей работы с аналого-цифровым преобразователем
(АЦП) и работа со встроенным отладчиком при программировании для микроконтроллеров
(МК) ARM.
Приборы и материалы:
1.
Отладочная плата MDR1986VE91T Rev 4 2.
Программатор J-Link ARM
3.
Блок питания 5В, 1.4А
4.
ПК с установленной средой программирования Keil uVision
5.
Цифровой вольтметр
Порядок работы:
1.
Собрать аппаратную часть по рекомендациям лабораторной работы № 2 2.
Открыть проект MDRProject в среде программирования Keil uVision.
3.
Подключить в менеджере Manage Run-Time Environment к проекту библиотеки ADC,
PORT, RST_CLK необходимые для работы с АЦП.
4.
Очистить содержимое файла main.c и добавить ссылки на подключенные библиотеки:
#include
#include
#include
#include
5. Добавить в файл исходного кода функцию ADCInit(), в которой произвести инициализацию седьмого канала АЦП1 (на отладочной плате к этому каналу подключено переменное сопротивление).
ADC_InitTypeDef ADC;
//Общая инициализацинная структура подсистемы АЦП
ADCx_InitTypeDef ADC1;
//Инициализацинная структура для АЦП1
void ADCInit(){
//Подача тактования на процессор и АЦП
RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK | RST_CLK_PCLK_ADC, ENABLE);
ADC_StructInit(&ADC);
//Заполнение структуры умолч. значениями
ADC_Init(&ADC); //
Инициализация
ADCx_StructInit(&ADC1);
ADC1.ADC_ChannelNumber = ADC_CH_ADC7; //
Выбор седьмого канала
ADC1_Init(&ADC1);
//Инициализация прерываний АЦП
NVIC_EnableIRQ(ADC_IRQn);
NVIC_SetPriority(ADC_IRQn, 0);
//Включение прерываний по окончанию преобразования
ADC1_ITConfig(ADCx_IT_END_OF_CONVERSION, ENABLE);
//Включение АЦП1
ADC1_Cmd(ENABLE);
}
6. Добавить в файл исходного кода обработчик прерывания по окончанию аналого-цифрового преобразования.
bool conInProgress;
//Флаг «в процессе преобразования»
unsigned int rawResult; //
Необработанный результат
unsigned char channel; //
Номер канала
float result; //
Результат в вольтах
void ADC_IRQHandler() { //
Обработчик прерываний АЦП
//Проверка что причина прерывания соответствует концу преобразования
if(ADC_GetITStatus(ADC1_IT_END_OF_CONVERSION)){ rawResult = ADC1_GetResult();
//Получение результата
channel = (rawResult & 0x1F0000) >> 16;
//Сохранение номера канала
rawResult &= 0xFFF;
//Удаление номера канала из результата
29

//Преобразование результата в вольты
result = (float)rawResult / (float)SCALE; conInProgress = false;
//Очистка флага «в процессе преобр
-
я»
NVIC_ClearPendingIRQ(ADC_IRQn);
//Очистка флага прерывания
}
}
Как видно из кода, результат содержит в себе не только преобразованное значение напряжения на канале, но и номер этого канала, который нужно убрать из результата. На странице 323 спецификации имеется таблица 301 (рисунок 5.1), иллюстрирующая это.
Рисунок 5.1 – Структура регистра с результатом преобразования
С помощью встроенного в Windows калькулятора в режиме программиста выясняем, что битовая маска, обнуляющая все биты, кроме блока с 20 по 16 включительно, имеет вид, отображенный в шестнадцатеричном формате на рисунке 5.2 (0x1F0000).
Рисунок 5.2 – Битовая маска для вычисления номера канала
Конъюнктивно применяя данную битовую маску к результату и смещая его на 16 разрядов вправо (для избавления от 16 значимых нулей в конце), выделяем номер канала, который теперь можно сохранить в отдельную переменную. Для выделения результата преобразования применим битовую маску 0xFFF (12 единиц в двоичном представлении).
Далее необходимо преобразовать полученный результат из цифрового кода, пропорционального напряжению, в вольты. Для этого результат необходимо поделить на коэффициент SCALE, значение которого предстоит определить экспериментальным путём.
7. Последним штрихом является написание функции main(), с которой начнётся исполнение программы. int i;
//Счетчик для задержки циклом
int main() {
ADCInit(); while(1){ for(i = 0xFFFF; i > 0; i--); //
Задержка циклом
(
плохой вариант
) if (!conInProgress){
//Не выполняется ли преобразование?
ADC1_Start();
//Начать преобразование!
conInProgress = true;
//Преобразование выполняется
}
}
}
30

Таким образом, в главном цикле через определенный промежуток времени запускается аналого-цифровое преобразование на седьмом канале первого АЦП. По окончании преобразования, вызывается соответствующий обработчик прерывания, в котором результат преобразования заносится в переменную result. Чтобы данный код заработал, не хватает константы SCALE, и чтобы найти такое ее значение, с помощью которого можно получить результат в вольтах, зададим ее равной единице.
#define SCALE 1 8. Подать питание на плату и загрузить программу в микроконтроллер по рекомендациям лабораторной работы №2 9. Поставить перемычку ADC_INP_SEL в положение TRIM для подключения переменного сопротивления в качестве источника сигнала для АЦП (рисунок 5.3).
Рисунок 5.3 – Блок аналогового входа
10. Подключить плюсовой вход вольтметра к среднему контакту перемычки (можно замкнуть перемычку в положение TRIM с помощью щупа вольтметра)
11. Подключить минусовой контакт вольтметра к любому общему проводу отладочной платы
(удобно использовать любое крепёжное отверстие по краям платы)
Рисунок 5.4 – Крепежные отверстия
31

12. Запустить сеанс отладки в программе Keil uVision (Ctrl+F5 или кнопка на панели инструментов)
13. Добавить переменную result в Watch 1 (правый клик по переменной в коде | Add ‘result’
to… | Watch 1
) и запустить код на исполнение (F5 или кнопка на панели инструментов)
14. Вращать вал переменного сопротивления (TRIM на рисунке 6.4), пока напряжение на
АЦП не станет равным 2 вольта.
15. Считать из окна Watch 1 отладчика значение переменной result при известном напряжении на АЦП (рисунок 5.5).
16. Поделить полученное цифровое значение на напряжение, которому оно соответствует.
18. Остановить отладку.
17. Полученный коэффициент вписать в код в качестве константы SCALE.
19. Загрузить код с новым коэффициентом SCALE в МК.
20. Запустить сеанс отладки и убедиться, что переменная result отображает значение, совпадающее с показаниями вольтметра.
Рисунок 5.5 – Окно Keil uVision в процессе отладки
В окне среды Keil uVision на рисунке 5.5 также открыто окно регистров MDR_ADC.
Данное окно можно открыть в меню System Viewer Windows ( ) на панели инструментов. При анализе содержимого регистра ADC1_RESULT, можно подтвердить правильность его описания (рисунок 6.2) и даже понять его структуру при отсутствии описания. Отладка является мощнейшим инструментом разработки и помогает увидеть любые ошибки времени выполнения легко и наглядно.
Задание:
Используя знания, полученные в лабораторной работе № 5, создать цифровой преобразователь сигнала. При входном уровне сигнала (от переменного сопротивления) от 0 до 1 вольта, он должен выдавать сигнал от 2 до 3 вольт аналогичной формы.
Приложение:
32

#include
#include
#include
#include
#define delay(T) for(i = T; i > 0; i--) int i;
#define SCALE 1252.5
ADC_InitTypeDef ADC;
ADCx_InitTypeDef ADC1; void ADCInit(){
RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK | RST_CLK_PCLK_ADC, ENABLE);
ADC_StructInit(&ADC);
ADC_Init(&ADC);
ADCx_StructInit(&ADC1);
ADC1.ADC_ChannelNumber = ADC_CH_ADC7; //Switch to TRIM!!!
ADC1_Init(&ADC1);
//Int
NVIC_EnableIRQ(ADC_IRQn);
NVIC_SetPriority(ADC_IRQn, 0);
ADC1_ITConfig(ADCx_IT_END_OF_CONVERSION, ENABLE);
ADC1_Cmd(ENABLE);
} bool conInProgress; unsigned int rawResult; unsigned char channel; float result; void ADC_IRQHandler() { if(ADC_GetITStatus(ADC1_IT_END_OF_CONVERSION)){ rawResult = ADC1_GetResult(); channel = (rawResult & 0x1F0000) >> 16; rawResult &= 0x00FFF; result = (float)rawResult / (float)SCALE; conInProgress = false;
NVIC_ClearPendingIRQ(ADC_IRQn);
}
} int main() {
ADCInit(); while(1){ delay(0xFFFF); if (!conInProgress){
ADC1_Start(); conInProgress = true;
}
}
}
33
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей

Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей