HALを使用したSTM32 ADC変換


10

stm32から「新しい」HALライブラリを使用する方法を学習しようとしています。
単純なADC変換を行おうとすると、1回だけ機能しますが、変換が停止します。変換終了フラグが設定されていないと思います。STM32f429I Discoveryボードを使用していますが、これにはボードにSTM32f429ZIが搭載されています。
私は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 2015年

私もHALを学んでいるだけなので、その理由はまだわかりません。ただの体験です。私は、HALが何度も気になっていることに気づきました。
Bence Kaulics、2015年

私は定義値をチェックしましたが、#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)これは無効と同じなので、無効は実際にはADC_EOC_SEQ_CONVです。
Bence Kaulics、2015年

1
ああ、わかりました。文字通り無効にされていません。これは理にかなっています。以前はADC_EOC_SINGLE_CONVでしたが、これはおそらくそれだけを意味します。変換は1回だけで、ADC_EOC_SEQ_CONVは連続変換です。もう1つの謎が解けました:)ありがとう!
ScienceSamovar 2015年

はい、そうです。:)
Bence Kaulics

2

Hm ... 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);

  }

こんにちは、私はこの方法で問題を見つけました、それはあなたがA LOTによって達成できる最大サンプルレートを制限します、迅速な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.