HAL kullanarak STM32 ADC dönüşümü


10

Ben stm32 "yeni" HAL kütüphanesi kullanmayı öğrenmek için çalışıyorum.
Basit ADC dönüşümü yapmaya çalıştığımda sadece bir kez çalışıyor, ama sonra dönüşmeyi durduruyor. Sanırım dönüşüm sonu bayrağı ayarlanmadı. Gemide STM32f429ZI olan STM32f429I Keşif panosunu kullanıyorum.
Sprintf'in kötü uygulama olduğunu biliyorum ve kesinti ile adc yapmak daha iyi, biliyorum, lütfen işaret etmeyin, bu soru ile ilgili değil, sadece HAL'ı burada test ediyorum.
Soru şu: EOC bayrağı neden ayarlanmadı ya da çalışması için ne yapabilirim? Google'da HAL hakkında çok az iyi malzeme olduğu için googling çok yardımcı olmuyor.

İşte kod:

__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);
}

Ayrıca CubeMX ile proje oluşturdum, adc yapılandırma aşağıdaki gibidir: resim açıklamasını buraya girin

EDIT 1
Her şeyi hata ayıklamaya çalıştım ve program EOC bayrağı için kontrol sıkışmış gibi görünüyor - gösterilmiyor ve bu nedenle EOC görünmesini bekleyen zamanlayıcı sorunları (ama asla ayarlanmıyor) İşte burada kodu hata ayıklayıcıda takılı kalıyor:

/* 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;
      }
    }

Yanıtlar:


6

Orijinal kodunuzda, Dönüşüm Sonu Seçimi'ni devre dışı olarak ayarlayın.

 hadc1.Init.EOCSelection = DISABLE;

#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)Değerin eşit olduğu ortaya çıktı DISABLE. Yani aslında EOCSelection şu şekilde yapılandırılmalıdır: ADC'yi birden çok kez yoklayabilmek için.resim açıklamasını buraya girin

Ardından ADC'yi durdurmadan ve başlatmadan ADC'yi sürekli olarak okuyabilirsiniz:

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);
        }
    }
}

Bu şekilde benim için iyi çalıştı.

HAL oldukça yeni bir kütüphane olduğu için bulunacak çok fazla kaynak yok ama imkansız değil. Bu öğreticiden çok şey öğrendim , tüm ADC kullanımını adım adım gösterir; basit yoklamadan kesmelere ve DMA kullanımına kadar.


hm ... EOCSelection'ın devre dışı bırakılması çalışmasını sağlar, ancak tanımından şunu söyler - EOC bayrağının tek kanal dönüşümünün sonunda mı yoksa tüm dönüşümlerin sonunda mı ayarlandığını belirtir. Bunu devre dışı bırakmak tanım gereği yardımcı olmamalı .. ama yardımcı olur ... kafa karıştırıcı. Bunun tam olarak devre dışı bırakılmasının neden işe yaradığını biliyor musunuz? Yine de cevap için teşekkürler
ScienceSamovar

Ben de HAL öğreniyorum, bu yüzden nedenini henüz bilmiyorum. Bu sadece bir deneyim. HAL'ın birçok kez toplanabileceğini buldum.
Bence Kaulics

#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)Tanımlama değerlerini kontrol ettim ve devre dışı olanla aynı, yani devre dışı aslında ADC_EOC_SEQ_CONV.
Bence Kaulics

1
oh, tamam, yani tam anlamıyla devre dışı değil. Mantıklı, daha önce ADC_EOC_SINGLE_CONV idi, bu muhtemelen sadece - bir kez dönüştürür ve ADC_EOC_SEQ_CONV sürekli dönüşümdür. Bir gizem daha çözüldü :) Teşekkürler!
ScienceSamovar

Evet, durum böyle olmalı. :)
Bence Kaulics

2

Hm ... Dönüştürmeyi bitirmek için HAL_ADC_Stop (& hadc1) kullanılan birkaç öğretici buldum ... Daha önce bu öğreticilere bakıyordum ve bunun oldukça barbar bir yol olduğunu düşündüm, ADC'yi tamamen devre dışı bıraktığı görünüyor, bu yüzden farklı yöntem. Ama öyle görünüyor ki, bu gerçekten iyi çalışıyor.
HAL_ADC_Stop () kullanmanın oldukça korkunç olduğunu, ancak öğrenme amaçları için kullanılabileceğini düşündüğümden, bunu yapmanın daha zarif bir yolu varsa, yanıt gönderebilirsiniz.

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

  }

Merhaba, bu yöntemle ilgili bir sorun buldum, A LOT ile elde edebileceğiniz maksimum örnek hızını kısıtlıyor, hızlı ADC dönüşümlerine ihtiyacınız varsa bu yöntemi kullanmanız önerilmez.
Richard Bamford

2

Bunu benim kurulum (nucleo-h743) ayarlamak için yeterli olmadığını eklemek istiyorum:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

Ayrıca taşma ayarını da etkinleştirmem gerekiyordu:

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

Bu olmadan HAL_ADC_PollForConversion hala engelliyordu. Bunun neden gerekli olduğunu tam olarak anlamıyorum ama sürekli modda anket yapmama izin veriyor.


0

Bu benim için çalışıyor, umarım yardımcı olur:

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.