/** * @brief Temperature monitoring thread * @param none * @retval none */ void Thread_Temperature (void const *argument) { while(1) { HAL_ADC_Start(&ADC1_Handle); /* start ADC conversion */ if (HAL_ADC_PollForConversion(&ADC1_Handle, 10000) == HAL_OK) { /* wait for the conversion to be done and get data */ adc_val = HAL_ADC_GetValue(&ADC1_Handle); /* get the value */ kalmanUpdate(&adcState, adc_val); /* filter the data and update the filter parameters */ temperature = convertTemp(adcState.x); __HAL_ADC_CLEAR_FLAG(&ADC1_Handle, ADC_FLAG_EOC); } // check if the alarm needs to be triggered if (temperature > THRESHHOLD_TEMP_URGENT) { flash_alarm = 2; } else if (temperature > THRESHHOLD_TEMP) { flash_alarm = 1; } else { flash_alarm = 0; } osDelay(TEMP_DELAY); } }
/** * @brief Get ADC injected group conversion result. * @param hadc: ADC handle * @param InjectedRank: the converted ADC injected rank. * This parameter can be one of the following values: * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected * @retval None */ uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank) { uint32_t tmp_jdr = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); assert_param(IS_ADC_INJECTED_RANK(InjectedRank)); /* Clear injected group conversion flag to have similar behaviour as */ /* regular group: reading data register also clears end of conversion flag. */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Get ADC converted value */ switch(InjectedRank) { case ADC_INJECTED_RANK_4: tmp_jdr = hadc->Instance->JDR4; break; case ADC_INJECTED_RANK_3: tmp_jdr = hadc->Instance->JDR3; break; case ADC_INJECTED_RANK_2: tmp_jdr = hadc->Instance->JDR2; break; case ADC_INJECTED_RANK_1: default: tmp_jdr = hadc->Instance->JDR1; break; } /* Return ADC converted value */ return tmp_jdr; }
/** * @brief Enables ADC, starts conversion of injected group with interruption. * - JEOC (end of conversion of injected group) * Each of these interruptions has its dedicated callback function. * @param hadc: ADC handle * @retval HAL status. */ HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Process locked */ __HAL_LOCK(hadc); /* Enable the ADC peripheral */ tmp_hal_status = ADC_Enable(hadc); /* Start conversion if ADC is effectively enabled */ if (tmp_hal_status != HAL_ERROR) { /* Check if a regular conversion is ongoing */ if(hadc->State == HAL_ADC_STATE_BUSY_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ; } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Set ADC error code to none */ ADC_CLEAR_ERRORCODE(hadc); /* Clear injected group conversion flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Enable end of conversion interrupt for injected channels */ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC); /* Enable conversion of injected group. */ /* If software start has been selected, conversion starts immediately. */ /* If external trigger has been selected, conversion will start at next */ /* trigger event. */ /* If automatic injected conversion is enabled, conversion will start */ /* after next regular group conversion. */ if (ADC_IS_SOFTWARE_START_INJECTED(hadc) && HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) ) { /* Enable ADC software conversion for injected channels */ SET_BIT(hadc->Instance->CR2, ADC_CR2_JSWSTART); } } /* Return function status */ return tmp_hal_status; }
/*---------------------------------------------------------------------------- * Implementation of the temperature checking thread *---------------------------------------------------------------------------*/ void Thread_check_temp (void const *argument) { float temperature = 0.0f; while(1){ //Using a delay of 10ms so that the frequency of temperature sampling is 100Hz osDelay(10); //Start the ADC if (HAL_ADC_Start(&ADC1_Handle) != HAL_OK) { Error_Handler(ADC_START_FAIL); } else { //Check for successful conversion of the polled analog value to a digital reading if(HAL_ADC_PollForConversion(&ADC1_Handle, 1000000) != HAL_OK) { Error_Handler(ADC_POLL_FAIL); } else { //Measure temperature from sensor temperature = get_data_from_sensor(); } //Clear the EOC flag __HAL_ADC_CLEAR_FLAG(&ADC1_Handle,ADC_FLAG_EOC); } //Pass the temp value to the temperature checking function display_temp = temperature; check_temperature_status(display_temp); } }
/** * @brief Gets the converted value from data register of injected channel. * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param InjectedRank: the ADC injected rank. * This parameter can be one of the following values: * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected * @retval None */ uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank) { __IO uint32_t tmp = 0; /* Check the parameters */ assert_param(IS_ADC_INJECTED_RANK(InjectedRank)); /* Clear the ADCx's flag for injected end of conversion */ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_JEOC); /* Return the selected ADC converted value */ switch (InjectedRank) { case ADC_INJECTED_RANK_4: { tmp = hadc->Instance->JDR4; } break; case ADC_INJECTED_RANK_3: { tmp = hadc->Instance->JDR3; } break; case ADC_INJECTED_RANK_2: { tmp = hadc->Instance->JDR2; } break; case ADC_INJECTED_RANK_1: { tmp = hadc->Instance->JDR1; } break; default: break; } return tmp; }
/** * @brief Poll for conversion event * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param EventType: the ADC event type. * This parameter can be one of the following values: * @arg ADC_AWD_EVENT: ADC Analog watch Dog event. * @arg ADC_OVR_EVENT: ADC Overrun event. * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout) { uint32_t tickstart = 0; /* Check the parameters */ assert_param(IS_ADC_EVENT_TYPE(EventType)); /* Get tick */ tickstart = HAL_GetTick(); /* Check selected event flag */ while(!(__HAL_ADC_GET_FLAG(hadc,EventType))) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { hadc->State= HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_TIMEOUT; } } } /* Check analog watchdog flag */ if(EventType == ADC_AWD_EVENT) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_AWD; /* Clear the ADCx's analog watchdog flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD); } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_ERROR; /* Clear the ADCx's Overrun flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR); } /* Return ADC state */ return HAL_OK; }
/** * @brief This function handles ADC1_2 interrupt request. * @param None * @retval None */ void ADC1_2_IRQHandler(void) { /* Clear ADC interrupt flag */ __HAL_ADC_CLEAR_FLAG(&AdcHandle, ADC_FLAG_JEOS); /* Get conversion value of Vin and Vout synchronized with Timer A CMP4 */ VinConversion = HAL_ADCEx_InjectedGetValue(&AdcHandle, ADC_INJECTED_RANK_1); VoutConversion = HAL_ADCEx_InjectedGetValue(&AdcHandle, ADC_INJECTED_RANK_2); }
/** * @brief Poll for injected conversion complete * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart = 0U; /* Get tick */ tickstart = HAL_GetTick(); /* Check End of conversion flag */ while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC))) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) { hadc->State= HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_TIMEOUT; } } } /* Clear injected group conversion flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); /* Update ADC state machine */ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC); /* Determine whether any further conversion upcoming on group injected */ /* by external trigger, continuous mode or scan sequence on going. */ /* Note: On STM32F4, there is no independent flag of end of sequence. */ /* The test of scan sequence on going is done either with scan */ /* sequence disabled or with end of conversion flag set to */ /* of end of sequence. */ if(ADC_IS_SOFTWARE_START_INJECTED(hadc) && (HAL_IS_BIT_CLR(hadc->Instance->JSQR, ADC_JSQR_JL) || HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS) ) && (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) && (ADC_IS_SOFTWARE_START_REGULAR(hadc) && (hadc->Init.ContinuousConvMode == DISABLE) ) ) ) { /* Set ADC state */ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY); if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) { SET_BIT(hadc->State, HAL_ADC_STATE_READY); } } /* Return ADC state */ return HAL_OK; }
/** * @brief 电机驱动芯片工作电流采样初值计算 * @param None * @retval None */ void Motor_CurrentReadingCalibration() { u32 sum[2] = {0, 0}; u16 bIndex; //获得零电压偏移值 for(bIndex=0; bIndex <16; bIndex++) { while(!__HAL_ADC_GET_FLAG(MotorParams[0].CURR_ADC, ADC_FLAG_JEOC)) { } __HAL_ADC_CLEAR_FLAG(MotorParams[0].CURR_ADC, ADC_FLAG_JEOC); sum[0] += HAL_ADCEx_InjectedGetValue(MotorParams[0].CURR_ADC, ADC_INJECTED_RANK_1); while(!__HAL_ADC_GET_FLAG(MotorParams[1].CURR_ADC, ADC_FLAG_JEOC)) { } __HAL_ADC_CLEAR_FLAG(MotorParams[1].CURR_ADC, ADC_FLAG_JEOC); sum[1] += HAL_ADCEx_InjectedGetValue(MotorParams[1].CURR_ADC, ADC_INJECTED_RANK_1); } MotorParams[0].h_phase_a_offset = sum[0] / bIndex; MotorParams[1].h_phase_a_offset = sum[1] / bIndex; }
/*---------------------------------------------------------------------------- * Thread 'LED_Thread': Toggles LED *---------------------------------------------------------------------------*/ void Thread_Temp (void const *argument) { while(1){ osDelay(1000); HAL_ADC_Start(&ADCHandleinit); HAL_ADC_PollForConversion(&ADCHandleinit, 10); rawValue = HAL_ADC_GetValue(&ADCHandleinit); convertedValue[0] = tempConv(rawValue); if(convertedValue[0] > 38) overHeat = 1; else overHeat = 0; __HAL_ADC_CLEAR_FLAG(&ADCHandleinit,ADC_FLAG_EOC); } }
/** * @brief Polls the ADC for temperature digitization, and filters using Kalman filter * > Set alarm if temperature above threshold * @file main.c * @param None * @retval None */ void poll() { float voltage, temperature, filtered_temp; HAL_ADC_Start(&ADC1_Handle); if (HAL_ADC_PollForConversion(&ADC1_Handle, 10) == HAL_OK) { voltage = HAL_ADC_GetValue(&ADC1_Handle); voltage *= (3000.0f/0xfff); // getting resolution in mV temperature = (voltage -760.0f) / 2.5f; // normalizing around 25C voltage and average slope temperature += 25.0f; // Use Kalman filter to get filtered value and store in 'filtered_temp' Kalmanfilter_C(&temperature, &filtered_temp, &kalman_temp, 1); // printf("%f\n", filtered_temp); getSetValue(filtered_temp,1,2); __HAL_ADC_CLEAR_FLAG(&ADC1_Handle,ADC_FLAG_EOC); } }
/** * @brief Gets the converted value from data register of injected channel. * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param InjectedRank: the ADC injected rank. * This parameter can be one of the following values: * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected * @retval None */ uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank) { __IO uint32_t tmp = 0U; /* Check the parameters */ assert_param(IS_ADC_INJECTED_RANK(InjectedRank)); /* Clear injected group conversion flag to have similar behaviour as */ /* regular group: reading data register also clears end of conversion flag. */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Return the selected ADC converted value */ switch(InjectedRank) { case ADC_INJECTED_RANK_4: { tmp = hadc->Instance->JDR4; } break; case ADC_INJECTED_RANK_3: { tmp = hadc->Instance->JDR3; } break; case ADC_INJECTED_RANK_2: { tmp = hadc->Instance->JDR2; } break; case ADC_INJECTED_RANK_1: { tmp = hadc->Instance->JDR1; } break; default: break; } return tmp; }
/** * @brief Enables the interrupt and starts ADC conversion of injected channels. * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * * @retval HAL status. */ HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc) { __IO uint32_t counter = 0U; uint32_t tmp1 = 0U, tmp2 = 0U; /* Process locked */ __HAL_LOCK(hadc); /* Enable the ADC peripheral */ /* Check if ADC peripheral is disabled in order to enable it and wait during Tstab time the ADC's stabilization */ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) { /* Enable the Peripheral */ __HAL_ADC_ENABLE(hadc); /* Delay for ADC stabilization time */ /* Compute number of CPU cycles to wait for */ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); while(counter != 0U) { counter--; } } /* Start conversion if ADC is effectively enabled */ if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) { /* Set ADC state */ /* - Clear state bitfield related to injected group conversion results */ /* - Set state bitfield related to injected operation */ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); /* Check if a regular conversion is ongoing */ /* Note: On this device, there is no ADC error code fields related to */ /* conversions on group injected only. In case of conversion on */ /* going on group regular, no error code is reset. */ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) { /* Reset ADC all error code fields */ ADC_CLEAR_ERRORCODE(hadc); } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Clear injected group conversion flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); /* Enable end of conversion interrupt for injected channels */ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC); /* Check if Multimode enabled */ if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI)) { tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); if(tmp1 && tmp2) { /* Enable the selected ADC software conversion for injected group */ hadc->Instance->CR2 |= ADC_CR2_JSWSTART; } } else { tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); if((hadc->Instance == ADC1) && tmp1 && tmp2) { /* Enable the selected ADC software conversion for injected group */ hadc->Instance->CR2 |= ADC_CR2_JSWSTART; } } } /* Return function status */ return HAL_OK; }
/** * @brief Wait for injected group conversion to be completed. * @param hadc: ADC handle * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart; /* Variables for polling in case of scan mode enabled and polling for each */ /* conversion. */ __IO uint32_t Conversion_Timeout_CPU_cycles = 0; uint32_t Conversion_Timeout_CPU_cycles_max = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Get timeout */ tickstart = HAL_GetTick(); /* Polling for end of conversion: differentiation if single/sequence */ /* conversion. */ /* For injected group, flag JEOC is set only at the end of the sequence, */ /* not for each conversion within the sequence. */ /* - If single conversion for injected group (scan mode disabled or */ /* InjectedNbrOfConversion ==1), flag jEOC is used to determine the */ /* conversion completion. */ /* - If sequence conversion for injected group (scan mode enabled and */ /* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */ /* sequence. */ /* To poll for each conversion, the maximum conversion time is computed */ /* from ADC conversion time (selected sampling time + conversion time of */ /* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */ /* settings, conversion time range can be from 28 to 32256 CPU cycles). */ if ((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET) { /* Wait until End of Conversion flag is raised */ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC)) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } } } else { /* Poll with maximum conversion time */ /* - Computation of CPU clock cycles corresponding to ADC clock cycles */ /* and ADC maximum conversion cycles on all channels. */ /* - Wait for the expected ADC clock cycles delay */ Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC)) * ADC_CONVCYCLES_MAX_RANGE(hadc) ); while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } Conversion_Timeout_CPU_cycles ++; } } /* Clear injected group conversion flag (and regular conversion flag raised */ /* simultaneously) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC | ADC_FLAG_EOC); /* Update state machine on conversion status if not in error state */ if(hadc->State != HAL_ADC_STATE_ERROR) { /* Update ADC state machine */ if(hadc->State != HAL_ADC_STATE_EOC_INJ_REG) { if(hadc->State == HAL_ADC_STATE_EOC_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ; } } } /* Return ADC state */ return HAL_OK; }
/** * @brief Enables ADC DMA request after last transfer (Multi-ADC mode) and enables ADC peripheral * * @note Caution: This function must be used only with the ADC master. * * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param pData: Pointer to buffer in which transferred from ADC peripheral to memory will be stored. * @param Length: The length of data to be transferred from ADC peripheral to memory. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) { __IO uint32_t counter = 0U; /* Check the parameters */ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests)); /* Process locked */ __HAL_LOCK(hadc); /* Check if ADC peripheral is disabled in order to enable it and wait during Tstab time the ADC's stabilization */ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) { /* Enable the Peripheral */ __HAL_ADC_ENABLE(hadc); /* Delay for temperature sensor stabilization time */ /* Compute number of CPU cycles to wait for */ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); while(counter != 0U) { counter--; } } /* Start conversion if ADC is effectively enabled */ if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) { /* Set ADC state */ /* - Clear state bitfield related to regular group conversion results */ /* - Set state bitfield related to regular group operation */ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR, HAL_ADC_STATE_REG_BUSY); /* If conversions on group regular are also triggering group injected, */ /* update ADC state. */ if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET) { ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); } /* State machine update: Check if an injected conversion is ongoing */ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY)) { /* Reset ADC error code fields related to conversions on group regular */ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA)); } else { /* Reset ADC all error code fields */ ADC_CLEAR_ERRORCODE(hadc); } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Set the DMA transfer complete callback */ hadc->DMA_Handle->XferCpltCallback = ADC_MultiModeDMAConvCplt; /* Set the DMA half transfer complete callback */ hadc->DMA_Handle->XferHalfCpltCallback = ADC_MultiModeDMAHalfConvCplt; /* Set the DMA error callback */ hadc->DMA_Handle->XferErrorCallback = ADC_MultiModeDMAError ; /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */ /* start (in case of SW start): */ /* Clear regular group conversion flag and overrun flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC); /* Enable ADC overrun interrupt */ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR); if (hadc->Init.DMAContinuousRequests != DISABLE) { /* Enable the selected ADC DMA request after last transfer */ ADC->CCR |= ADC_CCR_DDS; } else { /* Disable the selected ADC EOC rising on each regular channel conversion */ ADC->CCR &= ~ADC_CCR_DDS; } /* Enable the DMA Stream */ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&ADC->CDR, (uint32_t)pData, Length); /* if no external trigger present enable software conversion of regular channels */ if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET) { /* Enable the selected ADC software conversion for regular group */ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; } } /* Return function status */ return HAL_OK; }
/** @brief ADC conversion end interrupt */ extern "C" void ADC_IRQHandler (void) { adc::value = AdcHandle.Instance->DR; /* Clear the ADCx flag for regular end of conversion */ __HAL_ADC_CLEAR_FLAG(&AdcHandle, ADC_FLAG_EOC); }
/** * @brief Enables ADC, starts conversion of regular group and transfers result * through DMA. * Multimode must have been previously configured using * HAL_ADCEx_MultiModeConfigChannel() function. * Interruptions enabled in this function: * - DMA transfer complete * - DMA half transfer * Each of these interruptions has its dedicated callback function. * @note: On STM32F1 devices, ADC slave regular group must be configured * with conversion trigger ADC_SOFTWARE_START. * @note: ADC slave can be enabled preliminarily using single-mode * HAL_ADC_Start() function. * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used) * @param pData: The destination Buffer address. * @param Length: The length of data to be transferred from ADC peripheral to memory. * @retval None */ HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; ADC_HandleTypeDef tmphadcSlave; /* Check the parameters */ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); /* Process locked */ __HAL_LOCK(hadc); /* Set a temporary handle of the ADC slave associated to the ADC master */ ADC_MULTI_SLAVE(hadc, &tmphadcSlave); /* On STM32F1 devices, ADC slave regular group must be configured with */ /* conversion trigger ADC_SOFTWARE_START. */ /* Note: External trigger of ADC slave must be enabled, it is already done */ /* into function "HAL_ADC_Init()". */ if ((tmphadcSlave.Instance == NULL) || (! ADC_IS_SOFTWARE_START_REGULAR(&tmphadcSlave)) ) { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } /* Enable the ADC peripherals: master and slave (in case if not already */ /* enabled previously) */ tmp_hal_status = ADC_Enable(hadc); if (tmp_hal_status != HAL_ERROR) { tmp_hal_status = ADC_Enable(&tmphadcSlave); } /* Start conversion all ADCs of multimode are effectively enabled */ if (tmp_hal_status != HAL_ERROR) { /* State machine update (ADC master): Check if an injected conversion is */ /* ongoing. */ if(hadc->State == HAL_ADC_STATE_BUSY_INJ) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_REG; } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Set ADC error code to none */ ADC_CLEAR_ERRORCODE(hadc); /* Set the DMA transfer complete callback */ hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt; /* Set the DMA half transfer complete callback */ hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt; /* Set the DMA error callback */ hadc->DMA_Handle->XferErrorCallback = ADC_DMAError; /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */ /* start (in case of SW start): */ /* Clear regular group conversion flag and overrun flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC); /* Enable ADC DMA mode of ADC master */ SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA); /* Start the DMA channel */ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length); /* Start conversion of regular group if software start has been selected. */ /* If external trigger has been selected, conversion will start at next */ /* trigger event. */ /* Note: Alternate trigger for single conversion could be to force an */ /* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/ if (ADC_IS_SOFTWARE_START_REGULAR(hadc)) { /* Start ADC conversion on regular group with SW start */ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG)); } else { /* Start ADC conversion on regular group with external trigger */ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG); } } else { /* Process unlocked */ __HAL_UNLOCK(hadc); } /* Return function status */ return tmp_hal_status; }
/** * @brief Handles ADC interrupt request * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @retval None */ void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc) { uint32_t tmp1 = 0, tmp2 = 0; /* Check the parameters */ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion)); assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection)); tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC); tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_EOC); /* Check End of conversion flag for regular channels */ if(tmp1 && tmp2) { /* Check if an injected conversion is ready */ if(hadc->State == HAL_ADC_STATE_EOC_INJ) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_REG; } if((hadc->Init.ContinuousConvMode == DISABLE) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)) { if(hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV) { /* DISABLE the ADC end of conversion interrupt for regular group */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC); /* DISABLE the ADC overrun interrupt */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR); } else { if (hadc->NbrOfCurrentConversionRank == 0) { hadc->NbrOfCurrentConversionRank = hadc->Init.NbrOfConversion; } /* Decrement the number of conversion when an interrupt occurs */ hadc->NbrOfCurrentConversionRank--; /* Check if all conversions are finished */ if(hadc->NbrOfCurrentConversionRank == 0) { /* DISABLE the ADC end of conversion interrupt for regular group */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC); /* DISABLE the ADC overrun interrupt */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR); } } } /* Conversion complete callback */ HAL_ADC_ConvCpltCallback(hadc); /* Clear the ADCx flag for regular end of conversion */ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_EOC); } tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC); tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_JEOC); /* Check End of conversion flag for injected channels */ if(tmp1 && tmp2) { /* Check if a regular conversion is ready */ if(hadc->State == HAL_ADC_STATE_EOC_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ; } tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); if(((hadc->Init.ContinuousConvMode == DISABLE) || tmp1) && tmp2) { /* DISABLE the ADC end of conversion interrupt for injected group */ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC); } /* Conversion complete callback */ HAL_ADCEx_InjectedConvCpltCallback(hadc); /* Clear the ADCx flag for injected end of conversion */ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_JEOC); } tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_AWD); tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_AWD); /* Check Analog watchdog flag */ if(tmp1 && tmp2) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_AWD; /* Clear the ADCx's Analog watchdog flag */ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_AWD); /* Level out of window callback */ HAL_ADC_LevelOutOfWindowCallback(hadc); } tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_OVR); tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_OVR); /* Check Overrun flag */ if(tmp1 && tmp2) { /* Change ADC state to overrun state */ hadc->State = HAL_ADC_STATE_ERROR; /* Set ADC error code to overrun */ hadc->ErrorCode |= HAL_ADC_ERROR_OVR; /* Clear the Overrun flag */ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_OVR); /* Error callback */ HAL_ADC_ErrorCallback(hadc); } }
/** * @brief Wait for injected group conversion to be completed. * @param hadc: ADC handle * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart; /* Variables for polling in case of scan mode enabled and polling for each */ /* conversion. */ /* Note: Variable "conversion_timeout_cpu_cycles" set to offset 28 CPU */ /* cycles to compensate number of CPU cycles for processing of variable */ /* "conversion_timeout_cpu_cycles_max" */ uint32_t conversion_timeout_cpu_cycles = 28; uint32_t conversion_timeout_cpu_cycles_max = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); /* Get timeout */ tickstart = HAL_GetTick(); /* Polling for end of conversion: differentiation if single/sequence */ /* conversion. */ /* For injected group, flag JEOC is set only at the end of the sequence, */ /* not for each conversion within the sequence. */ /* If setting "EOCSelection" is set to poll for each single conversion, */ /* management of polling depends on setting of injected group sequencer: */ /* - If single conversion for injected group (scan mode disabled or */ /* InjectedNbrOfConversion ==1), flag JEOC is used to determine the */ /* conversion completion. */ /* - If sequence conversion for injected group (scan mode enabled and */ /* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */ /* sequence. */ /* To poll for each conversion, the maximum conversion time is computed */ /* from ADC conversion time (selected sampling time + conversion time of */ /* 12 ADC clock cycles) and APB2/ADC clock prescalers (depending on */ /* settings, conversion time range can vary from 8 to several thousands */ /* of CPU cycles). */ /* Note: On STM32L1, setting "EOCSelection" is related to regular group */ /* only, by hardware. For compatibility with other STM32 devices, */ /* this setting is related also to injected group by software. */ if (((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET) || (hadc->Init.EOCSelection != EOC_SINGLE_CONV) ) { /* Wait until End of Conversion flag is raised */ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC)) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } } } else { /* Computation of CPU cycles corresponding to ADC conversion cycles. */ /* Retrieve ADC clock prescaler and ADC maximum conversion cycles on all */ /* channels. */ conversion_timeout_cpu_cycles_max = __ADC_GET_CLOCK_PRESCALER_DECIMAL(hadc); conversion_timeout_cpu_cycles_max *= __ADC_CONVCYCLES_MAX_RANGE(hadc); /* Poll with maximum conversion time */ while(conversion_timeout_cpu_cycles < conversion_timeout_cpu_cycles_max) { /* Check if timeout is disabled (set to infinite wait) */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Update ADC state machine to timeout */ hadc->State = HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } } conversion_timeout_cpu_cycles ++; } } /* Clear end of conversion flag of injected group if low power feature */ /* "Auto Wait" is disabled, to not interfere with this feature until data */ /* register is read using function HAL_ADCEx_InjectedGetValue(). */ if (hadc->Init.LowPowerAutoWait == DISABLE) { /* Clear injected group conversion flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); } /* Update state machine on conversion status if not in error state */ if(hadc->State != HAL_ADC_STATE_ERROR) { /* Update ADC state machine */ if(hadc->State != HAL_ADC_STATE_EOC_INJ_REG) { if(hadc->State == HAL_ADC_STATE_EOC_REG) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_EOC_INJ; } } } /* Return ADC state */ return HAL_OK; }