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.0Q15'te+1.0olur 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.
İlgili C Programlama soruları
- C dilinde volatile anahtar kelimesi ne işe yarar?
- Bir yazmaçtaki belirli bir biti set, clear ve toggle eden C kodunu yazın.
- Stack ile heap arasındaki fark nedir? Gömülü sistemlerde dinamik bellek kullanımından neden kaçınılır?
- Endianness nedir? Little-endian ile big-endian farkı nedir?
- Bit field nedir? Donanım register'larına erişimde bit field mi yoksa bit maskesi mi kullanılmalı?
- Fonksiyon pointer'ları ve callback tabloları gömülü sistemlerde nasıl kullanılır? Bir state machine örneği verin.
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.