STM32F103 Output Compare Modları

Başlatan Tagli, 17 Haziran 2017, 17:45:54

Tagli

Amacım STM32F103 ile bir çeşit frekans bölücü yapmak ve bunun için TIM2 (veya TIM3) output compare modülünü kullanıyorum. CH1'den gelen bir sinyal ile TI1F_ED üzerinden timer'a clock veriyorum ve CCR2 eşleşmesi durumunda da OC2 (CH2) kanalını toggle yaparak çıkış üretiyorum. TIMx_CCMR1 register'ı altındaki OCxM ayarları hakkında kafam karıştı. Bunu toggle (011) modunda kullanırsam istediğim sonuca yaklaşıyorum, ancak giriş frekansı 2'nin katlarına bölünebiliyor sadece. Yani CCR2 5 ise mesela, frekans 10'a bölünmüş oluyor ki bu beklenen - ama istemediğim - bir durum.

Sorum şu: Diğer OCxM seçeneklerinde örneğin 001 için
Alıntı YapSet channel 1 to active level on match. OC1REF signal is forced high when the counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
demiş. Buradaki "forced" ne anlama geliyor? Forced olmadığı zaman bacağın durumu ne olacak? İlgili GPIO'nun ODR'sine mi bakıyor? Eşitlik olmadığında (yani CTR = CCR olmazsa) bu "forced" durumu ortadan kalkıyor mu? Yani ben daha sonradan bu bacağı bir şekilde 0 yapabiliyor muyum yazılım ile yoksa eşitlik kalktığında kendiliğinden mi 0 oluyor? (veya ODR ne ise o mu oluyor?). Yoksa "forced" demek ODR'yi de uygun şekilde değiştirdiği anlamına mı geliyor?

Eğer eşitlik ortadan kalktıktan sonra da 1 kalıyorsa ancak ben bunu istediğim zaman 0'a çekebiliyorsam bir şekilde o zaman istediğime ulaşabilmiş olacağım. Örneğin bir süre bekleyip ODR'ye 0 yazmak işe yarar mı?
Gökçe Tağlıoğlu

Tagli

İtiraf etmeliyim ki, belki bir bilen vardır diye kendim deneme yapmadan kolay yoldan cevaba ulaşırım diye soruyu sormuştum. Ancak anlaşılan o ki biraz kazık sormuşum...

Neyse, bir miktar denemeden sonra yanıtı buldum. ODR'yi tamamen unutun bir kere. Aslında akla yatkın olanı da bu, sonuçta AF (alternative function) etkin iken ODR'nin çıkışa bir etkisinin olmaması gerekir. Peki o zaman çıkışı nasıl sıfırlayacağız? Cevap yine aynı ayarda, OCxM bitlerini 0b100 (force inactive) yapmalıyız. Ama biz comparator match olduğunda çıkış tekrar otomatik olarak 1 olsun istiyoruz, böyle bırakırsak hep 0 kalır. Yapmamız gereken şey yine eski ayara geri dönmek ve bu bitleri tekrar 0b001 yapmak.

Bunları alıp kesme koduna koyarsak (ARR ve CCR2'yi eşit yapıyorum, compare'den 1 pulse sonra sayaç da sıfırlanıp kesme üretiyor):
void TIM2_IRQHandler(void) {
	TIM2->CCMR1 &= ~TIM_CCMR1_OC2M;
	TIM2->CCMR1 |= (0b100 << TIM_CCMR1_OC2M_Pos); // Reset PA1
	TIM2->CCMR1 &= ~TIM_CCMR1_OC2M;
	TIM2->CCMR1 |= (0b001 << TIM_CCMR1_OC2M_Pos); // Output compare force 1 on match
	TIM2->SR = 0; // Reset UIF (and others too)
}


Bu arada her nasılsa uzunca bir süre gözümden kaçan bir hatamı fark ettim. Eski yöntemimde zaten frekans tüm tamsayılara bölünüyormuş, yani 2'nin katları diye bir durum söz konusu değilmiş. Anlaşılan, TIMx_CHx girişlerindeki "Input Filter & Edge Detector" bloğu hem yükselen hem düşen kenara duyarlı. Şu anda yeni yöntemim ile frekansı buçuklu değerlere de bölebiliyorum 2, 2.5, 3, 3.5 gibi.
Gökçe Tağlıoğlu