Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

📊 hal::adc

Analog-to-Digital Converter - Analog Sinyal Dönüşümü

400 satır ~25 fonksiyon 12-bit ADC

📖 Genel Bakış

ADC (Analog-to-Digital Converter) modülü, analog sinyalleri dijital değerlere dönüştürür. Sensör okuma, sıcaklık ölçümü, batarya voltajı kontrolü gibi uygulamalarda kullanılır.

🔑 Temel Özellikler

  • 6-16 bit resolution (device dependent)
  • Multiple ADC channels (up to 19)
  • Single/continuous conversion
  • DMA support
  • Internal temperature sensor
  • Internal voltage reference
  • Analog watchdog
  • Configurable sampling time

🚀 Hızlı Başlangıç

içe_aktar hal::adc, hal::gpio

// ADC initialization
adc.clock_enable()
değişken adc1 = adc.init(adc.ADC1, yap
    resolution: adc.RESOLUTION_12BIT,
    align: adc.ALIGN_RIGHT
son)

// GPIO setup for analog input
değişken ain = gpio.pin_init(gpio.PORT_A, 0, yap
    mode: gpio.MODE_ANALOG,
    pull: gpio.PULL_NONE
son)

// Configure channel
adc.channel_config(adc1, adc.CHANNEL_0, yap
    sampling_time: adc.SAMPLETIME_480CYCLES
son)

// Read value
adc.start(adc1)
değişken value = adc.read(adc1)
io.println("ADC: " + value.yazıya())

💡 Örnek 1: Temperature Sensor

içe_aktar hal::adc, hal::gpio, hal::core

fonksiyon sıcaklık_oku() -> kesir yap
    // ADC setup
    adc.clock_enable()
    değişken adc1 = adc.init(adc.ADC1, yap
        resolution: adc.RESOLUTION_12BIT,
        align: adc.ALIGN_RIGHT
    son)
    
    // GPIO for analog input (PA0)
    gpio.clock_enable(gpio.PORT_A)
    gpio.pin_init(gpio.PORT_A, 0, yap
        mode: gpio.MODE_ANALOG,
        pull: gpio.PULL_NONE
    son)
    
    // Configure channel
    adc.channel_config(adc1, adc.CHANNEL_0, yap
        sampling_time: adc.SAMPLETIME_480CYCLES
    son)
    
    // Read multiple samples and average
    değişken toplam = 0.0
    değişken samples = 10
    
    her i içinde 0..samples için yap
        adc.start(adc1)
        değişken raw = adc.read(adc1)
        toplam += raw.kesir()
        core.delay_ms(10)
    son
    
    değişken ortalama = toplam / samples.kesir()
    
    // Convert to voltage (3.3V reference, 12-bit)
    değişken voltage = ortalama * 3.3 / 4095.0
    
    // LM35 sensor: 10mV/°C
    değişken temp = voltage * 100.0
    
    dön temp
son

fonksiyon ana() yap
    core.system_init()
    core.clock_config(72_000_000)
    
    döngü yap
        değişken temp = sıcaklık_oku()
        io.println("Sıcaklık: {:.1f}°C".formatla(temp))
        core.delay_ms(1000)
    son
son

💡 Örnek 2: Battery Voltage Monitor

içe_aktar hal::adc, hal::gpio

fonksiyon batarya_voltaj_oku() -> kesir yap
    // Voltage divider: Battery -> 10K -> ADC -> 10K -> GND
    // Max input: 6.6V (for 3.3V ADC)
    
    adc.clock_enable()
    değişken adc1 = adc.init(adc.ADC1, yap
        resolution: adc.RESOLUTION_12BIT,
        align: adc.ALIGN_RIGHT
    son)
    
    gpio.clock_enable(gpio.PORT_A)
    gpio.pin_init(gpio.PORT_A, 1, yap
        mode: gpio.MODE_ANALOG,
        pull: gpio.PULL_NONE
    son)
    
    adc.channel_config(adc1, adc.CHANNEL_1, yap
        sampling_time: adc.SAMPLETIME_480CYCLES
    son)
    
    // Read 100 samples for accuracy
    değişken toplam = 0
    her i içinde 0..100 için yap
        adc.start(adc1)
        toplam += adc.read(adc1)
    son
    
    değişken ortalama = toplam / 100
    değişken voltage = (ortalama.kesir() / 4095.0) * 3.3
    
    // Apply voltage divider ratio (2:1)
    değişken battery_voltage = voltage * 2.0
    
    dön battery_voltage
son

