
Controlling PWM of LED through direct access of TIM2 timer's registers.
main.cpp@9:e65dd1ad537e, 2019-08-02 (annotated)
- Committer:
- Ladon
- Date:
- Fri Aug 02 12:22:17 2019 +0000
- Revision:
- 9:e65dd1ad537e
- Parent:
- 8:6464500cc838
- Child:
- 10:f80370dd55f8
2nd version.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Ladon | 5:3ee6e0113b41 | 1 | #include <mbed.h> |
Ladon | 0:12efa8652054 | 2 | #include <iostream> |
Ladon | 0:12efa8652054 | 3 | |
Ladon | 0:12efa8652054 | 4 | using namespace std; |
Ladon | 0:12efa8652054 | 5 | |
Ladon | 5:3ee6e0113b41 | 6 | void led_init () |
Ladon | 0:12efa8652054 | 7 | { |
Ladon | 5:3ee6e0113b41 | 8 | // Led is at PA5. |
Ladon | 5:3ee6e0113b41 | 9 | // - |
Ladon | 9:e65dd1ad537e | 10 | // Set PA5 as AF1 (TIM2_CH1). |
Ladon | 8:6464500cc838 | 11 | // - |
Ladon | 8:6464500cc838 | 12 | ///* |
Ladon | 8:6464500cc838 | 13 | GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL5; |
Ladon | 8:6464500cc838 | 14 | GPIOA->AFR[0] |= 1 << GPIO_AFRL_AFRL5_Pos; |
Ladon | 8:6464500cc838 | 15 | GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5; |
Ladon | 5:3ee6e0113b41 | 16 | GPIOA->MODER &= ~GPIO_MODER_MODER5; |
Ladon | 8:6464500cc838 | 17 | GPIOA->MODER |= 2 << GPIO_MODER_MODER5_Pos; |
Ladon | 8:6464500cc838 | 18 | cout << "AFR : 0x" << hex << (GPIOA->AFR[0] & GPIO_AFRL_AFRL5) << endl; |
Ladon | 8:6464500cc838 | 19 | cout << "OSPEED : 0x" << (GPIOA->OSPEEDR & GPIO_OSPEEDER_OSPEEDR5) << endl; |
Ladon | 8:6464500cc838 | 20 | cout << "MODER : 0x" << (GPIOA->MODER & GPIO_MODER_MODER5) << endl; |
Ladon | 8:6464500cc838 | 21 | //*/ |
Ladon | 0:12efa8652054 | 22 | } |
Ladon | 0:12efa8652054 | 23 | |
Ladon | 5:3ee6e0113b41 | 24 | void inline reset_timer () |
Ladon | 0:12efa8652054 | 25 | { |
Ladon | 5:3ee6e0113b41 | 26 | // Peripheral Reset Register. |
Ladon | 5:3ee6e0113b41 | 27 | // - |
Ladon | 5:3ee6e0113b41 | 28 | RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST; |
Ladon | 5:3ee6e0113b41 | 29 | RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST; |
Ladon | 0:12efa8652054 | 30 | } |
Ladon | 0:12efa8652054 | 31 | |
Ladon | 5:3ee6e0113b41 | 32 | void inline clock_enable_for_timer () |
Ladon | 0:12efa8652054 | 33 | { |
Ladon | 5:3ee6e0113b41 | 34 | // Peripheral Clock Enable Register. |
Ladon | 5:3ee6e0113b41 | 35 | // TIM2 Timer Clock Enable. |
Ladon | 5:3ee6e0113b41 | 36 | // - |
Ladon | 5:3ee6e0113b41 | 37 | reset_timer(); |
Ladon | 5:3ee6e0113b41 | 38 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; |
Ladon | 0:12efa8652054 | 39 | } |
Ladon | 0:12efa8652054 | 40 | |
Ladon | 8:6464500cc838 | 41 | void inline timer_enable_pwm () |
Ladon | 8:6464500cc838 | 42 | { |
Ladon | 9:e65dd1ad537e | 43 | TIM2->CCR1 = TIM2->ARR * 0.6; |
Ladon | 9:e65dd1ad537e | 44 | TIM2->CCMR1 = (0b111 << TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE | TIM_CCMR1_OC1FE; |
Ladon | 9:e65dd1ad537e | 45 | // TIM2->CCER &= ~TIM_CCER_CC1NP; |
Ladon | 8:6464500cc838 | 46 | TIM2->CCER |= TIM_CCER_CC1E; |
Ladon | 8:6464500cc838 | 47 | } |
Ladon | 8:6464500cc838 | 48 | |
Ladon | 4:c52637c8d084 | 49 | void inline timer_downscale_by (const unsigned short& v) |
Ladon | 0:12efa8652054 | 50 | { |
Ladon | 5:3ee6e0113b41 | 51 | // Prescaler. |
Ladon | 5:3ee6e0113b41 | 52 | // - |
Ladon | 2:7c45a714b991 | 53 | TIM2->PSC = v; |
Ladon | 0:12efa8652054 | 54 | } |
Ladon | 0:12efa8652054 | 55 | |
Ladon | 4:c52637c8d084 | 56 | void inline timer_limit_counter_to (const unsigned int& v) |
Ladon | 0:12efa8652054 | 57 | { |
Ladon | 5:3ee6e0113b41 | 58 | // Auto-Reload Register. |
Ladon | 5:3ee6e0113b41 | 59 | // - |
Ladon | 2:7c45a714b991 | 60 | TIM2->ARR = v; |
Ladon | 0:12efa8652054 | 61 | } |
Ladon | 0:12efa8652054 | 62 | |
Ladon | 5:3ee6e0113b41 | 63 | void inline timer_set_period_to (const double& T) |
Ladon | 0:12efa8652054 | 64 | { |
Ladon | 8:6464500cc838 | 65 | // Precondition : T <= 59. |
Ladon | 5:3ee6e0113b41 | 66 | // - |
Ladon | 8:6464500cc838 | 67 | timer_limit_counter_to(72000000 * T); |
Ladon | 0:12efa8652054 | 68 | } |
Ladon | 0:12efa8652054 | 69 | |
Ladon | 5:3ee6e0113b41 | 70 | void inline timer_enable_interrupt () |
Ladon | 5:3ee6e0113b41 | 71 | { |
Ladon | 5:3ee6e0113b41 | 72 | // DMA/ Interrupt Enable Register. |
Ladon | 5:3ee6e0113b41 | 73 | // Update Interrupt Enable. |
Ladon | 5:3ee6e0113b41 | 74 | // - |
Ladon | 8:6464500cc838 | 75 | // TIM2->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE; |
Ladon | 8:6464500cc838 | 76 | TIM2->DIER |= TIM_DIER_UIE; |
Ladon | 5:3ee6e0113b41 | 77 | } |
Ladon | 0:12efa8652054 | 78 | |
Ladon | 5:3ee6e0113b41 | 79 | void inline timer_enable () |
Ladon | 0:12efa8652054 | 80 | { |
Ladon | 5:3ee6e0113b41 | 81 | // Control Register 1. |
Ladon | 5:3ee6e0113b41 | 82 | // Update Request Source | Counter Enable. |
Ladon | 0:12efa8652054 | 83 | // - |
Ladon | 8:6464500cc838 | 84 | // TIM2->CR1 = TIM_CR1_ARPE | TIM_CR1_URS; |
Ladon | 8:6464500cc838 | 85 | TIM2->CR1 = TIM_CR1_URS; |
Ladon | 8:6464500cc838 | 86 | // TIM2->EGR |= TIM_EGR_UG; |
Ladon | 8:6464500cc838 | 87 | TIM2->CR1 |= TIM_CR1_CEN; |
Ladon | 5:3ee6e0113b41 | 88 | } |
Ladon | 5:3ee6e0113b41 | 89 | |
Ladon | 5:3ee6e0113b41 | 90 | void inline timer_clear_status () |
Ladon | 5:3ee6e0113b41 | 91 | { |
Ladon | 5:3ee6e0113b41 | 92 | // Status Register. |
Ladon | 5:3ee6e0113b41 | 93 | // - |
Ladon | 5:3ee6e0113b41 | 94 | TIM2->SR = 0; |
Ladon | 0:12efa8652054 | 95 | } |
Ladon | 0:12efa8652054 | 96 | |
Ladon | 4:c52637c8d084 | 97 | void led_toggle () |
Ladon | 0:12efa8652054 | 98 | { |
Ladon | 5:3ee6e0113b41 | 99 | // Output Data Register. |
Ladon | 5:3ee6e0113b41 | 100 | // - |
Ladon | 2:7c45a714b991 | 101 | GPIOA->ODR ^= GPIO_ODR_5; |
Ladon | 0:12efa8652054 | 102 | } |
Ladon | 0:12efa8652054 | 103 | |
Ladon | 5:3ee6e0113b41 | 104 | /* |
Ladon | 5:3ee6e0113b41 | 105 | // I was unable to use the following handler : |
Ladon | 5:3ee6e0113b41 | 106 | // - |
Ladon | 5:3ee6e0113b41 | 107 | extern "C" void TIM2_IRQHandler (void) |
Ladon | 5:3ee6e0113b41 | 108 | { |
Ladon | 5:3ee6e0113b41 | 109 | cout << "Interrupt hit!" << endl; |
Ladon | 5:3ee6e0113b41 | 110 | clear_timer_status(); |
Ladon | 5:3ee6e0113b41 | 111 | toggle_LED(); |
Ladon | 5:3ee6e0113b41 | 112 | } |
Ladon | 5:3ee6e0113b41 | 113 | */ |
Ladon | 0:12efa8652054 | 114 | |
Ladon | 5:3ee6e0113b41 | 115 | // I couldn 't get TIM2_IRQHandler() to work; probably wrong name. Thus, I 'll use a custom handler |
Ladon | 5:3ee6e0113b41 | 116 | // and attach it using SetVector() from CMSIS : https://arm-software.github.io/CMSIS_5/Core/html/group__NVIC__gr.html. |
Ladon | 4:c52637c8d084 | 117 | // - |
Ladon | 4:c52637c8d084 | 118 | void interrupt_handler () |
Ladon | 3:db424769ecca | 119 | { |
Ladon | 8:6464500cc838 | 120 | // cout << "SR : 0x" << hex << TIM2->SR << endl; |
Ladon | 4:c52637c8d084 | 121 | timer_clear_status(); |
Ladon | 8:6464500cc838 | 122 | // led_toggle(); |
Ladon | 3:db424769ecca | 123 | } |
Ladon | 3:db424769ecca | 124 | |
Ladon | 4:c52637c8d084 | 125 | inline void interrupt_enable () |
Ladon | 0:12efa8652054 | 126 | { |
Ladon | 4:c52637c8d084 | 127 | // NVIC_SetPriority(TIM2_IRQn, 250); |
Ladon | 7:d93dcab712f1 | 128 | NVIC_SetVector(TIM2_IRQn, reinterpret_cast<uint32_t>(interrupt_handler)); |
Ladon | 2:7c45a714b991 | 129 | NVIC_EnableIRQ(TIM2_IRQn); |
Ladon | 5:3ee6e0113b41 | 130 | // ^Definition of NVIC_SetVector() : https://arm-software.github.io/CMSIS_5/Core/html/group__NVIC__gr.html#gab43c1c59d5c081f1bc725237f4b1f916. |
Ladon | 5:3ee6e0113b41 | 131 | // - |
Ladon | 0:12efa8652054 | 132 | } |
Ladon | 0:12efa8652054 | 133 | |
Ladon | 0:12efa8652054 | 134 | // |
Ladon | 0:12efa8652054 | 135 | // - |
Ladon | 0:12efa8652054 | 136 | // |
Ladon | 0:12efa8652054 | 137 | |
Ladon | 0:12efa8652054 | 138 | int main () |
Ladon | 0:12efa8652054 | 139 | { |
Ladon | 0:12efa8652054 | 140 | cout << "Entered main()." << endl; |
Ladon | 4:c52637c8d084 | 141 | led_init(); |
Ladon | 4:c52637c8d084 | 142 | clock_enable_for_timer(); |
Ladon | 8:6464500cc838 | 143 | timer_set_period_to(0.1); |
Ladon | 4:c52637c8d084 | 144 | timer_enable_interrupt(); |
Ladon | 8:6464500cc838 | 145 | timer_enable_pwm(); |
Ladon | 4:c52637c8d084 | 146 | timer_enable(); |
Ladon | 4:c52637c8d084 | 147 | interrupt_enable(); |
Ladon | 0:12efa8652054 | 148 | cout << "Exiting main().." << endl; |
Ladon | 0:12efa8652054 | 149 | } |