Arm 如何在STM32 MCU中每通道每n秒读取几个ADC接口?

Arm 如何在STM32 MCU中每通道每n秒读取几个ADC接口?,arm,adc,stm32f0,Arm,Adc,Stm32f0,我使用STM32F0微控制器的ADC通道(12位分辨率)读取电路板三个不同点的电压值。我想做的是每2秒读取一次值(我有2秒的时间读取三个点中的值),然后通过UART接口发送它们。为了选择我正在读取的ADC通道,我实现了如下电压读取功能: uint16_t readv1(void){ //Here I try to read ADC_CHANNEL_1 //chConfig and txtbuff are global variables: //ADC_ChannelCon

我使用STM32F0微控制器的ADC通道(12位分辨率)读取电路板三个不同点的电压值。我想做的是每2秒读取一次值(我有2秒的时间读取三个点中的值),然后通过UART接口发送它们。为了选择我正在读取的ADC通道,我实现了如下电压读取功能:

uint16_t readv1(void){
    //Here I try to read ADC_CHANNEL_1
    //chConfig and txtbuff are global variables:
    //ADC_ChannelConfTypeDef chConfig;
    //char txtbuff[64];

    chConfig.Channel = ADC_CHANNEL_1;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    uint32_t vref = HAL_ADC_GetValue(&hadc);
    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);

    return vref2;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if (htim->Instance==TIM3){
        //Here I call the functions which read the voltage values of different ADC channels
        volt1 = readv1();
        readv2(volt1);
        readv3(volt1);
    }
}
uint16_t readv1(void){
    chConfig.Channel = ADC_CHANNEL_1;

    // I added these two lines after the ADC channel selection
    chConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    chConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    // The first one will configure the ADC channel as enabled
    // The second one is the sampling time (1.5)

    HAL_ADC_ConfigChannel(&hadc, &chConfig);

    // Then I added these two instructions:
    HAL_ADC_Start_IT(&hadc);
    HAL_ADCEx_Calibration_Start(&hadc);
    // The first one starts the ADC in interruption mode
    // The second one calls the calibration function

    uint32_t vref = HAL_ADC_GetValue(&hadc);

    // Finally I added these three last instructions:
    HAL_ADC_Stop_IT(&hadc);
    chConfig.Rank = ADC_RANK_NONE;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    // The first one stops the ADC
    // The second one will configure the ADC channel as disabled
    // The third one sets the channel with the new parameters

    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);    

    return vref2;
}
这是扫描一个ADC通道的功能。对于读取其他两个ADC通道,我使用相同的程序,只是更改行
chConfig.Channel=ADC\u Channel\n中
n
的值其中
n
是频道号。请注意,
chConfig
MX\u ADC\u Init()
函数中声明的
sConfig
类型相同,但
chConfig
是全局变量,是否应在每个函数中声明为局部变量

我遇到的问题是,
readv1
函数读取恒定电压(我用电压计检查过),但终端通过UART显示的数字变化很大,在120和2400之间。我不确定是否使用行
chConfig.Channel=ADC\u Channel\u 1是好的,或者是否有任何其他步骤要遵循。如何正确读取每个ADC的值

为了每两秒钟扫描一次ADC,我使用了一个8 MHz定时器,如下所示:

uint16_t readv1(void){
    //Here I try to read ADC_CHANNEL_1
    //chConfig and txtbuff are global variables:
    //ADC_ChannelConfTypeDef chConfig;
    //char txtbuff[64];

    chConfig.Channel = ADC_CHANNEL_1;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    uint32_t vref = HAL_ADC_GetValue(&hadc);
    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);

    return vref2;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if (htim->Instance==TIM3){
        //Here I call the functions which read the voltage values of different ADC channels
        volt1 = readv1();
        readv2(volt1);
        readv3(volt1);
    }
}
uint16_t readv1(void){
    chConfig.Channel = ADC_CHANNEL_1;

    // I added these two lines after the ADC channel selection
    chConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    chConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    // The first one will configure the ADC channel as enabled
    // The second one is the sampling time (1.5)

    HAL_ADC_ConfigChannel(&hadc, &chConfig);

    // Then I added these two instructions:
    HAL_ADC_Start_IT(&hadc);
    HAL_ADCEx_Calibration_Start(&hadc);
    // The first one starts the ADC in interruption mode
    // The second one calls the calibration function

    uint32_t vref = HAL_ADC_GetValue(&hadc);

    // Finally I added these three last instructions:
    HAL_ADC_Stop_IT(&hadc);
    chConfig.Rank = ADC_RANK_NONE;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    // The first one stops the ADC
    // The second one will configure the ADC channel as disabled
    // The third one sets the channel with the new parameters

    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);    

    return vref2;
}
这是我初始化外围设备的主要功能:

int main(void)
{

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART4_UART_Init();
  MX_ADC_Init();
  MX_TIM3_Init();

  /* USER CODE BEGIN 2 */
  HAL_ADC_Start_IT(&hadc);
  HAL_TIM_Base_Start_IT(&htim3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  }
}
以下是定时器和ADC的初始化功能:

/* TIM3 init function */
static void MX_TIM3_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 8000;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 1999;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}


/* ADC init function */
static void MX_ADC_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  hadc.Init.ContinuousConvMode = ENABLE;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.DMAContinuousRequests = DISABLE;
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_1;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_2;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_4;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

我通过修改函数解决了这个问题,如下所示:

uint16_t readv1(void){
    //Here I try to read ADC_CHANNEL_1
    //chConfig and txtbuff are global variables:
    //ADC_ChannelConfTypeDef chConfig;
    //char txtbuff[64];

    chConfig.Channel = ADC_CHANNEL_1;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    uint32_t vref = HAL_ADC_GetValue(&hadc);
    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);

    return vref2;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if (htim->Instance==TIM3){
        //Here I call the functions which read the voltage values of different ADC channels
        volt1 = readv1();
        readv2(volt1);
        readv3(volt1);
    }
}
uint16_t readv1(void){
    chConfig.Channel = ADC_CHANNEL_1;

    // I added these two lines after the ADC channel selection
    chConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    chConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    // The first one will configure the ADC channel as enabled
    // The second one is the sampling time (1.5)

    HAL_ADC_ConfigChannel(&hadc, &chConfig);

    // Then I added these two instructions:
    HAL_ADC_Start_IT(&hadc);
    HAL_ADCEx_Calibration_Start(&hadc);
    // The first one starts the ADC in interruption mode
    // The second one calls the calibration function

    uint32_t vref = HAL_ADC_GetValue(&hadc);

    // Finally I added these three last instructions:
    HAL_ADC_Stop_IT(&hadc);
    chConfig.Rank = ADC_RANK_NONE;
    HAL_ADC_ConfigChannel(&hadc, &chConfig);
    // The first one stops the ADC
    // The second one will configure the ADC channel as disabled
    // The third one sets the channel with the new parameters

    uint16_t vref2 = (uint16_t) vref;
    sprintf(TextBuffer, "%u\n", vref2);
    HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);    

    return vref2;
}
我添加了我在读取ADC通道的三个函数中提到的行。实际上,当我使用相同的程序读取所有ADC通道时,我创建了一个函数,该函数接收通道号作为参数。

volt1=readv1();readv2(volt1);readv3(volt1);为什么raeadv2()和readv3()接受参数volt1,而readv1()不接受?您说过“对于读取其他两个ADC通道,我使用相同的过程,只是更改行chConfig.Channel=ADC\u Channel\n;中的n是通道号。”尝试为volt1变量添加“volatile”。