fonksiyon batarya_durumu(voltage: kesir) -> yazı yap
    eğer voltage > 4.1 ise dön "Tam"
    yoksa eğer voltage > 3.7 ise dön "İyi"
    yoksa eğer voltage > 3.5 ise dön "Orta"
    yoksa dön "Düşük"
son

fonksiyon ana() yap
    core.system_init()
    
    döngü yap
        değişken v = batarya_voltaj_oku()
        değişken durum = batarya_durumu(v)
        io.println("Batarya: {:.2f}V [{}]".formatla(v, durum))
        core.delay_ms(5000)
    son
son

💡 Örnek 3: Multi-Channel ADC with DMA

içe_aktar hal::adc, hal::dma, hal::gpio

sabit CHANNELS = 4

fonksiyon adc_dma_init() -> adc.Handle yap
    // GPIO setup for 4 analog inputs (PA0-PA3)
    gpio.clock_enable(gpio.PORT_A)
    her i içinde 0..CHANNELS için yap
        gpio.pin_init(gpio.PORT_A, i, yap
            mode: gpio.MODE_ANALOG,
            pull: gpio.PULL_NONE
        son)
    son
    
    // ADC setup
    adc.clock_enable()
    değişken adc1 = adc.init(adc.ADC1, yap
        resolution: adc.RESOLUTION_12BIT,
        align: adc.ALIGN_RIGHT,
        scan_mode: doğru,
        continuous: doğru
    son)
    
    // Configure channels
    adc.channel_config(adc1, adc.CHANNEL_0, yap rank: 1 son)
    adc.channel_config(adc1, adc.CHANNEL_1, yap rank: 2 son)
    adc.channel_config(adc1, adc.CHANNEL_2, yap rank: 3 son)
    adc.channel_config(adc1, adc.CHANNEL_3, yap rank: 4 son)
    
    dön adc1
son

değişken adc_buffer: [sayı; CHANNELS] = [0, 0, 0, 0]

fonksiyon ana() yap
    core.system_init()
    değişken adc1 = adc_dma_init()
    
    // DMA setup for continuous ADC transfer
    dma.clock_enable()
    değişken dma_ch = dma.init(dma.DMA1_CH1, yap
        direction: dma.PERIPH_TO_MEMORY,
        periph_addr: adc.data_register(adc1),
        memory_addr: adc_buffer.adres(),
        buffer_size: CHANNELS,
        periph_inc: yanlış,
        memory_inc: doğru,
        periph_size: dma.SIZE_16BIT,
        memory_size: dma.SIZE_16BIT,
        circular: doğru,
        priority: dma.PRIORITY_HIGH
    son)
    
    // Start DMA and ADC
    dma.start(dma_ch)
    adc.start_dma(adc1)
    
    // Main loop - data is automatically updated by DMA
    döngü yap
        io.println("Kanal 0: {}  Kanal 1: {}  Kanal 2: {}  Kanal 3: {}".formatla(
            adc_buffer[0], adc_buffer[1], adc_buffer[2], adc_buffer[3]
        ))
        core.delay_ms(500)
    son
son

💡 Örnek 4: Analog Watchdog (Voltage Monitor)

içe_aktar hal::adc, hal::gpio, hal::int

sabit THRESHOLD_LOW = 1500   // ~1.2V
sabit THRESHOLD_HIGH = 3000  // ~2.4V

değişken alarm_triggered = yanlış

fonksiyon adc_watchdog_handler() yap
    alarm_triggered = doğru
    io.println("⚠️ UYARI: Voltaj threshold dışında!")
son

fonksiyon ana() yap
    core.system_init()
    
    // GPIO setup
    gpio.clock_enable(gpio.PORT_A)
    gpio.pin_init(gpio.PORT_A, 0, yap
        mode: gpio.MODE_ANALOG,
        pull: gpio.PULL_NONE
    son)
    
    // ADC setup
    adc.clock_enable()
    değişken adc1 = adc.init(adc.ADC1, yap
        resolution: adc.RESOLUTION_12BIT,
        align: adc.ALIGN_RIGHT
    son)
    
    adc.channel_config(adc1, adc.CHANNEL_0, yap
        sampling_time: adc.SAMPLETIME_480CYCLES
    son)
    
    // Configure analog watchdog
    adc.watchdog_enable(adc1, yap
        channel: adc.CHANNEL_0,
        low_threshold: THRESHOLD_LOW,
        high_threshold: THRESHOLD_HIGH
    son)
    
    // Enable interrupt
    adc.interrupt_enable(adc1, adc.WATCHDOG_INT)
    int.register_handler(int.ADC1_IRQ, adc_watchdog_handler)
    int.enable_irq(int.ADC1_IRQ)
    
    // Start continuous conversion
    adc.start_continuous(adc1)
    
    döngü yap
        eğer alarm_triggered ise yap
            alarm_triggered = yanlış
            değişken value = adc.read(adc1)
            değişken voltage = (value.kesir() / 4095.0) * 3.3
            io.println("Voltaj: {:.2f}V [ALARM]".formatla(voltage))
        son
        core.delay_ms(100)
    son
