[6] | 1 | /** |
---|
| 2 | ****************************************************************************** |
---|
| 3 | * @file Project/STM32L0_Internal_RC_Oscillators_Calibration/Src/hsi16.c |
---|
| 4 | * @author MCD Application Team |
---|
| 5 | * @version V0.1.0 |
---|
| 6 | * @date 17-December-2014 |
---|
| 7 | * @brief This file provides all the HSI measurement and calibration firmware functions. |
---|
| 8 | ****************************************************************************** |
---|
| 9 | * @attention |
---|
| 10 | * |
---|
| 11 | * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2> |
---|
| 12 | * |
---|
| 13 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); |
---|
| 14 | * You may not use this file except in compliance with the License. |
---|
| 15 | * You may obtain a copy of the License at: |
---|
| 16 | * |
---|
| 17 | * http://www.st.com/software_license_agreement_liberty_v2 |
---|
| 18 | * |
---|
| 19 | * Unless required by applicable law or agreed to in writing, software |
---|
| 20 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
| 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
| 22 | * See the License for the specific language governing permissions and |
---|
| 23 | * limitations under the License. |
---|
| 24 | * |
---|
| 25 | ****************************************************************************** |
---|
| 26 | */ |
---|
| 27 | |
---|
| 28 | /* Includes ------------------------------------------------------------------*/ |
---|
| 29 | #include "hsi16.h" |
---|
| 30 | #include <stdio.h> |
---|
| 31 | /* Private typedef -----------------------------------------------------------*/ |
---|
| 32 | /* Private define ------------------------------------------------------------*/ |
---|
| 33 | #define HSI16_MEASURE_FREQUENCY_TABLE |
---|
| 34 | |
---|
| 35 | // Timer related Defines |
---|
| 36 | #define CAPTURE_START ((uint32_t) 0x00000001) |
---|
| 37 | #define CAPTURE_ONGOING ((uint32_t) 0x00000002) |
---|
| 38 | #define CAPTURE_COMPLETED ((uint32_t) 0x00000003) |
---|
| 39 | #define CAPTURE_READY_FOR_NEW ((uint32_t) 0x00000004) |
---|
| 40 | |
---|
| 41 | #define __TIMx_CLK_ENABLE() __HAL_RCC_TIM16_CLK_ENABLE() |
---|
| 42 | #define TIMx TIM16 |
---|
| 43 | #define TIM_CHANNEL_y TIM_CHANNEL_1 |
---|
| 44 | #define HAL_TIM_ACTIVE_CHANNEL_y HAL_TIM_ACTIVE_CHANNEL_1 |
---|
| 45 | #define TIM_TIMx_GPIO TIM16_TI1_GPIO |
---|
| 46 | #define TIM_TIMx_LSE TIM_TIM16_TI1_LSE |
---|
| 47 | #define TIM_TIMx_MCO TIM16_TI1_MCO |
---|
| 48 | #define TIMx_IRQn TIM16_IRQn |
---|
| 49 | |
---|
| 50 | #define INITIAL_ERROR ((uint32_t)99999000) |
---|
| 51 | |
---|
| 52 | /* Exported macro ------------------------------------------------------------*/ |
---|
| 53 | #define __HAL_GET_TIM_PRESCALER(__HANDLE__) ((__HANDLE__)->Instance->PSC) |
---|
| 54 | #define ABS_RETURN(x) ((x < 0) ? (-x) : (x)) |
---|
| 55 | |
---|
| 56 | #define HSI16_TIMx_COUNTER_PRESCALER ((uint32_t)0) |
---|
| 57 | /* The signal in input capture is divided by 8 */ |
---|
| 58 | #define HSI16_TIMx_IC_DIVIDER TIM_ICPSC_DIV8 |
---|
| 59 | |
---|
| 60 | /* The LSE is divided by 8 => LSE/8 = 32768/8 = 4096 */ |
---|
| 61 | #define REFERENCE_FREQUENCY ((uint32_t)4096) /*!< The reference frequency value in Hz */ |
---|
| 62 | |
---|
| 63 | /* Number of measurements in the loop */ |
---|
| 64 | #define HSI16_NUMBER_OF_LOOPS ((uint32_t)10) |
---|
| 65 | |
---|
| 66 | /* Timeout to avoid endless loop */ |
---|
| 67 | #define HSI16_TIMEOUT ((uint32_t)0xFFFFFF) |
---|
| 68 | |
---|
| 69 | /* Get actual trimming settings of HSI16 */ |
---|
| 70 | #define GET_HSI16_TRIMMING_VALUE() ((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> 8) |
---|
| 71 | |
---|
| 72 | /* Private macro -------------------------------------------------------------*/ |
---|
| 73 | /* Private variables ---------------------------------------------------------*/ |
---|
| 74 | |
---|
| 75 | TIM_HandleTypeDef TimHandle; /* Timer handler declaration */ |
---|
| 76 | |
---|
| 77 | static uint16_t LSIFrequency = LSI_VALUE; |
---|
| 78 | static uint32_t __IO CaptureState = 0; |
---|
| 79 | static uint32_t __IO Capture = 0; |
---|
| 80 | static uint32_t IC1ReadValue1 = 0, IC1ReadValue2 = 0; |
---|
| 81 | |
---|
| 82 | #ifdef HSI16_MEASURE_FREQUENCY_TABLE |
---|
| 83 | int32_t aFrequenceChangeTable[128]; /* 2^7 positions*/ |
---|
| 84 | #endif |
---|
| 85 | |
---|
| 86 | /* Private function prototypes -----------------------------------------------*/ |
---|
| 87 | void HSI16_TIMx_ConfigForCalibration(void); |
---|
| 88 | void HSI16_RCC_AdjustCalibrationValue(uint8_t InternOsc, uint8_t TrimmingValue); |
---|
| 89 | uint32_t HSI16_FreqMeasure(void); |
---|
| 90 | void HSI16_MeasurementInit(void); |
---|
| 91 | |
---|
| 92 | void CLK_ConfigForCalibration(void); |
---|
| 93 | void GPIO_ConfigForCalibration(void); |
---|
| 94 | /* Private functions ---------------------------------------------------------*/ |
---|
| 95 | |
---|
| 96 | /** @addtogroup STM32L0xx_AN4631 |
---|
| 97 | * @{ |
---|
| 98 | */ |
---|
| 99 | |
---|
| 100 | /** |
---|
| 101 | * @brief Calibrates internal oscillators HSI to the minimum computed error. |
---|
| 102 | * The system clock source is checked: |
---|
| 103 | * - If HSI oscillator is used as system clock source, HSI is calibrated |
---|
| 104 | * and the new HSI value is returned. |
---|
| 105 | * - Otherwise function returns 0. |
---|
| 106 | * @param None. |
---|
| 107 | * @retval The optimum computed frequency of HSI oscillator. |
---|
| 108 | * Returning 0 means that the system clock source is not HSI. |
---|
| 109 | */ |
---|
| 110 | uint32_t HSI16_CalibrateMinError(void) |
---|
| 111 | { |
---|
| 112 | uint32_t measuredfrequency = 0; |
---|
| 113 | uint32_t sysclockfrequency = 0; |
---|
| 114 | uint32_t optimumfrequency = 0; |
---|
| 115 | uint32_t frequencyerror = 0; |
---|
| 116 | uint32_t optimumfrequencyerror = INITIAL_ERROR; /* Large value */ |
---|
| 117 | uint32_t numbersteps = 0; /* Number of steps: size of trimming bits */ |
---|
| 118 | uint32_t trimmingvalue = 0; |
---|
| 119 | uint32_t optimumcalibrationvalue = 0; |
---|
| 120 | |
---|
| 121 | /* Set measurement environment */ |
---|
| 122 | HSI16_MeasurementInit(); |
---|
| 123 | |
---|
| 124 | /* Get system clock frequency */ |
---|
| 125 | sysclockfrequency = HAL_RCC_GetSysClockFreq(); |
---|
| 126 | |
---|
| 127 | /* HSI16TRIM is 7-bit length */ |
---|
| 128 | numbersteps = 128; /* number of steps is 2^7 = 128 */ |
---|
| 129 | |
---|
| 130 | /* Internal Osc frequency measurement for numbersteps */ |
---|
| 131 | for (trimmingvalue = 0; trimmingvalue < numbersteps; trimmingvalue++) |
---|
| 132 | { |
---|
| 133 | |
---|
| 134 | /* Set the Intern Osc trimming bits to trimmingvalue */ |
---|
| 135 | HSI16_RCC_AdjustCalibrationValue(__HAL_RCC_GET_SYSCLK_SOURCE(), trimmingvalue); |
---|
| 136 | |
---|
| 137 | /* Get actual frequency value */ |
---|
| 138 | measuredfrequency = HSI16_FreqMeasure(); |
---|
| 139 | |
---|
| 140 | /* Compute current frequency error corresponding to the current trimming value: |
---|
| 141 | measured value is subtracted from the typical one */ |
---|
| 142 | frequencyerror = ABS_RETURN((int32_t) (measuredfrequency - sysclockfrequency)); |
---|
| 143 | |
---|
| 144 | /* Get the nearest frequency value to typical one */ |
---|
| 145 | if (optimumfrequencyerror > frequencyerror) |
---|
| 146 | { |
---|
| 147 | optimumfrequencyerror = frequencyerror; |
---|
| 148 | optimumcalibrationvalue = trimmingvalue; |
---|
| 149 | optimumfrequency = measuredfrequency; |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | /* Set trimming bits corresponding to the nearest frequency */ |
---|
| 155 | HSI16_RCC_AdjustCalibrationValue(__HAL_RCC_GET_SYSCLK_SOURCE(), optimumcalibrationvalue); |
---|
| 156 | /* Return the intern oscillator frequency after calibration */ |
---|
| 157 | printf("calilbration value : %d", optimumcalibrationvalue); |
---|
| 158 | measuredfrequency = HSI16_FreqMeasure(); |
---|
| 159 | printf(": frequency : %d\n", measuredfrequency); |
---|
| 160 | return (optimumfrequency); |
---|
| 161 | |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | /** |
---|
| 165 | * @brief Calibrates the internal oscillator (HSI only) with the maximum allowed |
---|
| 166 | * error value set by user. |
---|
| 167 | * If this value was not found, this function sets the oscillator |
---|
| 168 | * to default value. |
---|
| 169 | * @param MaxAllowedError: maximum absolute value allowed of the HSI frequency |
---|
| 170 | * error given in Hz. |
---|
| 171 | * @param Freq: returns value of calibrated frequency |
---|
| 172 | * @retval ErrorStatus: |
---|
| 173 | * - SUCCESS: a frequency error =< MaxAllowedError was found. |
---|
| 174 | * - ERROR: a frequency error =< MaxAllowedError was not found. |
---|
| 175 | */ |
---|
| 176 | ErrorStatus HSI16_CalibrateFixedError(uint32_t MaxAllowedError, uint32_t* Freq) |
---|
| 177 | { |
---|
| 178 | uint32_t measuredfrequency; |
---|
| 179 | uint32_t frequencyerror = 0; |
---|
| 180 | uint32_t sysclockfrequency = 0; |
---|
| 181 | uint32_t trimmingindex = 0; |
---|
| 182 | uint32_t trimmingvalue = 0; |
---|
| 183 | uint32_t numbersteps; |
---|
| 184 | int32_t sign = 1; |
---|
| 185 | ErrorStatus calibrationstatus = ERROR; |
---|
| 186 | |
---|
| 187 | /* HSI16TRIM is 7-bit length */ |
---|
| 188 | numbersteps = 128; /* number of steps is 2^7 = 128 */ |
---|
| 189 | |
---|
| 190 | /* Set measurement environment */ |
---|
| 191 | HSI16_MeasurementInit(); |
---|
| 192 | |
---|
| 193 | /* Get system clock frequency */ |
---|
| 194 | sysclockfrequency = HAL_RCC_GetSysClockFreq(); |
---|
| 195 | |
---|
| 196 | /* Start frequency measurement for current trimming value */ |
---|
| 197 | measuredfrequency = 0; |
---|
| 198 | |
---|
| 199 | /* RC Frequency measurement for different values */ |
---|
| 200 | for (trimmingindex = 0; trimmingindex < numbersteps; trimmingindex++) |
---|
| 201 | { |
---|
| 202 | /* Compute trimming value */ |
---|
| 203 | trimmingvalue = trimmingvalue + (trimmingindex * sign); |
---|
| 204 | sign *= (-1); |
---|
| 205 | |
---|
| 206 | /* Set the HSI16TRIM register to trimmingvalue to be ready for measurement */ |
---|
| 207 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(trimmingvalue); |
---|
| 208 | |
---|
| 209 | /* Get actual frequency value */ |
---|
| 210 | measuredfrequency = HSI16_FreqMeasure(); |
---|
| 211 | |
---|
| 212 | /* Compute current frequency error corresponding to the current trimming value: |
---|
| 213 | measured value is subtracted from the typical one */ |
---|
| 214 | frequencyerror = ABS_RETURN((int32_t) (measuredfrequency - sysclockfrequency)); |
---|
| 215 | |
---|
| 216 | /* Check if frequency error is less or equal to value set by the user */ |
---|
| 217 | if (frequencyerror <= MaxAllowedError) |
---|
| 218 | { |
---|
| 219 | calibrationstatus = SUCCESS; /* The calibration has succeed */ |
---|
| 220 | break; /* stop searching and measurements for frequencies */ |
---|
| 221 | } |
---|
| 222 | } |
---|
| 223 | |
---|
| 224 | /* Save the new HSI value */ |
---|
| 225 | *Freq = measuredfrequency; |
---|
| 226 | |
---|
| 227 | /* If the frequency error set by the user was not found */ |
---|
| 228 | if (calibrationstatus == ERROR) |
---|
| 229 | { |
---|
| 230 | /* Set the HSI16TRIM register to default value */ |
---|
| 231 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(numbersteps / 2); |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | /* Return the calibration status: ERROR or SUCCESS */ |
---|
| 235 | return (calibrationstatus); |
---|
| 236 | } |
---|
| 237 | |
---|
| 238 | #ifdef HSI16_MEASURE_FREQUENCY_TABLE |
---|
| 239 | /** |
---|
| 240 | * @brief For all possible trimming values change of frequency is measured |
---|
| 241 | * @retval None. |
---|
| 242 | */ |
---|
| 243 | void HSI16_GetCurve(void) |
---|
| 244 | { |
---|
| 245 | uint32_t output; |
---|
| 246 | uint32_t measuredfrequency; |
---|
| 247 | uint32_t trimmingindex = 0; |
---|
| 248 | uint32_t trimmingindexorig; |
---|
| 249 | //uint32_t orig_frequency; |
---|
| 250 | uint32_t numbersteps; |
---|
| 251 | uint32_t x; |
---|
| 252 | |
---|
| 253 | /* Set measurement environment */ |
---|
| 254 | HSI16_MeasurementInit(); |
---|
| 255 | |
---|
| 256 | /* HSI16TRIM is 7-bit length */ |
---|
| 257 | numbersteps = 128; /* number of steps is 2^7 = 128 */ |
---|
| 258 | |
---|
| 259 | /* Keep original values */ |
---|
| 260 | trimmingindexorig = GET_HSI16_TRIMMING_VALUE(); |
---|
| 261 | //orig_frequency = HSI16_FreqMeasure(); |
---|
| 262 | |
---|
| 263 | /* RC Frequency measurement for different values */ |
---|
| 264 | for (trimmingindex = 0; trimmingindex < numbersteps; trimmingindex++) |
---|
| 265 | { |
---|
| 266 | /* Set the HSI16TRIM register to trimmingvalue to be ready for measurement */ |
---|
| 267 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(trimmingindex); |
---|
| 268 | /* Start measuring Internal Oscillator frequency */ |
---|
| 269 | output = 2; |
---|
| 270 | while(output == 2) |
---|
| 271 | { |
---|
| 272 | output = HSI16_FreqMeasure(); |
---|
| 273 | } |
---|
| 274 | measuredfrequency = 0; |
---|
| 275 | measuredfrequency += output; |
---|
| 276 | |
---|
| 277 | /* Compute current frequency error corresponding to the current trimming value: |
---|
| 278 | measured value is subtracted from the typical one */ |
---|
| 279 | aFrequenceChangeTable[trimmingindex] = (int32_t)measuredfrequency; |
---|
| 280 | //aFrequenceChangeTable[trimmingindex] = ((int32_t)(measuredfrequency - orig_frequency)); |
---|
| 281 | #ifdef PRINT_FREQUENCY_MEASURE_RESULT |
---|
| 282 | printf(" %3d, %d\n", trimmingindex, aFrequenceChangeTable[trimmingindex]); |
---|
| 283 | #endif |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | /* Set back the original frequency value */ |
---|
| 287 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(trimmingindexorig); |
---|
| 288 | } |
---|
| 289 | #endif |
---|
| 290 | |
---|
| 291 | #ifdef HSI16_MEASURE_FREQUENCY_TABLE |
---|
| 292 | /** |
---|
| 293 | * @brief Adjust calibration value (writing to trimming bits) of selected oscillator. |
---|
| 294 | * @param Freq: pointer to an uint32_t variable that will contain the value |
---|
| 295 | * of the internal oscillator frequency after calibration. |
---|
| 296 | * @retval ErrorStatus: |
---|
| 297 | * - SUCCESS: successful calibration |
---|
| 298 | * - ERROR: if frequency could not be calibrated |
---|
| 299 | */ |
---|
| 300 | ErrorStatus HSI16_CalibrateCurve(uint32_t* Freq) |
---|
| 301 | { |
---|
| 302 | |
---|
| 303 | uint32_t measuredfrequency; |
---|
| 304 | uint32_t optimumcalibrationvalue; |
---|
| 305 | uint32_t i; |
---|
| 306 | uint32_t frequencyerror; |
---|
| 307 | uint32_t numbersteps = 128; |
---|
| 308 | uint32_t optimumfrequencyerror = INITIAL_ERROR; /* Large value */ |
---|
| 309 | ErrorStatus returnvalue = ERROR; |
---|
| 310 | |
---|
| 311 | /* HSI16TRIM is 7-bit length */ |
---|
| 312 | numbersteps = 128; /* number of steps is 2^7 = 128 */ |
---|
| 313 | |
---|
| 314 | /* Get position */ |
---|
| 315 | measuredfrequency = HSI16_FreqMeasure(); |
---|
| 316 | |
---|
| 317 | /* Find the closest difference */ |
---|
| 318 | for (i = 0; i < numbersteps; i++) |
---|
| 319 | { |
---|
| 320 | frequencyerror = ABS_RETURN((int32_t) (HSI_VALUE - (int32_t)(measuredfrequency + aFrequenceChangeTable[i]))); |
---|
| 321 | |
---|
| 322 | /* Get the nearest frequency value to typical one */ |
---|
| 323 | if (frequencyerror < optimumfrequencyerror) |
---|
| 324 | { |
---|
| 325 | optimumfrequencyerror = frequencyerror; |
---|
| 326 | optimumcalibrationvalue = i; |
---|
| 327 | } |
---|
| 328 | } |
---|
| 329 | |
---|
| 330 | if (optimumfrequencyerror != INITIAL_ERROR) |
---|
| 331 | { |
---|
| 332 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(optimumcalibrationvalue); |
---|
| 333 | /* Save the HSI measured value */ |
---|
| 334 | *Freq = measuredfrequency + aFrequenceChangeTable[optimumcalibrationvalue]; |
---|
| 335 | returnvalue = SUCCESS; |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | return returnvalue; |
---|
| 339 | } |
---|
| 340 | #endif |
---|
| 341 | |
---|
| 342 | /** |
---|
| 343 | * @brief Measures actual value of HSI |
---|
| 344 | * @param None. |
---|
| 345 | * @retval Actual HSI frequency |
---|
| 346 | */ |
---|
| 347 | static uint32_t frequencyMW; |
---|
| 348 | static int32_t loopCounter; |
---|
| 349 | |
---|
| 350 | uint32_t HSI16_FreqMeasure(void) |
---|
| 351 | { |
---|
| 352 | uint32_t measuredfrequency; |
---|
| 353 | //uint32_t timeout = HSI16_TIMEOUT; |
---|
| 354 | |
---|
| 355 | /* Start frequency measurement for current trimming value */ |
---|
| 356 | |
---|
| 357 | /* Start measuring Internal Oscillator frequency */ |
---|
| 358 | |
---|
| 359 | // EDIT ECS: |
---|
| 360 | // state machine einbauen um Blocken des Programmablaufes durch die while() Schleife zu verhindern |
---|
| 361 | // state machine ist schon da (globale var "CaptureState") |
---|
| 362 | |
---|
| 363 | if(CaptureState == CAPTURE_READY_FOR_NEW) |
---|
| 364 | { |
---|
| 365 | CaptureState = CAPTURE_START; |
---|
| 366 | |
---|
| 367 | /* Enable capture 1 interrupt */ |
---|
| 368 | HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_y); |
---|
| 369 | |
---|
| 370 | /* Enable the TIMx IRQ channel */ |
---|
| 371 | HAL_NVIC_EnableIRQ(TIMx_IRQn); |
---|
| 372 | // Return Capture Start |
---|
| 373 | return CAPTURE_ONGOING; |
---|
| 374 | } |
---|
| 375 | |
---|
| 376 | else if(CaptureState != CAPTURE_COMPLETED) |
---|
| 377 | { |
---|
| 378 | // Return Capture Ongoing |
---|
| 379 | return CAPTURE_ONGOING; |
---|
| 380 | } |
---|
| 381 | /* Wait for end of capture: two consecutive captures */ |
---|
| 382 | |
---|
| 383 | else if(CaptureState == CAPTURE_COMPLETED) |
---|
| 384 | { |
---|
| 385 | |
---|
| 386 | /* Disable IRQ channel */ |
---|
| 387 | HAL_NVIC_DisableIRQ(TIMx_IRQn); |
---|
| 388 | |
---|
| 389 | /* Disable TIMx */ |
---|
| 390 | HAL_TIM_IC_Stop_IT(&TimHandle, TIM_CHANNEL_y); |
---|
| 391 | |
---|
| 392 | CaptureState = CAPTURE_READY_FOR_NEW; |
---|
| 393 | |
---|
| 394 | if (loopCounter != 0) |
---|
| 395 | { |
---|
| 396 | /* Compute the frequency (the Timer prescaler isn't included) */ |
---|
| 397 | frequencyMW += (uint32_t) (REFERENCE_FREQUENCY * Capture); |
---|
| 398 | } |
---|
| 399 | |
---|
| 400 | if(loopCounter < HSI16_NUMBER_OF_LOOPS) |
---|
| 401 | { |
---|
| 402 | /* Increment loop counter */ |
---|
| 403 | loopCounter++; |
---|
| 404 | return CAPTURE_ONGOING; |
---|
| 405 | } |
---|
| 406 | /* END of Measurement */ |
---|
| 407 | else |
---|
| 408 | { |
---|
| 409 | measuredfrequency = 0; |
---|
| 410 | loopCounter = 0; |
---|
| 411 | /* Compute the average value corresponding the current trimming value */ |
---|
| 412 | measuredfrequency = (uint32_t)((__HAL_GET_TIM_PRESCALER(&TimHandle) + 1) * (frequencyMW / HSI16_NUMBER_OF_LOOPS)); |
---|
| 413 | frequencyMW = 0; |
---|
| 414 | return measuredfrequency; |
---|
| 415 | } |
---|
| 416 | } |
---|
| 417 | return 0; |
---|
| 418 | } |
---|
| 419 | |
---|
| 420 | /** |
---|
| 421 | * @brief Configures all the necessary peripherals necessary from frequency calibration. |
---|
| 422 | * @param None. |
---|
| 423 | * @retval None. |
---|
| 424 | */ |
---|
| 425 | void HSI16_MeasurementInit(void) |
---|
| 426 | { |
---|
| 427 | |
---|
| 428 | /* Configure the GPIO ports before starting calibration process */ |
---|
| 429 | //GPIO_ConfigForCalibration(); |
---|
| 430 | |
---|
| 431 | /* Configure clock before starting calibration process */ |
---|
| 432 | //CLK_ConfigForCalibration(); |
---|
| 433 | |
---|
| 434 | /* Configure TIMx before starting calibration process */ |
---|
| 435 | HSI16_TIMx_ConfigForCalibration(); |
---|
| 436 | CaptureState = CAPTURE_READY_FOR_NEW; |
---|
| 437 | } |
---|
| 438 | |
---|
| 439 | /** |
---|
| 440 | * @brief Configures the TIMx in input capture to measure HSI frequency. |
---|
| 441 | * @param None. |
---|
| 442 | * @retval None. |
---|
| 443 | */ |
---|
| 444 | void HSI16_TIMx_ConfigForCalibration(void) |
---|
| 445 | { |
---|
| 446 | TIM_IC_InitTypeDef ic_config; /* Timer Input Capture Configuration Structure declaration */ |
---|
| 447 | |
---|
| 448 | /* Enable TIMx clock */ |
---|
| 449 | __TIMx_CLK_ENABLE(); |
---|
| 450 | |
---|
| 451 | /* Set TIMx instance */ |
---|
| 452 | TimHandle.Instance = TIMx; |
---|
| 453 | |
---|
| 454 | /* Reset TIMx registers */ |
---|
| 455 | HAL_TIM_IC_DeInit(&TimHandle); |
---|
| 456 | |
---|
| 457 | /* Initialize TIMx peripheral as follows: |
---|
| 458 | + Period = 0xFFFF |
---|
| 459 | + Prescaler = 0 |
---|
| 460 | + ClockDivision = 0 |
---|
| 461 | + Counter direction = Up |
---|
| 462 | */ |
---|
| 463 | TimHandle.Init.Period = 0xFFFF; |
---|
| 464 | TimHandle.Init.Prescaler = HSI16_TIMx_COUNTER_PRESCALER; |
---|
| 465 | TimHandle.Init.ClockDivision = 0; |
---|
| 466 | TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; |
---|
| 467 | if (HAL_TIM_IC_Init(&TimHandle) != HAL_OK) |
---|
| 468 | { |
---|
| 469 | /* Initialization Error */ |
---|
| 470 | while(1); |
---|
| 471 | } |
---|
| 472 | |
---|
| 473 | /* Configure the Input Capture of channel y */ |
---|
| 474 | ic_config.ICPolarity = TIM_ICPOLARITY_RISING; |
---|
| 475 | ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI; |
---|
| 476 | ic_config.ICPrescaler = HSI16_TIMx_IC_DIVIDER; |
---|
| 477 | ic_config.ICFilter = 0; |
---|
| 478 | if (HAL_TIM_IC_ConfigChannel(&TimHandle, &ic_config, TIM_CHANNEL_y) != HAL_OK) |
---|
| 479 | { |
---|
| 480 | /* Configuration Error */ |
---|
| 481 | while(1); |
---|
| 482 | } |
---|
| 483 | |
---|
| 484 | // EDIT ECS START |
---|
| 485 | // Timer Input Source Selection |
---|
| 486 | // LSE als Timer Input |
---|
| 487 | if (HAL_TIMEx_TISelection(&TimHandle, TIM_TIM16_TI1_LSE, TIM_CHANNEL_1) != HAL_OK) |
---|
| 488 | { |
---|
| 489 | while(1); |
---|
| 490 | } |
---|
| 491 | // EDIT ECS END |
---|
| 492 | |
---|
| 493 | /* Configure the NVIC for TIMx */ |
---|
| 494 | HAL_NVIC_SetPriority(TIMx_IRQn, 0, 0); |
---|
| 495 | |
---|
| 496 | /* Disable the TIMx global Interrupt */ |
---|
| 497 | HAL_NVIC_DisableIRQ(TIMx_IRQn); |
---|
| 498 | |
---|
| 499 | } |
---|
| 500 | |
---|
| 501 | |
---|
| 502 | /** |
---|
| 503 | * @brief Adjust calibration value (writing to trimming bits) of selected oscillator. |
---|
| 504 | * @param InternOsc: Internal Oscillator source: HSI |
---|
| 505 | * @param TrimmingValue: calibration value to be written in trimming bits. |
---|
| 506 | * @retval None. |
---|
| 507 | */ |
---|
| 508 | void HSI16_RCC_AdjustCalibrationValue(uint8_t InternOsc, uint8_t TrimmingValue) |
---|
| 509 | { |
---|
| 510 | __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(TrimmingValue); |
---|
| 511 | } |
---|
| 512 | |
---|
| 513 | /** |
---|
| 514 | * @brief Configures LSE to be used as RTC clock source |
---|
| 515 | * @param None. |
---|
| 516 | * @retval None. |
---|
| 517 | */ |
---|
| 518 | void CLK_ConfigForCalibration(void) |
---|
| 519 | { |
---|
| 520 | |
---|
| 521 | /* Enable the LSE OSC */ |
---|
| 522 | __HAL_RCC_LSE_CONFIG(RCC_LSE_ON); |
---|
| 523 | |
---|
| 524 | /* Wait till LSE is ready */ |
---|
| 525 | while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
---|
| 526 | {} |
---|
| 527 | } |
---|
| 528 | |
---|
| 529 | |
---|
| 530 | /** |
---|
| 531 | * @brief Conversion complete callback in non blocking mode |
---|
| 532 | * @param htim : hadc handle |
---|
| 533 | * @retval None |
---|
| 534 | */ |
---|
| 535 | void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) |
---|
| 536 | { |
---|
| 537 | |
---|
| 538 | if ((htim->Channel) == HAL_TIM_ACTIVE_CHANNEL_y) |
---|
| 539 | { |
---|
| 540 | if (CaptureState == CAPTURE_START) |
---|
| 541 | { |
---|
| 542 | /* Get the 1st Input Capture value */ |
---|
| 543 | IC1ReadValue1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_y); |
---|
| 544 | //htim->Instance->CNT = 0; |
---|
| 545 | CaptureState = CAPTURE_ONGOING; |
---|
| 546 | } |
---|
| 547 | else if (CaptureState == CAPTURE_ONGOING) |
---|
| 548 | { |
---|
| 549 | /* Get the 2nd Input Capture value */ |
---|
| 550 | IC1ReadValue2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_y); |
---|
| 551 | |
---|
| 552 | // Timer interrupt ausschalten sonst treten Fehler auf |
---|
| 553 | HAL_NVIC_DisableIRQ(TIMx_IRQn); |
---|
| 554 | HAL_TIM_IC_Stop_IT(&TimHandle, TIM_CHANNEL_y); |
---|
| 555 | __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); |
---|
| 556 | |
---|
| 557 | /* Capture computation */ |
---|
| 558 | if (IC1ReadValue2 > IC1ReadValue1) |
---|
| 559 | { |
---|
| 560 | Capture = (IC1ReadValue2 - IC1ReadValue1); |
---|
| 561 | if(REFERENCE_FREQUENCY * Capture < 13000000) |
---|
| 562 | { |
---|
| 563 | printf("Value not valid\n"); |
---|
| 564 | printf("Frequency Measured = %d\n", REFERENCE_FREQUENCY * Capture); |
---|
| 565 | //while(1); |
---|
| 566 | } |
---|
| 567 | } |
---|
| 568 | else if (IC1ReadValue2 < IC1ReadValue1) |
---|
| 569 | { |
---|
| 570 | Capture = ((0xFFFF - IC1ReadValue1) + IC1ReadValue2); |
---|
| 571 | if(REFERENCE_FREQUENCY * Capture < 13000000) |
---|
| 572 | { |
---|
| 573 | printf("Value not valid\n"); |
---|
| 574 | printf("Frequency Measured = %d\n", REFERENCE_FREQUENCY * Capture); |
---|
| 575 | } |
---|
| 576 | } |
---|
| 577 | else |
---|
| 578 | { |
---|
| 579 | /* If capture values are equal, we have reached the limit of frequency |
---|
| 580 | measures */ |
---|
| 581 | while(1); |
---|
| 582 | } |
---|
| 583 | |
---|
| 584 | CaptureState = CAPTURE_COMPLETED; |
---|
| 585 | } |
---|
| 586 | } |
---|
| 587 | } |
---|
| 588 | |
---|
| 589 | /** |
---|
| 590 | * @} |
---|
| 591 | */ |
---|
| 592 | |
---|
| 593 | void frequencyErrorTest(void) |
---|
| 594 | { |
---|
| 595 | uint32_t HSIFrequencyBeforeCalib, highVal, lowVal; |
---|
| 596 | highVal = 0; |
---|
| 597 | lowVal = 20000000; |
---|
| 598 | HSI16_MeasurementInit(); |
---|
| 599 | while(1) |
---|
| 600 | { |
---|
| 601 | HSIFrequencyBeforeCalib = 2; |
---|
| 602 | while(HSIFrequencyBeforeCalib == 2) |
---|
| 603 | { |
---|
| 604 | HSIFrequencyBeforeCalib = HSI16_FreqMeasure(); |
---|
| 605 | } |
---|
| 606 | |
---|
| 607 | if(HSIFrequencyBeforeCalib > highVal) |
---|
| 608 | { |
---|
| 609 | highVal = HSIFrequencyBeforeCalib; |
---|
| 610 | printf("highest frequency %d\n",highVal); |
---|
| 611 | printf("lowest frequency %d\n",lowVal); |
---|
| 612 | } |
---|
| 613 | if(HSIFrequencyBeforeCalib < lowVal) |
---|
| 614 | { |
---|
| 615 | lowVal = HSIFrequencyBeforeCalib; |
---|
| 616 | printf("highest frequency %d\n",highVal); |
---|
| 617 | printf("lowest frequency %d\n",lowVal); |
---|
| 618 | } |
---|
| 619 | } |
---|
| 620 | } |
---|
| 621 | /******************* (C) COPYRIGHT 2014 STMicroelectronics *****END OF FILE****/ |
---|