Ich stehe vor einem Problem bezüglich der kontinuierlichen Erfassung des ADC-Kanals in STM32F103.
Ich verwende den Interrupt am Ende der Konvertierung, um eine Callback-Funktion aufzurufen, um den erfassten Wert zu speichern.
Das Problem betrifft den Callback, der nur beim ersten Mal aufgerufen wird.
Ich habe mein Projekt mit STM32CubeMx für kontinuierliche Erfassung und Interrupt-Generierung konfiguriert.
Dies ist die ADC-Konfiguration:
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/**Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Dies ist meine Akquisitionsfunktion:
ea_ADC_Err_Code_t ea_ADC_n_data_read(Adc_Channel_t channel, adc_eoc_callback adc_cb)
{
ea_ADC_Err_Code_t err_code = ADC_ERR;
ADC_ChannelConfTypeDef sConfig;
adc_read_value = 0;
adc_eoc_cb = adc_cb;
n_adc_acquisition = ADC_MAX_CONS_ACQ;
/* Deinit ADC */
//while(HAL_ADC_DeInit(&adc_handler) != HAL_OK);
/* Initialize ADC */
//HAL_ADC_Init(&adc_handler);
/* Configure ADC Channel */
sConfig.Channel = channel;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&adc_handler, &sConfig);
/* Set ADC callback */
HAL_ADC_ConvCpltCallback(&adc_handler);
/* ADC Calibration */
//HAL_ADCEx_Calibration_Start(&adc_handler);
/* Start conversion with interrupt*/
if (HAL_ADC_Start_IT(&adc_handler) == HAL_OK)
{
err_code = ADC_OK;
}
return err_code;
}
Und zum Schluss mein Rückruf:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (n_adc_acquisition)
{
adc_read_value += HAL_ADC_GetValue(&adc_handler);
n_adc_acquisition--;
edi_Print_L1("ADC Callback %d\n", n_adc_acquisition);
}
else
{
HAL_ADC_Stop_IT(&adc_handler);
adc_read_value = adc_read_value >> ADC_DIVIDE_BY_EIGTH;
adc_eoc_cb(adc_read_value);
}
}
Habe ich beim Rückruf etwas vergessen?
Sie haben vergessen, die ADC-Interrupts zu aktivieren, was ungefähr so gemacht werden kann:
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
Das nächste Problem bei der Interrupt-Behandlung von HAL ist, dass es zwei schwache Funktionsdeklarationen gibt.
void ADC_IRQHandler()
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
Sie müssen den ADC_IRQHandler()
ersten implementieren, dieser wird aufgerufen, wenn ein Interrupt vom ADC generiert wird. Innerhalb dieser Funktion müssen Sie den aufrufen HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
, Parameter ist der Handler Ihres ADC ( ADC_HandleTypeDef
).
void ADC_IRQHandler()
{
HAL_ADC_IRQHandler(&hadc1);
//HAL_ADC_IRQHandler(&hadc2); <--- In case of a second ADC
}
Jetzt HAL_ADC_IRQHandler()
wird jede Art von Fehler für Sie überprüft (Sie können dies in seiner Implementierung überprüfen) und wenn alles in Ordnung ist, wird die void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
. Da es auch eine schwache Deklaration hat, müssen Sie die Funktion implementieren.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
int converted_value = HAL_ADC_GetValue(hadc);
// Do stuff
}
//if(hadc->Instance == ADC2) // <-- In case of a second ADC
//{
//
//}
}
In STM32CubeMX gibt es im ADC1-Konfigurationsfenster eine Registerkarte namens NVIC-Einstellungen . Hier können Sie die globalen Interrupts für ADC1 und ADC2 aktivieren, und wenn Sie dies tun, implementiert STM32Cube die void ADC_IRQHandler(void)
in der Datei stm32f1xx_it.c .
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles ADC1 and ADC2 global interrupts.
*/
void ADC_IRQHandler(void)
{
/* USER CODE BEGIN ADC_IRQn 0 */
/* USER CODE END ADC_IRQn 0 */
HAL_ADC_IRQHandler(&hadc1);
/* USER CODE BEGIN ADC_IRQn 1 */
/* USER CODE END ADC_IRQn 1 */
}
Außerdem ist es nur eine kurze Zusammenfassung, also schlage ich vor, das Tutorial durchzulesen , das @Eugene Sh dir gezeigt hat.
Eugen Sch.
Federico
Eugen Sch.
Eugen Sch.
HAL_ADC_ConvCpltCallback
damit Sie sehen, dass sie aufgerufen wird.Marko Buršič
Federico
Eugen Sch.
Marko Buršič
Eugen Sch.
Federico
Eugen Sch.
Federico
Eugen Sch.
HAL_ADC_ConvCpltCallback(&adc_handler);
Diese Zeile ruft die Funktion auf.Eugen Sch.
main
, da der Ablauf unklar ist.Federico
Eugen Sch.