son

💡 Örnek 5: Internal Temperature Sensor

içe_aktar hal::adc

fonksiyon cpu_sicaklik_oku() -> kesir yap
    adc.clock_enable()
    değişken adc1 = adc.init(adc.ADC1, yap
        resolution: adc.RESOLUTION_12BIT,
        align: adc.ALIGN_RIGHT
    son)
    
    // Enable internal temperature sensor
    adc.enable_temp_sensor()
    
    // Configure internal channel (usually CH16)
    adc.channel_config(adc1, adc.CHANNEL_TEMP, yap
        sampling_time: adc.SAMPLETIME_480CYCLES  // Long sampling for accuracy
    son)
    
    // Read multiple samples
    değişken toplam = 0
    her i içinde 0..10 için yap
        adc.start(adc1)
        toplam += adc.read(adc1)
        core.delay_ms(5)
    son
    
    değişken ortalama = toplam / 10
    
    // STM32 formula: Temp = (V25 - Vsense) / Avg_Slope + 25
    // Typical: V25 = 1.43V (@ 25°C), Avg_Slope = 4.3mV/°C
    değişken voltage = (ortalama.kesir() / 4095.0) * 3.3
    değişken temp = ((1.43 - voltage) / 0.0043) + 25.0
    
    dön temp
son

fonksiyon ana() yap
    core.system_init()
    
    döngü yap
        değişken temp = cpu_sicaklik_oku()
        io.println("CPU Sıcaklığı: {:.1f}°C".formatla(temp))
        
        // Thermal management
        eğer temp > 80.0 ise yap
            io.println("⚠️ UYARI: Yüksek sıcaklık!")
            // Reduce clock speed or take action
        son
        
        core.delay_ms(2000)
    son
son

📦 Tipler ve Enum'lar

// ADC Instance
enum Instance {
    ADC1, ADC2, ADC3
}

// Resolution
enum Resolution {
    RESOLUTION_6BIT,   // 6-bit (fastest)
    RESOLUTION_8BIT,   // 8-bit
    RESOLUTION_10BIT,  // 10-bit
    RESOLUTION_12BIT   // 12-bit (highest accuracy)
}

// Data Alignment
enum Alignment {
    ALIGN_RIGHT,  // Right-aligned (default)
    ALIGN_LEFT    // Left-aligned
}

// Sampling Time
enum SamplingTime {
    SAMPLETIME_3CYCLES,
    SAMPLETIME_15CYCLES,
    SAMPLETIME_28CYCLES,
    SAMPLETIME_56CYCLES,
    SAMPLETIME_84CYCLES,
    SAMPLETIME_112CYCLES,
    SAMPLETIME_144CYCLES,
    SAMPLETIME_480CYCLES  // Longest (most accurate)
}

// ADC Channels
sabit CHANNEL_0 = 0
sabit CHANNEL_1 = 1
// ... up to CHANNEL_18
sabit CHANNEL_TEMP = 16     // Internal temperature sensor
sabit CHANNEL_VREFINT = 17  // Internal voltage reference
sabit CHANNEL_VBAT = 18     // VBAT/2

yapı Config yap
    resolution: Resolution,
    align: Alignment,
    scan_mode: mantıksal,      // Multi-channel scan
    continuous: mantıksal,      // Continuous conversion
    dma_mode: mantıksal,        // DMA enable
    external_trigger: İsteğe_Bağlı[Trigger]
son

⚙️ Fonksiyonlar

Initialization

fonksiyon clock_enable()
// Enable ADC clock

fonksiyon init(instance: Instance, config: Config) -> Handle
// Initialize ADC with configuration

fonksiyon deinit(handle: Handle)
// Deinitialize ADC

fonksiyon calibrate(handle: Handle) -> Sonuç[Hiçbir, Hata]
// Run ADC calibration (recommended at startup)

Channel Configuration

fonksiyon channel_config(handle: Handle, channel: sayı, config: ChannelConfig)
// Configure ADC channel

yapı ChannelConfig yap
    sampling_time: SamplingTime,
    rank: İsteğe_Bağlı[sayı]  // For scan mode (1-16)
son

Conversion Control

fonksiyon start(handle: Handle)
// Start single conversion

