Автор работы: Пользователь скрыл имя, 09 Сентября 2014 в 09:42, лекция
В микроконтроллерах семейства STM32L1xx можно организовать отсчет времени по тактам системных часов. По умолчанию в момент запуска системные часы ядра CORTEX – 3M устанавливаются на тактовую частоту f=2000000 гц, обеспечивая длительность одного такта τ=1/f=1/2000000 с =0.0000005 с =0.5 млс. Измерители времени или таймеры способны автономно подсчитывать системные такты до заданной величины.
// (R/W) Coprocessor Access Control Register
__IO uint32_t CPACR; // Offset: 0x088
} SCB_Type;
Продолжим вычисления в теле функции Timer_NVIC. Регистр SCB->AIRCR предназначен для прерываний и управления. В старших двух байтах находится информация для прерывания. Битовая конъюнкция с последующим вычитанием ( 0x700 - ( (SCB->AIRCR) & (uint32_t)0x700 ) ) оставляет инверсию маски в первом байте. Этот результат перемещается с помощью сдвига вправо в нулевой байт и запоминается в рабочей переменной tmp = ( 0x700 - ( (SCB->AIRCR) & (uint32_t)0x700 ) ) >> 0x08.
Затем с помощью инструкции tmppre = ( 0x4 - tmp ) определяется множитель или сдвиг преимущественного приоритета группы. В следующей инструкции tmpsub = tmpsub >> tmp вычисляется приведенный подприоритет внутри группы.
Теперь можно собрать абсолютный приоритет. Сначала с помощью сдвига вычисляется абсолютный преимущественный приоритет группы tmp = (uint32_t)preemptionPriority << tmppre. В младшие биты вставляется подприоритет tmp |= (uint8_t)( subPriority & tmpsub ). Итоговый приоритет получается после сдвига tmp = tmp << 0x04. Остается запомнить его в соответствующем регистре периферийных прерываний NVIC->IP[channel] = tmp. Приоритет установлен.
Теперь необходимо включить разрешение анализа приоритетов для поступающих прерываний:
NVIC->ISER[ channel >> 0x05 ] =
(uint32_t)0x01 << (channel & (uint8_t)0x1F).
Функция Timer_NVIC() завершена.
2.1.6. Вектор прерываний для функции прерывания TIM2_IRQHandler.
В каждом проекте программы файл startup_stm32l1xx_md.s содержит ассемблерный код вектора прерываний. Для программы FT11 этот файл имеет следующий вид.
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD 0 ;NMI_Handler ; NMI Handler
DCD 0 ;HardFault_Handler
DCD 0 ;MemManage_Handler
; MPU Fault Handler
DCD 0 ;BusFault_Handler
DCD 0 ;UsageFault_Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ;SVC_Handler ; SVCall Handler
DCD 0 ;DebugMon_Handler
; Debug Monitor Handler
DCD 0 ; Reserved
DCD 0 ;PendSV_Handler
DCD 0 ;SysTick_Handler
; External Interrupts
DCD 0 ;WWDG_IRQHandler ; Window Watchdog
DCD 0 ;PVD_IRQHandler
; PVD through EXTI Line detect
DCD 0 ;TAMPER_STAMP_IRQHandler
; Tamper and Time Stamp
DCD 0 ;RTC_WKUP_IRQHandler ; RTC Wakeup
DCD 0 ;FLASH_IRQHandler ; FLASH
DCD 0 ;RCC_IRQHandler
DCD 0 ;EXTI0_IRQHandler ; EXTI Line 0
DCD 0 ;EXTI1_IRQHandler ; EXTI Line 1
DCD 0 ;EXTI2_IRQHandler ; EXTI Line 2
DCD 0 ;EXTI3_IRQHandler ; EXTI Line 3
DCD 0 ;EXTI4_IRQHandler ; EXTI Line 4
DCD 0 ;DMA1_Channel1_IRQHandler
; DMA1 Channel 1
DCD 0 ;DMA1_Channel2_IRQHandler
; DMA1 Channel 2
DCD 0 ;DMA1_Channel3_IRQHandler
; DMA1 Channel 3
DCD 0 ;DMA1_Channel4_IRQHandler
; DMA1 Channel 4
DCD 0 ;DMA1_Channel5_IRQHandler
; DMA1 Channel 5
DCD 0 ;DMA1_Channel6_IRQHandler
; DMA1 Channel 6
DCD 0 ;DMA1_Channel7_IRQHandler
; DMA1 Channel 7
DCD 0 ;ADC1_IRQHandler ; ADC1
DCD 0 ;USB_HP_IRQHandler
; USB High Priority
DCD 0 ;USB_LP_IRQHandler
; USB Low Priority
DCD 0 ;DAC_IRQHandler
DCD 0 ;COMP_IRQHandler
; COMP through EXTI Line
DCD 0 ;EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD LCD_IRQHandler
DCD 0 ;TIM9_IRQHandler ; TIM9
DCD 0 ;TIM10_IRQHandler ; TIM10
DCD 0 ;TIM11_IRQHandler ; TIM11
DCD TIM2_IRQHandler
DCD 0 ;TIM3_IRQHandler ; TIM3
DCD 0 ;TIM4_IRQHandler ; TIM4
DCD 0 ;I2C1_EV_IRQHandler ; I2C1 Event
DCD 0 ;I2C1_ER_IRQHandler ; I2C1 Error
DCD 0 ;I2C2_EV_IRQHandler ; I2C2 Event
DCD 0 ;I2C2_ER_IRQHandler ; I2C2 Error
DCD 0 ;SPI1_IRQHandler ; SPI1
DCD 0 ;SPI2_IRQHandler ; SPI2
DCD 0 ;USART1_IRQHandler ; USART1
DCD 0 ;USART2_IRQHandler ; USART2
DCD 0 ;USART3_IRQHandler ; USART3
DCD 0 ;EXTI15_10_IRQHandler
; EXTI Line 15..10
DCD 0 ;RTC_Alarm_IRQHandler
; RTC Alarm through EXTI Line
DCD 0 ;USB_FS_WKUP_IRQHandler
; USB FS Wakeup from suspend
DCD 0 ;TIM6_IRQHandler ; TIM6
DCD 0 ;TIM7_IRQHandler ; TIM7
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset handler routine
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
;Dummy Exception Handlers (infinite loops which can be modified)
Default_Handler PROC
EXPORT LCD_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK]
LCD_IRQHandler
TIM2_IRQHandler
B .
ENDP
ALIGN
В этом векторе прерываний учтены два варианта прерываний: от дисплея LCD_IRQHandler и от таймера TIM2_IRQHandler. Текст функции TIM2_IRQHandler находится вместе с главной функцией main() (п.2.1.1). Каждый раз, когда добавляется новое прерывание, в векторе прерываний необходимо модифицировать или открывать строчку соответствующего прерывания с указанием имени функции обработки прерывания. Непосредственно текст определения это функции записывается на языке Си и размещается в одном из программных файлов проекта (п.2.1.1).
2.2. Доступ к таймерам в файле Timer_Init.h.
Для комфортного программирования функции инициализации всех таймеров и их макросов собраны в подключаемом файле Timer_Lib.h.
// Подключаемый файл Timer_Init.h
// Функции инициализации таймеров
#define TIM2_Start TIM2->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM2_Stop TIM2->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM2_EnInterrupt TIM2->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM2_DisInterrupt TIM2->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM2_EnPending TIM2->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM2_DisPending TIM2->SR &= ~TIM_IT_Update
#define TIM3_Start TIM3->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM3_Stop TIM3->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM3_EnInterrupt TIM3->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM3_DisInterrupt TIM3->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM3_EnPending TIM3->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM3_DisPending TIM3->SR &= ~TIM_IT_Update
#define TIM4_Start TIM4->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM4_Stop TIM4->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM4_EnInterrupt TIM4->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM4_DisInterrupt TIM4->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM4_EnPending TIM4->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM4_DisPending TIM4->SR &= ~TIM_IT_Update
#define TIM6_Start TIM6->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM6_Stop TIM6->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM6_EnInterrupt TIM6->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM6_DisInterrupt TIM6->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM6_EnPending TIM6->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM6_DisPending TIM6->SR &= ~TIM_IT_Update
#define TIM7_Start TIM7->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM7_Stop TIM7->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM7_EnInterrupt TIM7->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM7_DisInterrupt TIM7->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM7_EnPending TIM7->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM7_DisPending TIM7->SR &= ~TIM_IT_Update
#define TIM9_Start TIM9->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM9_Stop TIM9->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM9_EnInterrupt TIM9->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM9_DisInterrupt TIM9->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM9_EnPending TIM9->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM9_DisPending TIM9->SR &= ~TIM_IT_Update
#define TIM10_Start TIM10->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM10_Stop TIM10->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM10_EnInterrupt TIM10->DIER |= TIM_IT_Update
// выключить возможность прерывания
#define TIM10_DisInterrupt TIM10->DIER &= ~TIM_IT_Update
// разрешить использование этого прерывания другими источниками
#define TIM10_EnPending TIM10->SR |= TIM_IT_Update
// запретить использование этого прерывания другими источниками
#define TIM10_DisPending TIM10->SR &= ~TIM_IT_Update
#define TIM11_Start TIM11->CR1 |= TIM_CR1_CEN // старт счетчика
#define TIM11_Stop TIM11->CR1 &= ~TIM_CR1_CEN // стоп счетчика
// включить возможность прерывания
#define TIM11_EnInterrupt TIM11->DIER |= TIM_IT_Update
// выключить возможность прерывания