Controlling PWM of LED through direct access of TIM2 timer's registers.

Dependencies:   mbed

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?

UserRevisionLine numberNew 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 }