fonksiyon start_continuous(handle: Handle)
// Start continuous conversion

fonksiyon stop(handle: Handle)
// Stop conversion

fonksiyon read(handle: Handle) -> sayı
// Read conversion result (blocking)

fonksiyon read_nonblocking(handle: Handle) -> İsteğe_Bağlı[sayı]
// Read conversion result (non-blocking)

fonksiyon is_conversion_complete(handle: Handle) -> mantıksal
// Check if conversion is complete

DMA Support

fonksiyon start_dma(handle: Handle, buffer: &mut [sayı])
// Start ADC with DMA transfer

fonksiyon stop_dma(handle: Handle)
// Stop DMA transfer

fonksiyon data_register(handle: Handle) -> *const u32
// Get ADC data register address for DMA

Analog Watchdog

fonksiyon watchdog_enable(handle: Handle, config: WatchdogConfig)
// Enable analog watchdog

yapı WatchdogConfig yap
    channel: sayı,
    low_threshold: sayı,
    high_threshold: sayı
son

fonksiyon watchdog_disable(handle: Handle)
// Disable analog watchdog

Internal Sensors

fonksiyon enable_temp_sensor()
// Enable internal temperature sensor

fonksiyon disable_temp_sensor()
// Disable internal temperature sensor

fonksiyon enable_vrefint()
// Enable internal voltage reference

fonksiyon read_vrefint() -> kesir
// Read internal reference voltage (typically 1.2V)

Interrupts

fonksiyon interrupt_enable(handle: Handle, interrupt: Interrupt)
// Enable ADC interrupt

enum Interrupt {
    EOC,        // End of conversion
    JEOC,       // Injected end of conversion
    WATCHDOG,   // Analog watchdog
    OVERRUN     // Overrun
}

fonksiyon interrupt_disable(handle: Handle, interrupt: Interrupt)
// Disable ADC interrupt

⚡ Performans İpuçları

  • Sampling Time: Daha uzun sampling time = daha yüksek hassasiyet, ancak daha yavaş
  • Kalibrasyon: Her açılışta calibrate() çalıştırın
  • Ortalama Alma: Gürültüyü azaltmak için 10-100 sample ortalaması alın
  • DMA Kullanımı: Multi-channel okumada CPU yükünü azaltır
  • Continuous Mode: Yüksek hızlı örnekleme için kullanın
  • Input Impedance: Yüksek empedanslı kaynaklarda sampling time arttırın

⚠️ Önemli Notlar

  • ADC kullanmadan önce clock_enable() çağırın
  • Analog pinler için GPIO MODE_ANALOG kullanın
  • Maximum input voltage: VREF+ (genellikle 3.3V)
  • Input impedance: <50kΩ önerilir
  • Conversion time = sampling time + 12 cycles (12-bit)
  • Internal temperature sensor ±2°C hassasiyet
  • DMA kullanırken circular buffer kullanın
  • Watchdog sadece tek kanal izleyebilir

🔬 Hassasiyet ve Doğruluk

ResolutionLevelsStep (3.3V)Conversion Time
6-bit6451.6 mV~1 µs
8-bit25612.9 mV~1.5 µs
10-bit10243.2 mV~2 µs
12-bit40960.8 mV~3 µs

🎯 Uygulama Senaryoları

  • Sensör Okuma: Sıcaklık, basınç, nem sensörleri
  • Batarya Monitörü: Li-Po/Li-Ion voltage monitoring
  • Ses İşleme: Mikrofon girişi (high-speed sampling)
  • Joystick/Potansiyometre: Analog pozisyon kontrolü
  • Akım Sensörü: INA219/ACS712 gibi sensörler
  • Işık Sensörü: LDR, fotodiode okumaları

📚 Platform Desteği

  • STM32 F1: 12-bit, 2 ADC (72 MHz)
  • STM32 F4: 12-bit, 3 ADC (84 MHz)
  • STM32 F7: 12-bit, 3 ADC (216 MHz)
  • STM32 H7: 16-bit, 3 ADC (400 MHz)
  • ESP32: 12-bit, 2 ADC (240 MHz)
  • GD32VF103: 12-bit, 2 ADC (RISC-V)

🔗 İlgili Modüller

  • hal::gpio - Analog pin configuration
  • hal::dma - DMA transfers for multi-channel
  • hal::timer - External trigger source
  • hal::dac - Digital-to-Analog conversion

📖 Referanslar

  • STM32 RM0008 - Reference Manual (ADC section)
  • AN2834 - How to get the best ADC accuracy
  • AN3116 - STM32 ADC modes and applications

← HAL Modülleri | Tüm Modüller | Ana Sayfa