Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
hardware_timer.c@1:c125f4e65df7, 2021-11-03 (annotated)
- Committer:
- rajathr
- Date:
- Wed Nov 03 05:31:26 2021 +0000
- Revision:
- 1:c125f4e65df7
- Parent:
- 0:716b93ab9a58
Commit as on 3rd Nov at 1.31 AM
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| rajathr | 0:716b93ab9a58 | 1 | #include "hardware_timer.h" |
| rajathr | 0:716b93ab9a58 | 2 | #include "gpio.h" |
| rajathr | 0:716b93ab9a58 | 3 | #include "stm32f4xx_rcc_mort.h" |
| rajathr | 0:716b93ab9a58 | 4 | #include "interrupt.h" |
| rajathr | 0:716b93ab9a58 | 5 | |
| rajathr | 0:716b93ab9a58 | 6 | |
| rajathr | 0:716b93ab9a58 | 7 | /*Below are defined all Timers and flags required //Mort: These should be in a timer.c or something like that file*/ |
| rajathr | 0:716b93ab9a58 | 8 | #define TIM3_BASE_ADDRESS ((uint32_t)0x40000400) |
| rajathr | 0:716b93ab9a58 | 9 | #define TIM3_STATUS_REGISTER (TIM3_BASE_ADDRESS + 0x10) |
| rajathr | 0:716b93ab9a58 | 10 | #define TIM3_PSC_REGISTER (TIM3_BASE_ADDRESS + 0x28) |
| rajathr | 0:716b93ab9a58 | 11 | #define TIM3_AUTORELOAD_REGISTER (TIM3_BASE_ADDRESS + 0x2C) |
| rajathr | 0:716b93ab9a58 | 12 | #define TIM3_COUNTER_REGISTER (TIM3_BASE_ADDRESS + 0x24) |
| rajathr | 0:716b93ab9a58 | 13 | #define TIM3_CAPTURE_COMPARE_MODE_2_REGISTER (TIM3_BASE_ADDRESS + 0x1C) |
| rajathr | 0:716b93ab9a58 | 14 | #define TIM_CCMR13_OC1M_0 (0b00010000) |
| rajathr | 0:716b93ab9a58 | 15 | #define TIM_CCMR13_OC1M_1 (0b00100000) |
| rajathr | 0:716b93ab9a58 | 16 | #define TIM_CCMR13_OC1M_2 (0b01000000) |
| rajathr | 0:716b93ab9a58 | 17 | #define TIM_CCMR13_OCPE (0b00001000) |
| rajathr | 0:716b93ab9a58 | 18 | #define TIM_CCMR13_OUTPUT 0x00 |
| rajathr | 0:716b93ab9a58 | 19 | #define TIM3_COMPARE3_REGISTER (TIM3_BASE_ADDRESS + 0x3C) |
| rajathr | 0:716b93ab9a58 | 20 | #define TIM3_CAPTURE_COMPARE_ENABLE_REGISTER (TIM3_BASE_ADDRESS + 0x20) |
| rajathr | 0:716b93ab9a58 | 21 | #define TIM3_CR1_REGISTER1 (TIM3_BASE_ADDRESS + 0x00) |
| rajathr | 0:716b93ab9a58 | 22 | #define TIM3_CAPTURE_COMPARE_MODE_1_REGISTER (TIM3_BASE_ADDRESS + 0x18) |
| rajathr | 0:716b93ab9a58 | 23 | #define TIM3_CAPTURE_COMPARE_REGISTER_1 (TIM3_BASE_ADDRESS + 0x34) |
| rajathr | 0:716b93ab9a58 | 24 | |
| rajathr | 0:716b93ab9a58 | 25 | #define TIM3_CCMR2_CC3S_OUTPUT (0b11111100) |
| rajathr | 0:716b93ab9a58 | 26 | #define TIM3_CCMR2_OC3FE (0b11111011) |
| rajathr | 0:716b93ab9a58 | 27 | #define TIM3_CCMR2_OC3PE (0b00001000) |
| rajathr | 0:716b93ab9a58 | 28 | #define TIM3_CCMR2_OC3M1 (0b11101111) |
| rajathr | 0:716b93ab9a58 | 29 | #define TIM3_CCMR2_OC3M2 (0b01100000) |
| rajathr | 0:716b93ab9a58 | 30 | |
| rajathr | 0:716b93ab9a58 | 31 | #define TIM3_INTERRUPT_ENABLE_REGISTER (TIM3_BASE_ADDRESS + 0x0C) |
| rajathr | 0:716b93ab9a58 | 32 | |
| rajathr | 0:716b93ab9a58 | 33 | |
| rajathr | 0:716b93ab9a58 | 34 | |
| rajathr | 0:716b93ab9a58 | 35 | void TMR3CH3OutputCompare(void) |
| rajathr | 0:716b93ab9a58 | 36 | { |
| rajathr | 0:716b93ab9a58 | 37 | uint16_t *reg; |
| rajathr | 0:716b93ab9a58 | 38 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//Enable Clock - SEE THE BUS UNDER WHICH THE REGISTER OR PERIPHERAL IS PRESENT |
| rajathr | 0:716b93ab9a58 | 39 | |
| rajathr | 0:716b93ab9a58 | 40 | reg = (uint16_t *)TIM3_STATUS_REGISTER; //Read flag value of STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 41 | *reg = (~((uint16_t)0x01)); //Clear update event flag in STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 42 | |
| rajathr | 0:716b93ab9a58 | 43 | reg = (uint16_t *)TIM3_PSC_REGISTER; //Read value of PRESCALER REGISTER |
| rajathr | 0:716b93ab9a58 | 44 | *reg = 8999; //Setting the PRESCALER VALUE TO 899999, CALCULATE BY 90MHz/(Prescale + 1) --> ARR * 1/freq = 1Hz ---> freqcounter = 90MHz/(prescale +1) |
| rajathr | 0:716b93ab9a58 | 45 | |
| rajathr | 0:716b93ab9a58 | 46 | reg = (uint16_t *)TIM3_AUTORELOAD_REGISTER; //Read value of AUTORELOAD REGISTER |
| rajathr | 0:716b93ab9a58 | 47 | *reg = 10000; //Count till 65535 or 2^16-1, DEFINES LIMIT UPTO WHICH COUNTER SHOULD COUNT,POST THIS IT WILL RESET ITSELF |
| rajathr | 0:716b93ab9a58 | 48 | |
| rajathr | 0:716b93ab9a58 | 49 | /*Setup mode resgister 2 to output compare and enable output*/ //(0b00000000 00110000) |
| rajathr | 0:716b93ab9a58 | 50 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_MODE_2_REGISTER; //READ CAPTURE COMPARE MODE REGISTER |
| rajathr | 0:716b93ab9a58 | 51 | *reg = *reg | TIM_CCMR13_OC1M_1 | TIM_CCMR13_OC1M_0 | TIM_CCMR13_OUTPUT;//Setting the Output Compare to the OC3M bit fields and enabling it as an output |
| rajathr | 0:716b93ab9a58 | 52 | |
| rajathr | 0:716b93ab9a58 | 53 | reg = (uint16_t *)TIM3_COMPARE3_REGISTER; //READ VALUE OF COMPARE REGISTER |
| rajathr | 0:716b93ab9a58 | 54 | *reg = 2000; //Any value to count between two cycles- this is the value that we want to compare |
| rajathr | 0:716b93ab9a58 | 55 | |
| rajathr | 0:716b93ab9a58 | 56 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_ENABLE_REGISTER; //READ VALUE OF CAPTURE COMPARE ENABLE REGISTER |
| rajathr | 0:716b93ab9a58 | 57 | *reg = *reg | 0x0100; // Enabling TIM3 Channel3 - Setting the CC3E (Enable) bit in the CCER REGISTER |
| rajathr | 0:716b93ab9a58 | 58 | |
| rajathr | 0:716b93ab9a58 | 59 | //Also keeping the default configuration for channel polarity |
| rajathr | 0:716b93ab9a58 | 60 | reg = (uint16_t *)TIM3_CR1_REGISTER1; |
| rajathr | 0:716b93ab9a58 | 61 | *reg = *reg | ((uint16_t)0x01);//Enabling the Timer3 subsystem by setting the CEN bit in TIM3_CR1 |
| rajathr | 0:716b93ab9a58 | 62 | } |
| rajathr | 0:716b93ab9a58 | 63 | |
| rajathr | 0:716b93ab9a58 | 64 | |
| rajathr | 0:716b93ab9a58 | 65 | void TMR3CH1GPIOCPin6asInputCapture(void) |
| rajathr | 0:716b93ab9a58 | 66 | { |
| rajathr | 0:716b93ab9a58 | 67 | uint16_t *reg; |
| rajathr | 0:716b93ab9a58 | 68 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Enable Clock |
| rajathr | 0:716b93ab9a58 | 69 | |
| rajathr | 0:716b93ab9a58 | 70 | /*Clear Status register*/ |
| rajathr | 0:716b93ab9a58 | 71 | reg = (uint16_t *)TIM3_STATUS_REGISTER; //Read flag value of STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 72 | *reg = (~((uint16_t)0x1)); //Clear update event flag in STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 73 | |
| rajathr | 0:716b93ab9a58 | 74 | reg = (uint16_t *)TIM3_PSC_REGISTER; //Read value of PRESCALER REGISTER |
| rajathr | 0:716b93ab9a58 | 75 | *reg = 9999; //Setting the PRESCALER VALUE TO 9999, CALCULATE BY 90MHz/(Prescale + 1) |
| rajathr | 0:716b93ab9a58 | 76 | |
| rajathr | 0:716b93ab9a58 | 77 | reg = (uint16_t *)TIM3_AUTORELOAD_REGISTER; //Read value of AUTORELOAD REGISTER |
| rajathr | 0:716b93ab9a58 | 78 | *reg = 0xFFFF; //Count till 65535 or 2^16-1, DEFINES LIMIT UPTO WHICH COUNTER SHOULD COUNT,POST THIS IT WILL RESET ITSELF |
| rajathr | 0:716b93ab9a58 | 79 | |
| rajathr | 0:716b93ab9a58 | 80 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_MODE_1_REGISTER; //READ CAPTURE COMPARE MODE REGISTER |
| rajathr | 0:716b93ab9a58 | 81 | *reg = *reg | 0x01;//Configuring CC1 Channel as Input |
| rajathr | 0:716b93ab9a58 | 82 | //IC1 is mapped on TI1 - Configuring the REGISTER TO INPUT CAPTURE - CC1S BIT - 01 |
| rajathr | 0:716b93ab9a58 | 83 | //ALL OTHER BITS TO BE SET FOR INPUT CAPTURE ARE 00's |
| rajathr | 0:716b93ab9a58 | 84 | //IC1PSC - 00 - NO PRESCALER |
| rajathr | 0:716b93ab9a58 | 85 | //IC1F - 0000 - No filter, sampling is done at fDTS - Input Capture 1 Filter |
| rajathr | 0:716b93ab9a58 | 86 | |
| rajathr | 0:716b93ab9a58 | 87 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_ENABLE_REGISTER; //READ VALUE OF CAPTURE COMPARE ENABLE REGISTER |
| rajathr | 0:716b93ab9a58 | 88 | *reg = *reg | 0x01; // Enabling TIM3 Channel1 - Setting the CC3E bit in the CCER REGISTER |
| rajathr | 0:716b93ab9a58 | 89 | //BY DEFAULT TIMER IS SENSITIVE TO RISING EDGE - ENABLE AND KEEP IT AS IT IS |
| rajathr | 0:716b93ab9a58 | 90 | |
| rajathr | 0:716b93ab9a58 | 91 | reg = (uint16_t *)TIM3_CR1_REGISTER1; |
| rajathr | 0:716b93ab9a58 | 92 | *reg = *reg | ((uint16_t)0x01);//Enabling the Timer3 subsystem by setting the CEN bit in TIM3_CR1 |
| rajathr | 0:716b93ab9a58 | 93 | } |
| rajathr | 0:716b93ab9a58 | 94 | |
| rajathr | 0:716b93ab9a58 | 95 | /* Question - Why dont we initialize or set bits of IC1PSC, IC1F AND IC1 |
| rajathr | 0:716b93ab9a58 | 96 | WHY CAN'T IT BE *reg=0b00000001*/ |
| rajathr | 0:716b93ab9a58 | 97 | |
| rajathr | 0:716b93ab9a58 | 98 | uint16_t readCounterValueIfFlagIsSet(void) |
| rajathr | 0:716b93ab9a58 | 99 | { |
| rajathr | 0:716b93ab9a58 | 100 | uint16_t * reg1; |
| rajathr | 0:716b93ab9a58 | 101 | uint16_t * reg2; |
| rajathr | 0:716b93ab9a58 | 102 | uint16_t value; |
| rajathr | 0:716b93ab9a58 | 103 | value=0; |
| rajathr | 0:716b93ab9a58 | 104 | |
| rajathr | 0:716b93ab9a58 | 105 | reg1 = (uint16_t *)TIM3_STATUS_REGISTER; |
| rajathr | 0:716b93ab9a58 | 106 | |
| rajathr | 0:716b93ab9a58 | 107 | if( *reg1 & (uint16_t)0b10 == 0b10 ) |
| rajathr | 0:716b93ab9a58 | 108 | { |
| rajathr | 0:716b93ab9a58 | 109 | reg2 = (uint16_t *)TIM3_CAPTURE_COMPARE_REGISTER_1; |
| rajathr | 0:716b93ab9a58 | 110 | value = *reg2; |
| rajathr | 0:716b93ab9a58 | 111 | //Do we need to clear the flag? - The TIM3_STATUS_REGISTER |
| rajathr | 0:716b93ab9a58 | 112 | } |
| rajathr | 0:716b93ab9a58 | 113 | |
| rajathr | 0:716b93ab9a58 | 114 | return value; |
| rajathr | 0:716b93ab9a58 | 115 | |
| rajathr | 0:716b93ab9a58 | 116 | } |
| rajathr | 0:716b93ab9a58 | 117 | |
| rajathr | 0:716b93ab9a58 | 118 | //read status reguster, |
| rajathr | 0:716b93ab9a58 | 119 | //check if CCIF1 flag is set, if it is, you clear it rc_w0 |
| rajathr | 0:716b93ab9a58 | 120 | //Statusregister = ~(CCIF1) |
| rajathr | 0:716b93ab9a58 | 121 | //and also you read the INput caputre register and return the value. |
| rajathr | 0:716b93ab9a58 | 122 | |
| rajathr | 0:716b93ab9a58 | 123 | |
| rajathr | 0:716b93ab9a58 | 124 | |
| rajathr | 0:716b93ab9a58 | 125 | |
| rajathr | 0:716b93ab9a58 | 126 | uint16_t readCounterRegister(void) |
| rajathr | 0:716b93ab9a58 | 127 | { |
| rajathr | 0:716b93ab9a58 | 128 | uint16_t *reg; |
| rajathr | 0:716b93ab9a58 | 129 | reg = (uint16_t *)TIM3_COUNTER_REGISTER; |
| rajathr | 0:716b93ab9a58 | 130 | return *reg; |
| rajathr | 0:716b93ab9a58 | 131 | } |
| rajathr | 0:716b93ab9a58 | 132 | |
| rajathr | 0:716b93ab9a58 | 133 | |
| rajathr | 0:716b93ab9a58 | 134 | void TMR3CH3OutputPWMMode1(void) |
| rajathr | 0:716b93ab9a58 | 135 | { |
| rajathr | 0:716b93ab9a58 | 136 | uint16_t *reg; |
| rajathr | 0:716b93ab9a58 | 137 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//Enable Clock - SEE THE BUS UNDER WHICH THE REGISTER OR PERIPHERAL IS PRESENT |
| rajathr | 0:716b93ab9a58 | 138 | |
| rajathr | 0:716b93ab9a58 | 139 | reg = (uint16_t *)TIM3_STATUS_REGISTER; //Read flag value of STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 140 | *reg = (~((uint16_t)0x01)); //Clear update event flag in STATUS REGISTER |
| rajathr | 0:716b93ab9a58 | 141 | |
| rajathr | 0:716b93ab9a58 | 142 | reg = (uint16_t *)TIM3_PSC_REGISTER; //Read value of PRESCALER REGISTER |
| rajathr | 0:716b93ab9a58 | 143 | *reg = 35999; //Setting the PRESCALER VALUE TO 35999 |
| rajathr | 0:716b93ab9a58 | 144 | |
| rajathr | 0:716b93ab9a58 | 145 | reg = (uint16_t *)TIM3_AUTORELOAD_REGISTER; //Read value of AUTORELOAD REGISTER |
| rajathr | 0:716b93ab9a58 | 146 | *reg = 10000; //Count till 65535 or 2^16-1, DEFINES LIMIT UPTO WHICH COUNTER SHOULD COUNT,POST THIS IT WILL RESET ITSELF |
| rajathr | 0:716b93ab9a58 | 147 | |
| rajathr | 0:716b93ab9a58 | 148 | /*Setup mode resgister 2 to output compare and enable output*/ //(0b00000000 01101000) |
| rajathr | 0:716b93ab9a58 | 149 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_MODE_2_REGISTER; //READ CAPTURE COMPARE MODE REGISTER |
| rajathr | 0:716b93ab9a58 | 150 | *reg = *reg | TIM3_CCMR2_OC3M2 & TIM3_CCMR2_OC3M1 | TIM3_CCMR2_OC3PE & TIM3_CCMR2_OC3FE & TIM3_CCMR2_CC3S_OUTPUT ;//Setting the PWM Mode 1 to the OC3M bit fields and enabling it as an output |
| rajathr | 0:716b93ab9a58 | 151 | |
| rajathr | 0:716b93ab9a58 | 152 | reg = (uint16_t *)TIM3_COMPARE3_REGISTER; //READ VALUE OF COMPARE REGISTER |
| rajathr | 0:716b93ab9a58 | 153 | *reg = 5000; //We want half of 0.5Hz - Autoreload Register is 0.5Hz and Compare Value is at 0.25Hz |
| rajathr | 0:716b93ab9a58 | 154 | |
| rajathr | 0:716b93ab9a58 | 155 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_ENABLE_REGISTER; //READ VALUE OF CAPTURE COMPARE ENABLE REGISTER |
| rajathr | 0:716b93ab9a58 | 156 | *reg = *reg | 0x0100; // Enabling TIM3 Channel3 - Setting the CC3E (Enable) bit in the CCER REGISTER |
| rajathr | 0:716b93ab9a58 | 157 | |
| rajathr | 0:716b93ab9a58 | 158 | //Also keeping the default configuration for channel polarity |
| rajathr | 0:716b93ab9a58 | 159 | reg = (uint16_t *)TIM3_CR1_REGISTER1; |
| rajathr | 0:716b93ab9a58 | 160 | *reg = *reg | ((uint16_t)0x01);//Enabling the Timer3 subsystem by setting the CEN bit in TIM3_CR1 |
| rajathr | 0:716b93ab9a58 | 161 | } |
| rajathr | 0:716b93ab9a58 | 162 | |
| rajathr | 0:716b93ab9a58 | 163 | void initTimer3ToInterrupt(void) |
| rajathr | 0:716b93ab9a58 | 164 | { |
| rajathr | 0:716b93ab9a58 | 165 | uint16_t * reg; |
| rajathr | 0:716b93ab9a58 | 166 | uint16_t prescalervalue2, autoreloadvalue; |
| rajathr | 0:716b93ab9a58 | 167 | /* Timer 3 APB clock enable */ |
| rajathr | 0:716b93ab9a58 | 168 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); |
| rajathr | 0:716b93ab9a58 | 169 | /*enable the interrupt that would go to timer 3*/ |
| rajathr | 0:716b93ab9a58 | 170 | enableNVIC_Timer3(); |
| rajathr | 0:716b93ab9a58 | 171 | /* Compute Prescale and Autorreload */ |
| rajathr | 0:716b93ab9a58 | 172 | prescalervalue2 = 35999; //Frequency of clock is 90 MHz |
| rajathr | 0:716b93ab9a58 | 173 | autoreloadvalue = 10000; |
| rajathr | 0:716b93ab9a58 | 174 | /* Clear any pending flags in the status register */ |
| rajathr | 0:716b93ab9a58 | 175 | reg = (uint16_t *)TIM3_STATUS_REGISTER; |
| rajathr | 0:716b93ab9a58 | 176 | *reg = 0; |
| rajathr | 0:716b93ab9a58 | 177 | /* Set Prescale and Autorreload */ |
| rajathr | 0:716b93ab9a58 | 178 | reg = (uint16_t *)TIM3_PSC_REGISTER; |
| rajathr | 0:716b93ab9a58 | 179 | *reg = prescalervalue2; |
| rajathr | 0:716b93ab9a58 | 180 | reg = (uint16_t *)TIM3_AUTORELOAD_REGISTER; |
| rajathr | 0:716b93ab9a58 | 181 | *reg = autoreloadvalue; |
| rajathr | 0:716b93ab9a58 | 182 | /* Set Compare Value */ |
| rajathr | 0:716b93ab9a58 | 183 | reg = (uint16_t *)TIM3_COMPARE3_REGISTER; |
| rajathr | 0:716b93ab9a58 | 184 | *reg = autoreloadvalue/2; |
| rajathr | 0:716b93ab9a58 | 185 | /* Enable Preload Register (Don’t HAVE to, but good practice) */ |
| rajathr | 0:716b93ab9a58 | 186 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_MODE_2_REGISTER; |
| rajathr | 0:716b93ab9a58 | 187 | *reg = *reg | 0b00001000; |
| rajathr | 0:716b93ab9a58 | 188 | /*enable the TIM3 channel 3 counter and keep the default configuration for channel polarity*/ |
| rajathr | 0:716b93ab9a58 | 189 | reg = (uint16_t *)TIM3_CAPTURE_COMPARE_ENABLE_REGISTER; |
| rajathr | 0:716b93ab9a58 | 190 | *reg = *reg | 0x0100; |
| rajathr | 0:716b93ab9a58 | 191 | /*enable interrupt on capture compare channel 3*/ |
| rajathr | 0:716b93ab9a58 | 192 | reg = (uint16_t *)TIM3_INTERRUPT_ENABLE_REGISTER; |
| rajathr | 0:716b93ab9a58 | 193 | *reg = (0x8 | 0x1); |
| rajathr | 0:716b93ab9a58 | 194 | /*enable timer 3*/ |
| rajathr | 0:716b93ab9a58 | 195 | reg = (uint16_t *)TIM3_CR1_REGISTER1; |
| rajathr | 0:716b93ab9a58 | 196 | *reg = *reg | (uint16_t)0x01; |
| rajathr | 0:716b93ab9a58 | 197 | } |
| rajathr | 0:716b93ab9a58 | 198 | |
| rajathr | 0:716b93ab9a58 | 199 |