📊 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
| Resolution | Levels | Step (3.3V) | Conversion Time |
|---|---|---|---|
| 6-bit | 64 | 51.6 mV | ~1 µs |
| 8-bit | 256 | 12.9 mV | ~1.5 µs |
| 10-bit | 1024 | 3.2 mV | ~2 µs |
| 12-bit | 4096 | 0.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 configurationhal::dma- DMA transfers for multi-channelhal::timer- External trigger sourcehal::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