HAL을 사용한 STM32 ADC 변환


10

stm32에서 "new"HAL 라이브러리를 사용하는 방법을 배우려고합니다.
간단한 ADC 변환을 시도하면 한 번만 작동하지만 변환이 중지됩니다. 전환 종료 플래그가 설정되지 않았다고 가정합니다. STM32f429ZI가 탑재 된 STM32f429I 디스커버리 보드를 사용하고 있습니다.
나는 sprintf가 나쁜 습관이고 인터럽트로 adc를 만드는 것이 더 낫다는 것을 알고 있습니다. 지적하지 마십시오.이 질문과 관련이 없으며 HAL을 테스트하고 있습니다.
따라서 EOC 플래그가 설정되지 않은 이유 또는 작동시키기 위해 어떻게해야합니까? 인터넷 검색은 HAL에 대한 좋은 자료가 거의 없기 때문에 크게 도움이되지 않습니다.

코드는 다음과 같습니다.

__IO uint16_t ADCValue=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

int main(void)
{
  char str[15];

  /* Various initializations */

  HAL_ADC_Start(&hadc1);
  while (1)
  {

        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
            sprintf(str, "%d", ADCValue);
            BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }

  }

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADCValue = HAL_ADC_GetValue(&hadc1);
}

또한 CubeMX로 프로젝트를 만들었습니다. adc 구성은 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

편집 1
모든 것을 디버깅하려고 시도했지만 프로그램이 EOC 플래그를 확인하는 데 걸리는 것처럼 보입니다. 표시되지 않았으므로 EOC가 표시되기를 기다리는 타이머를 발행합니다 (그러나 결코 설정되지 않음) 여기에 코드가 있습니다 디버거에 갇히게됩니다.

/* Check End of conversion flag */
  while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)))
  {
    /* 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;
      }
    }

답변:


6

원래 코드에서 변환 끝 선택을 사용 안함으로 설정하십시오.

 hadc1.Init.EOCSelection = DISABLE;

#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)값은 같다는 것이 밝혀졌습니다 DISABLE. 따라서 실제로 EOCSelection은 ADC를 여러 번 폴링 할 수 있도록 다음과 같이 구성해야합니다 .여기에 이미지 설명을 입력하십시오

그런 다음 ADC를 중지하거나 시작하지 않고도 ADC를 계속 읽을 수 있습니다.

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    ConfigureADC();

    HAL_ADC_Start(&hadc1);
    while(1)
    {
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
        }
    }
}

이런 식으로 그것은 나를 위해 잘 작동했습니다.

HAL은 매우 새로운 라이브러리이기 때문에 찾을 리소스가 많지 않지만 불가능하지는 않습니다. 이 튜토리얼 에서 많은 것을 배웠습니다. 가능한 모든 ADC 사용을 단계별로 보여줍니다. 간단한 폴링에서 인터럽트 및 DMA 사용까지.


hm ... EOCSelection을 비활성화하면 작동하지만 해당 정의에서-EOC 플래그가 단일 채널 변환의 끝 또는 모든 변환의 끝에서 설정되는지 여부를 지정합니다. 이 기능을 비활성화하면 정의에 의해 도움이되지는 않지만 혼란에 도움이됩니다. 이것을 정확히 비활성화하면 작동하는 이유를 알고 있습니까? 어쨌든 대답 주셔서 감사합니다
ScienceSamovar

나는 단지 HAL도 배우고 있으므로 아직 이유를 모릅니다. 단지 경험 일뿐입니다. 나는 HAL이 여러 번 혼란 스러울 수 있다는 것을 알았습니다.
Bence Kaulics

정의 값을 확인했으며 #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)비활성화 된 것과 동일한 것이므로 비활성화 된 것은 실제로 ADC_EOC_SEQ_CONV입니다.
Bence Kaulics

1
오, 그래, 문자 그대로 비활성화되어 있지 않습니다. 이전에는 ADC_EOC_SINGLE_CONV였습니다. 아마도 한 번만 변환하고 ADC_EOC_SEQ_CONV는 연속 변환입니다. 하나 더 미스터리 해결 :) 감사합니다!
ScienceSamovar

그렇습니다. :)
Bence Kaulics

2

흠 ... 변환을 끝내기 위해 HAL_ADC_Stop (& hadc1)을 사용한 몇 가지 자습서를 발견했습니다 ...이 자습서를보고 있었고이 방법이 다소 야만적이라고 생각했습니다. ADC가 완전히 비활성화 된 것 같습니다. 다른 방법. 그러나 이것이 실제로 잘 작동하는 것 같습니다.
HAL_ADC_Stop ()을 사용하는 것이 꽤 끔찍하지만 학습 목적으로 사용될 수 있다고 생각하기 때문에 더 우아한 방법이 있다면 답변을 게시하십시오.

while (1)
  {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
                        sprintf(str, "%d", ADCValue);
                        BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }
        HAL_ADC_Stop(&hadc1);

  }

안녕, 나는이 방법에 대한 문제를 발견, 그것은 당신이 많이 얻을 수있는 최대 샘플 속도를 제한, 빠른 ADC 변환이 필요한 경우이 방법을 사용하지 않는 것이 좋습니다.
Richard Bamford

2

내 설정 (nucleo-h743)에 대해 설정하고 싶지 않았습니다.

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

오버런 설정도 활성화해야했습니다.

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

이것이 없으면 HAL_ADC_PollForConversion이 여전히 차단되었습니다. 이것이 왜 필요한지 완전히 이해하지 못하지만 연속 모드로 폴링 할 수 있습니다.


0

이것은 나를 위해 일합니다. 도움이되기를 바랍니다.

if (HAL_ADC_Start(&hadc) != HAL_OK)
{
    /* Start Conversation Error */
    // Error_Handler();
}
if (HAL_ADC_PollForConversion(&hadc, 500) != HAL_OK)
{
    /* End Of Conversion flag not set on time */
    // Error_Handler();
    ADCValue=-1;
}
else
{
    /* ADC conversion completed */
    /*##-5- Get the converted value of regular channel ########################*/
    ADCValue = HAL_ADC_GetValue(&hadc);
}
HAL_ADC_Stop(&hadc);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.