Spyros Papanastasiou
/
General_purpose_timer_TIM2__PWM_LED
Controlling PWM of LED through direct access of TIM2 timer's registers.
main.cpp@4:c52637c8d084, 2019-08-02 (annotated)
- Committer:
- Ladon
- Date:
- Fri Aug 02 04:25:43 2019 +0000
- Revision:
- 4:c52637c8d084
- Parent:
- 3:db424769ecca
- Child:
- 5:3ee6e0113b41
Cleaned up code a bit..
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Ladon | 3:db424769ecca | 1 | //#include <mbed.h> |
Ladon | 3:db424769ecca | 2 | #include "stm32f303xe.h" |
Ladon | 0:12efa8652054 | 3 | #include <iostream> |
Ladon | 0:12efa8652054 | 4 | #include <iomanip> |
Ladon | 0:12efa8652054 | 5 | |
Ladon | 0:12efa8652054 | 6 | using namespace std; |
Ladon | 0:12efa8652054 | 7 | |
Ladon | 0:12efa8652054 | 8 | // Timer functions: |
Ladon | 0:12efa8652054 | 9 | // - |
Ladon | 0:12efa8652054 | 10 | |
Ladon | 4:c52637c8d084 | 11 | void inline timer_enable () |
Ladon | 0:12efa8652054 | 12 | { |
Ladon | 4:c52637c8d084 | 13 | TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN; |
Ladon | 0:12efa8652054 | 14 | } |
Ladon | 0:12efa8652054 | 15 | |
Ladon | 4:c52637c8d084 | 16 | void inline timer_enable_interrupt () |
Ladon | 0:12efa8652054 | 17 | { |
Ladon | 2:7c45a714b991 | 18 | TIM2->DIER = TIM_DIER_UIE; |
Ladon | 0:12efa8652054 | 19 | } |
Ladon | 0:12efa8652054 | 20 | |
Ladon | 4:c52637c8d084 | 21 | void inline timer_clear_status () |
Ladon | 0:12efa8652054 | 22 | { |
Ladon | 2:7c45a714b991 | 23 | TIM2->SR = 0; |
Ladon | 0:12efa8652054 | 24 | } |
Ladon | 0:12efa8652054 | 25 | |
Ladon | 4:c52637c8d084 | 26 | void inline timer_downscale_by (const unsigned short& v) |
Ladon | 0:12efa8652054 | 27 | { |
Ladon | 2:7c45a714b991 | 28 | cout << "Downscaling counter by : 0x" << hex << 1 + v << endl; |
Ladon | 2:7c45a714b991 | 29 | TIM2->PSC = v; |
Ladon | 0:12efa8652054 | 30 | } |
Ladon | 0:12efa8652054 | 31 | |
Ladon | 4:c52637c8d084 | 32 | void inline timer_downscale_by_max () |
Ladon | 0:12efa8652054 | 33 | { |
Ladon | 4:c52637c8d084 | 34 | timer_downscale_by(0xFFFF); |
Ladon | 0:12efa8652054 | 35 | } |
Ladon | 0:12efa8652054 | 36 | |
Ladon | 4:c52637c8d084 | 37 | void inline timer_limit_counter_to (const unsigned int& v) |
Ladon | 0:12efa8652054 | 38 | { |
Ladon | 2:7c45a714b991 | 39 | cout << "Limiting counter to : 0x" << hex << v << endl; |
Ladon | 2:7c45a714b991 | 40 | TIM2->ARR = v; |
Ladon | 0:12efa8652054 | 41 | } |
Ladon | 0:12efa8652054 | 42 | |
Ladon | 4:c52637c8d084 | 43 | void inline timer_set_interrupt_period_to (const double& T) |
Ladon | 0:12efa8652054 | 44 | { |
Ladon | 4:c52637c8d084 | 45 | timer_limit_counter_to(36000); |
Ladon | 4:c52637c8d084 | 46 | timer_downscale_by(1999 + (T - 1) * 2e3); |
Ladon | 1:8d34cf217c0a | 47 | // ^This allows : 500us <= T <= 32.768 |
Ladon | 1:8d34cf217c0a | 48 | // The ^former was found by solving : 0 <= 1999 + (T - 1) * 2e3 <= 0xFFFF, for the prescaler register. |
Ladon | 1:8d34cf217c0a | 49 | // - |
Ladon | 0:12efa8652054 | 50 | } |
Ladon | 0:12efa8652054 | 51 | |
Ladon | 0:12efa8652054 | 52 | // GPIOA functions: |
Ladon | 0:12efa8652054 | 53 | // - |
Ladon | 0:12efa8652054 | 54 | |
Ladon | 4:c52637c8d084 | 55 | void led_init () |
Ladon | 0:12efa8652054 | 56 | { |
Ladon | 2:7c45a714b991 | 57 | GPIOA->MODER &= ~GPIO_MODER_MODER5; |
Ladon | 2:7c45a714b991 | 58 | // Set as output. |
Ladon | 0:12efa8652054 | 59 | // - |
Ladon | 2:7c45a714b991 | 60 | GPIOA->MODER |= 1 << GPIO_MODER_MODER5_Pos; |
Ladon | 0:12efa8652054 | 61 | } |
Ladon | 0:12efa8652054 | 62 | |
Ladon | 4:c52637c8d084 | 63 | void led_toggle () |
Ladon | 0:12efa8652054 | 64 | { |
Ladon | 2:7c45a714b991 | 65 | GPIOA->ODR ^= GPIO_ODR_5; |
Ladon | 0:12efa8652054 | 66 | } |
Ladon | 0:12efa8652054 | 67 | |
Ladon | 0:12efa8652054 | 68 | // Other functions: |
Ladon | 0:12efa8652054 | 69 | // - |
Ladon | 0:12efa8652054 | 70 | |
Ladon | 4:c52637c8d084 | 71 | void inline clock_enable_for_timer () |
Ladon | 0:12efa8652054 | 72 | { |
Ladon | 2:7c45a714b991 | 73 | RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST; |
Ladon | 2:7c45a714b991 | 74 | RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST; |
Ladon | 2:7c45a714b991 | 75 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; |
Ladon | 0:12efa8652054 | 76 | } |
Ladon | 0:12efa8652054 | 77 | |
Ladon | 0:12efa8652054 | 78 | // NVIC functions: |
Ladon | 0:12efa8652054 | 79 | // - |
Ladon | 4:c52637c8d084 | 80 | /* |
Ladon | 4:c52637c8d084 | 81 | // I couldn 't get TIM2_IRQHandler() to work; probably wrong name. |
Ladon | 4:c52637c8d084 | 82 | // - |
Ladon | 2:7c45a714b991 | 83 | extern "C" void TIM2_IRQHandler (void) |
Ladon | 0:12efa8652054 | 84 | { |
Ladon | 2:7c45a714b991 | 85 | cout << "Interrupt hit!" << endl; |
Ladon | 2:7c45a714b991 | 86 | clear_timer_status(); |
Ladon | 0:12efa8652054 | 87 | toggle_LED(); |
Ladon | 0:12efa8652054 | 88 | } |
Ladon | 4:c52637c8d084 | 89 | */ |
Ladon | 4:c52637c8d084 | 90 | void interrupt_handler () |
Ladon | 3:db424769ecca | 91 | { |
Ladon | 3:db424769ecca | 92 | cout << "Interrupt hit!" << endl; |
Ladon | 4:c52637c8d084 | 93 | timer_clear_status(); |
Ladon | 4:c52637c8d084 | 94 | led_toggle(); |
Ladon | 3:db424769ecca | 95 | } |
Ladon | 3:db424769ecca | 96 | |
Ladon | 4:c52637c8d084 | 97 | inline void interrupt_enable () |
Ladon | 0:12efa8652054 | 98 | { |
Ladon | 4:c52637c8d084 | 99 | // NVIC_SetPriority(TIM2_IRQn, 250); |
Ladon | 2:7c45a714b991 | 100 | NVIC_EnableIRQ(TIM2_IRQn); |
Ladon | 4:c52637c8d084 | 101 | NVIC_SetVector(TIM2_IRQn, (uint32_t) &interrupt_handler); |
Ladon | 0:12efa8652054 | 102 | } |
Ladon | 0:12efa8652054 | 103 | |
Ladon | 0:12efa8652054 | 104 | // |
Ladon | 0:12efa8652054 | 105 | // - |
Ladon | 0:12efa8652054 | 106 | // |
Ladon | 0:12efa8652054 | 107 | |
Ladon | 0:12efa8652054 | 108 | int main () |
Ladon | 0:12efa8652054 | 109 | { |
Ladon | 0:12efa8652054 | 110 | cout << "Entered main()." << endl; |
Ladon | 4:c52637c8d084 | 111 | led_init(); |
Ladon | 4:c52637c8d084 | 112 | clock_enable_for_timer(); |
Ladon | 2:7c45a714b991 | 113 | TIM2->ARR = 0xffffffff; |
Ladon | 2:7c45a714b991 | 114 | TIM2->CR1 = TIM2->CR2 = TIM2->SMCR = TIM2->DIER = TIM2->SR = TIM2->CCMR1 = TIM2->CCMR2 |
Ladon | 2:7c45a714b991 | 115 | = TIM2->CCER = TIM2->CNT = TIM2->PSC = TIM2->CCR1 = TIM2->CCR2 = TIM2->CCR3 |
Ladon | 2:7c45a714b991 | 116 | = TIM2->CCR4 = TIM2->DCR = TIM2->DMAR = 0; |
Ladon | 3:db424769ecca | 117 | TIM2->CR1 |= TIM_CR1_UDIS; |
Ladon | 4:c52637c8d084 | 118 | timer_downscale_by_max(); |
Ladon | 4:c52637c8d084 | 119 | timer_limit_counter_to(0x1000); |
Ladon | 0:12efa8652054 | 120 | // ^ LED stays open for 0.5 and closed for 0.5 with a total of 1 sec. |
Ladon | 0:12efa8652054 | 121 | // - |
Ladon | 4:c52637c8d084 | 122 | timer_clear_status(); |
Ladon | 4:c52637c8d084 | 123 | timer_enable_interrupt(); |
Ladon | 4:c52637c8d084 | 124 | timer_enable(); |
Ladon | 4:c52637c8d084 | 125 | interrupt_enable(); |
Ladon | 0:12efa8652054 | 126 | cout << "Exiting main().." << endl; |
Ladon | 0:12efa8652054 | 127 | cout << endl; |
Ladon | 3:db424769ecca | 128 | cout << hex |
Ladon | 3:db424769ecca | 129 | << "Status : 0x" << TIM2->SR << endl |
Ladon | 3:db424769ecca | 130 | << "Count : 0x" << TIM2->CNT << endl; |
Ladon | 3:db424769ecca | 131 | TIM2->CR1 &= ~TIM_CR1_UDIS; |
Ladon | 2:7c45a714b991 | 132 | while (true) |
Ladon | 2:7c45a714b991 | 133 | { |
Ladon | 2:7c45a714b991 | 134 | cout << hex |
Ladon | 2:7c45a714b991 | 135 | << "Status : 0x" << TIM2->SR << endl |
Ladon | 2:7c45a714b991 | 136 | << "Count : 0x" << TIM2->CNT << endl; |
Ladon | 3:db424769ecca | 137 | if (TIM2->CNT > 2) |
Ladon | 3:db424769ecca | 138 | TIM2->SR = 0; |
Ladon | 2:7c45a714b991 | 139 | } |
Ladon | 0:12efa8652054 | 140 | } |