Fixed-point aritmetik nedir? FPU olmayan bir MCU'da Q15 veya Q16.16 formatında çarpma ve toplama nasıl yapılır?

Cevap

Fixed-point, kesirli sayıları sabit bir ölçek faktörüyle çarpılmış tamsayılar olarak saklamaktır. FPU olmayan MCU'larda (Cortex-M0/M3) float işlemleri yazılımla emüle edilir ve onlarca çevrim sürer; fixed-point ise tamsayı ALU'sunda birkaç çevrimde biter ve deterministiktir.

Q formatı

  • Q15: 16-bit signed, 1 işaret biti + 15 kesir biti. Aralık [-1, 1 - 2^-15]. Değer = tamsayı / 32768.
  • Q16.16: 32-bit signed, 16 tam + 16 kesir biti. Çözünürlük yaklaşık 0.0000153.
#include <stdint.h>

typedef int16_t q15_t;
typedef int32_t q16_16_t;

#define Q15(x)     ((q15_t)((x) * 32768.0f))      /* sadece derleme anı sabitleri için */
#define Q16(x)     ((q16_16_t)((x) * 65536.0f))

/* Toplama: aynı formatta doğrudan toplanır, ama taşmaya dikkat */
static inline q15_t q15_add_sat(q15_t a, q15_t b)
{
    int32_t s = (int32_t)a + b;
    if (s > INT16_MAX) s = INT16_MAX;
    if (s < INT16_MIN) s = INT16_MIN;
    return (q15_t)s;
}

/* Çarpma: sonuç Q30 olur, 15 bit sağa kaydırıp Q15'e döner */
static inline q15_t q15_mul(q15_t a, q15_t b)
{
    int32_t p = (int32_t)a * b;      /* önce genişlet */
    p += 1 << 14;                    /* yuvarlama */
    p >>= 15;
    if (p > INT16_MAX) p = INT16_MAX;  /* -1 * -1 = +1 temsil edilemez */
    return (q15_t)p;
}

static inline q16_16_t q16_mul(q16_16_t a, q16_16_t b)
{
    return (q16_16_t)(((int64_t)a * b) >> 16);
}

static inline q16_16_t q16_div(q16_16_t a, q16_16_t b)
{
    return (q16_16_t)(((int64_t)a << 16) / b);
}

Kritik noktalar

  • Çarpımdan önce daha geniş tipe cast edilmezse ara sonuç taşar.
  • -1.0 * -1.0 Q15'te +1.0 olur ve temsil edilemez; doyurma (saturation) gerekir.
  • Signed sayıyı sağa kaydırma implementation-defined'dır (pratikte aritmetik kaydırma).
  • Hassasiyet ile aralık arasında seçim yapılır: ADC verisi için Q15, PID kontrol için Q16.16 yaygındır.

Cortex-M4/M7'de DSP talimatları (SSAT, SMLAD, QADD) ve CMSIS-DSP'nin arm_mult_q15 gibi fonksiyonları bu işlemleri tek çevrimde yapar. Ama Cortex-M4F/M7'de tek hassasiyetli FPU varsa float kullanmak çoğu zaman daha okunur ve yeterince hızlıdır; double ise yine yazılım emülasyonudur.

  1. C dilinde volatile anahtar kelimesi ne işe yarar?OrtaC ProgramlamaEmbedded
  2. Bir yazmaçtaki belirli bir biti set, clear ve toggle eden C kodunu yazın.KolayC ProgramlamaEmbedded
  3. Stack ile heap arasındaki fark nedir? Gömülü sistemlerde dinamik bellek kullanımından neden kaçınılır?OrtaC ProgramlamaEmbedded
  4. Endianness nedir? Little-endian ile big-endian farkı nedir?KolayC ProgramlamaEmbedded
  5. Bit field nedir? Donanım register'larına erişimde bit field mi yoksa bit maskesi mi kullanılmalı?OrtaC ProgramlamaEmbedded
  6. Fonksiyon pointer'ları ve callback tabloları gömülü sistemlerde nasıl kullanılır? Bir state machine örneği verin.OrtaC ProgramlamaEmbedded

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle