Лабораторная работа № 2: Прерывания и их применение. Использование таймеров
Цель работы:ознакомится с использованием прерывания,возможностями,которые они предоставляют;применять таймеры для выполнения действий в определенные временные интервалы. Прерывания – механизм, который позволяет аппаратному обеспечению сообщать о наступлении важных событий в своей работе. В момент, когда происходит прерывание, процессор переключается с выполнения основной программы на выполнение соответствующего обработчика прерываний. Как только выполнение обработчика завершено, продолжается выполнение основной программы с места, в котором она была прервана.
Для использования прерываний необходимо вначале настроить регистр, который называется Nested Vector Interrupt Controller (NVIC), всторенный контроллер вектора прерываний. Данный регистр является стандартной частью архитектуры ARM и встречается на всех процессорах, независимо от производителя. NVIC разработан таким образом, что задержка прерывания минимальна. NVIC поддерживает встроенные прерывания с 16-ю уровнями приоритета.
Микроконтроллер STM32F407VG содержит 14 таймеров. Производитель разделяет все таймеры на три типа: 1) с расширенными возможностями Advanced-control timers (TIM1 и TIM8); 2) общего назначения General-purpose timers (TIM2, TIM3, TIM4, TIM5); 3) базовые Basic timers.
Каждый таймер может иметь до 4 линий захвата/сравнения (именно они используются в режиме генерации ШИМ). Код программы обеспечивает переключение светодиода с интегрированного к порту GPIO через параметры времени, заданные TIM1. Сконфигурируем в CubeMX источник тактирования в модуле Mode. Зададим Clock Source ⇨ Internal Clock —это значит, что генератор тактирования внутренний — частота задается на плате от шины APB2. Конфигурируем таймер в CubeMX: Up — счётчик будет считать «вверх», от нуля до значения переполнения. Counter Period — Счётчик будет считать до 50000. При частоте 100кГц он досчитает до 50000 за 500мс., нужно вычитать «1» из числа. Поэтому зададим 49999. В CubeMX зададим прерывание. TIM1 update interrupt — прерывание при переполнении, когда счётчик переполнится, он обновится (update). Перед while(1) в режиме прерывания запустим таймер 1: /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim1); /* USER CODE END 2 */ \мигаем светодиодом\ /* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM1) //check if the interrupt comes from TIM1 { HAL_GPIO_TogglePin(led14_GPIO_Port, led14_Pin); \инициализировали мигание светодиода с пина14 Сконфигурируем тактирование микроконтроллера источником внешнего сигнала ETR2. Зададим переполнение равным 10. External clock source mode 2 читается как ETR2. В данном режиме таймер тактируется, когда импульс с низкого уровня становится высоким на выводе TIM1_ETR (PA1). Фильтр входящего сигнала Clock Filter, устраняет дребезг в линии аппаратно. Параметр Clock Polarity — не инвертировать, поэтому таймер тактируется в момент перехода с высокого уровня на низкий. В CubeMX параметр Clock Prescaler — пред делитель частоты входящего сигнала Применим к входному сигналу фильтр №6. fSAMPLING=fDTS/4, N=6. TCK_INT Частота синтеза меньше системной частоты таймера. HAL_TIM_Base_Start_IT(&htim1); /* USER CODE END 2 */ /* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(pa5_GPIO_Port, pa5_Pin, GPIO_PIN_RESET); HAL_Delay(50); HAL_GPIO_WritePin(p5_GPIO_Port, pa5_Pin, GPIO_PIN_SET); HAL_Delay(50); Соединяем порт PA5 с портом светодиода PA14 (TIM1_ETR) и компилируем программу. Таймер имеет четыре канала, которые могут взаимодействовать как с GPIO портами так и с выводами МК, связанными с таймерами. Первый канал в режиме выхода — Output Compare. Прерывание будет происходить в момент переключения. В строке Chanel1 укажем режим Output Compare СН1.
Пред делитель установим 7200, а в строке Counter Period поставим 50000. Через 5 с будет происходить переполнение.
В CubeMX в строке Mode поставим Toggle on match — в момент сравнения, на выводе микроконтроллера PA8 (TIM1_CH1) происходит переключение. Сконфигурируем контроллер по счетчику TIM6: Пример программы Код программы выполняет работу с прерываниями и с таймерами. Светодиод, который подключен к порту ввода/вывода GPIO, переключается через определенные интервалы времени. /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "usb_host.h" /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); static void MX_I2S3_Init(void); static void MX_SPI1_Init(void); static void MX_TIM1_Init(void); void MX_USB_HOST_Process(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance == TIM1) { HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin); } } /* USER CODE END 0 */
/** * @brief The application entry point. * @retval int */ int main(void) { /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; PeriphClkInitStruct.PLLI2S.PLLI2SN = 192; PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } } void TIM6_DAC_IRQHandler(void) { /* USER CODE BEGIN TIM6_DAC_IRQn 0 */ /* USER CODE END TIM6_DAC_IRQn 0 */ HAL_TIM_IRQHandler(&htim6); /* USER CODE BEGIN TIM6_DAC_IRQn 1 */ switch(count){ case 0: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); count++; break; case 1: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); count++; break; case 2: HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); count++; break; case 3: HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_SET); count++; break; default: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); count = 1; break; }
//HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); /* USER CODE END TIM6_DAC_IRQn 1 */ }
Порядок работы 1. На основе примера написать свой код в среде разработки и скомпилировать его. 2. Ознакомиться с работой программы. 3. Создать новый проект в среде CubeMX и Keil. 4. Скомпилировать код на плату и проверить работу на отладочной плате Discavery.
Популярное: Почему стероиды повышают давление?: Основных причин три... Модели организации как закрытой, открытой, частично открытой системы: Закрытая система имеет жесткие фиксированные границы, ее действия относительно независимы... Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ... Как построить свою речь (словесное оформление):
При подготовке публичного выступления перед оратором возникает вопрос, как лучше словесно оформить свою... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (407)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |