МК. Встроенная периферия выполнили студенты группы Принял ассистент Таганрог 2021 Цель работы
Скачать 0.88 Mb.
|
Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования Институт компьютерных технологий и информационной безопасности Кафедра математического обеспечения и применения электронно-вычислительных машин ОТЧЁТ о выполнении лабораторной работы №2 по дисциплине «Введение в инженерную деятельность» ВСТРОЕННАЯ ПЕРИФЕРИЯ Выполнили: студенты группы Принял: ассистент Таганрог 2021 Цель работы Целью работы является изучение всторенной базовой периферии МК, её режимов работы и параметров функционирования. Задачами работы являются: Изучение аналогово-цифрового преобразователя и считывание показаний аналоговых устройств; Настройка и управление цифро-аналоговым преобразователем, генерация аналоговых сигналов; Использование аппаратных таймеров для генерация широтно-импульсной модуляции; Управление системой прерывания микроконтроллера и обработка внешних событий. Ход работы Аналогово-цифровой преобразователь Для получения сигналов из аналоговых устройств используется встроенный в контроллер аналого-цифровой преобразователь. Активируем АЦП и подготавливаем контакты (таблица 1) для получения сигнала: Рисунок 1 – Настройка аналогово-цифрового преобразователя Циклически считываем данные с потенциометров (POT1 и POT2): Рисунок 2 - Считывание данных потенциометра Также считываем данные джойстика (Джойстик X и Джойстик Y): Рисунок 3 - Считывание данных джойстика Для считывания текущих значений и получения мгновенных показаний переменных при пошаговой отладке программы используются окна «Watch»
Таблица 1 – линии АЦП. Таймеры и генератор ШИМ Микроконтроллер содержит таймер для точного отсчета интервалов времени. Они используются для генерации сигналов, вызовов прерываний, синхронизации периферии и т. д. Для удобства создадим функцию выбора альтернативного режима: Рисунок 4 - Функция альтернативного режима Альтернативный режим позволяет передать управление контактом микроконтроллера периферийному устройству, в нашем случае таймер TIM4 получает контроль над PD12, PD13 и PD14: Рисунок 5 - Подготовка контактов контроллера Настраиваем таймер: Рисунок 6 - Настройка таймера Циклически задаем скважность ШИМ, чтобы RGB светодиод на плате менял свой цвет каждые полсекунды: Рисунок 7 - Скважность ШИМ Система прерываний Прерывания в микроконтроллере служат для обработки внутренних и внешних событий. Создадим прерывание при нажатии кнопки, задействовав контакт PE6 (Не забываем выбрать правильный номер прерывания, соответствующий номеру линии): Рисунок 8 – Настройка прерывания Создаем функцию для обработки прерываний: Рисунок 9 - Функция обработки прерываний Создаем функцию для выбора порта и канала: Рисунок 10 - Функция выбора порта и канала Теперь при появлении или падении напряжения на PE6 будет вызываться прерывание и исполнятся код в функции «EXTI9_5_IRQHandler». Для обработки прерываний на линии 6 используется название функции и номер прерывания из таблицы 2:
Таблица 2 – линии внешних прерываний Разработка программы для управления RGB светодиодом Ниже приведён разработанный в рамках данной работы программный код. #include "stm32f4xx.h" int data; bool isChanged = false; enum PORT { A, B, C, D, E, F, G, H, I }; // Перечисление доступных портов extern "C" void EXTI9_5_IRQHandler() // Название функции для EXTI0 { EXTI->PR = 1 << 6; // Снять бит активности прерывания (прерывание 6 обработано) if (GPIOE->IDR & (1 << 6)) // Прочесть значение входящего сигнала в PE6 { isChanged = true; } else { isChanged = false; } } void SetEXTI(PORT Port, int Channel, bool Rise, bool Fall) { SYSCFG->EXTICR[Channel / 4] &= (15 << (4 * (Channel % 4))); // Сбросить порт SYSCFG->EXTICR[Channel / 4] |= Port << (4 * (Channel % 4)); // Выбрать порт EXTI->IMR |= 1 << Channel; // Прерывание выбрано if (Rise) EXTI->RTSR |= 1 << Channel; // Ловить повышение напряжения else EXTI->RTSR &= (1 << Channel); // Не ловить повышение напряжения if (Fall) EXTI->FTSR |= 1 << Channel; // Ловить падение напряжения else EXTI->FTSR &= (1 << Channel); // Не ловить падение напряжения } void SetAltFunc(GPIO_TypeDef* Port, int Channel, int AF) { Port->MODER &= (3 << (2 * Channel)); // Сброс режима Port->MODER |= 2 << (2 * Channel); // Установка альт. Режима if (Channel < 8) // Выбор регистра зависит от номера контакта { Port->AFR[0] &= (15 << 4 * Channel); // Сброс альт. функции Port->AFR[0] |= AF << (4 * Channel); // Установка альт. функции } else { Port->AFR[1] &= (15 << 4 * (Channel - 8)); // Сброс альт. функции Port->AFR[1] |= AF << (4 * (Channel - 8)); // Установка альт. функции } } int main() { RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // ADC задействован RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // Порт C задействован GPIOC->MODER &= GPIO_MODER_MODER3; // Сброс режима для PC3 GPIOC->MODER |= GPIO_MODER_MODER3; // Аналоговый вход для PC3 ADC1->CR2 = ADC_CR2_ADON; // ADC активен RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // Таймер 4 задействован (APB1 x2 = 84МГц) RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Порт D задействован SetAltFunc(GPIOD, 12, 2); // Установка альт. режима AF2 для TIM4 CH1 (PD12) SetAltFunc(GPIOD, 13, 2); // Установка альт. режима AF2 для TIM4 CH2 (PD13) SetAltFunc(GPIOD, 14, 2); // Установка альт. режима AF2 для TIM4 CH3 (PD14) TIM4->CR2 = TIM_CR2_MMS_0 | TIM_CR2_MMS_1; // Генерация пульса сравнения TIM4->ARR = 1000 - 1; // Диапазон сравнения 1000 TIM4->PSC = (84000000 / 1000 / 2000) - 1; // Задан делитель TIM4->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE; // Режим CCR1 TIM4->CCMR1 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // Режим CCR2 TIM4->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; // Режим CCR3 TIM4->CCER = TIM_CCER_CC1E; // Выход PD12 активен TIM4->CCER |= TIM_CCER_CC2E; // Выход PD13 активен TIM4->CCER |= TIM_CCER_CC3E; // Выход PD14 активен TIM4->CR1 = TIM_CR1_CEN; // Таймер запущен RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; // Порт E задействован GPIOE->MODER &= GPIO_MODER_MODER6; // Сброс режима (режим входа) PE6 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Задействован SYSCFG SetEXTI(PORT::E, 6, true, true); // Прерывание PE6 при появлении и исчезновении сигнала NVIC_SetPriority(EXTI9_5_IRQn, 0); // Высший приоритет прерывания NVIC_EnableIRQ(EXTI9_5_IRQn); // Прерывание активировано while (1) { /* POT 1 */ ADC1->SQR3 = 13; // Выбран 13 канал for (int a = 0; a < 100; a++) {} // Ожидать больше 100 тактов ADC1->CR2 |= ADC_CR2_SWSTART; // Начать преобразование while (!(ADC1->SR & ADC_SR_EOC)) {} // Ждать установки бита конца операции data = ADC1->DR; // Получение результата преобразования if (isChanged) // Прочесть значение входящего сигнала в PE6 { TIM4->CCR1 = data / 5; // Скважность PD12 = 100*500/1000 = 100% (RED) TIM4->CCR2 = 0; // Скважность PD13 = 100*500/1000 = 0% (GREEN) TIM4->CCR3 = 0; // Скважность PD14 = 100*500/1000 = 0% (BLUE) } else { TIM4->CCR1 = 0; // Скважность PD12 = 100*500/1000 = 0% (RED) TIM4->CCR2 = 0; // Скважность PD13 = 100*500/1000 = 0% (GREEN) TIM4->CCR3 = data / 5; // Скважность PD14 = 100*500/1000 = 100% (BLUE) } } return 0; } Вывод о проделанной работе В ходе проведенной работы была изучена работа аналогово-цифрового преобразователя: произведена настройка и управление, генерация аналоговых сигналов. Было осуществлено использование аппаратных таймеров для генерации широтно-импульсной модуляции. Было произведено управление системой прерываний микроконтроллера и обработка внешних событий. Была разработана программа, реализующая управление светодиодом RGB с возможностью задавать цвет и частоту мерцания. |