TIM1 e bağlı olarak tek kanal PWM sinyali üretiyorum. Normalde TIM1 kendi başına belli durumlarda kesme oluşturabiliyor, ancak PWM sinyalinin yükselen veya ve düşen kenarında kesme oluşturmam ve kenar tespiti yapmam gerekiyor.
Datasheet'e göz attım ancak aradığımı tam olarak bulamadım gözden kaçırmışta olabilirim.
Break pinini kullanmadan PWM kenar tespiti yapmak mümkün mü? Mümkün değilse alternatif olarak nasıl bir yöntem önerirsiniz?
Normal Timer kesmesinde olduğu gibi TIM_IT_Update kesmesini açtığınızda oluyor.
PWM duty'sinin yükselen kenarında kesme üretiyor olması lazım.
Evet hocam ARR registerı güncellendiğinde kesme oluşuyor ama bana birde düşen kenarı lazım.
"yükselen veya düşen kenarında" diyince düşen kenara kafa patlatmadım : )
Direk o şekilde aktif edilen bir kanal olmayabilir.
Etrafından dolaş,
Bir timer daha kullan , tüm katsayıları aynı olsun fakat diğer timerın düşen kenarında kesme üretecek şekilde init et onu da.
Timerları aynı anda init et , aynı anda durdur. 1-2 clock farkla elde edersin kesmeyi.
Yada Duty'nin yükselen kenar kesmesinde , yeni bir timer aç , bu timer'ın kesme süresi senin duty süren kadar olsun. Duty sonunda diğer timerdan bir kesme daha üretmiş olursun.
Alıntı yapılan: camby - 26 Ocak 2014, 22:18:13
"yükselen veya düşen kenarında" diyince düşen kenara kafa patlatmadım : )
Hocam yanlış yazmışım sizin yorumunuzdan sonra fark ettim, düzelttim.
Donanımsal olarak tespit edemiyorsam dediğiniz gibi yeni bir timer kurup öğreneceğim. Teşekkürler.
Timer'ı aktif ettikten sonra programın biryerinde pasif yapıyorum. Yani timerı istediğim şekilde açıp kapatmak istiyorum.
Aktif için: TIM_Cmd(TIM2,ENABLE);
Pasif için: TIM_Cmd(TIM2,DISABLE);
Kullanıyorum.
Ancak aktif yaptıktan sonra pasif fonksiyonunu çağırırsam pasif olmuyor timer kesmeleri bozuluyor. Normalde bunun tamamen kapanması gerekmez mi? Yanlış fonksiyonu mu kullanıyorum ?
--
Saat kaynağını kapatıyorum mantıklı olarak Timer duruyor, ama neden sayıcıyı durdurduğumda kesme üretiyor ki bu meret?
doğru bu şekilde , sürekli açıp kapatıyorum ben bu fonksiyon ile
TIM_Cmd(TIM2,DISABLE) ile kapattıktan sonra, açmadan önce tekrar init edecekmiyiz? Garip bir şekilde timer çalışmaya ve kendi kafasına göre kesme üretmeye devam ediyor.
yok init yok , sadece enable disable yapıyorum.
Gözden kaçırdığım bişeyler var sanırım tekrar kontrol edeyim.
void TIM2_IRQHandler(void)
{
TIM_IT bitini sil.
//Falanca işlemleri yap
TIM_Cmd(TIM2, DISABLE);
}
Şeklinde kullanımda sorun olur mu? Kesmeden çıkarken kendisini kapatmak istiyorum ve TIM1 kesmesinde tekrar açıyorum.
kodlarıma bakıyorum da ,
bir handler'ın içinde açmışım , başka bir handler içinde kapatmışım.
// Counter Disable
TIM6->CR1 &=~ 0x0001; // Counter Disable
// Clear & Start Timer
TIM6->CNT = 0; // TIM6 Clear
TIM_Cmd(TIM6, ENABLE); // Enable TIM6
kaparken register seviyesinde yazmışım, ilk zamanlardan kalma bir satırdır ama onun bir şey değiştireceğini sanmıyorum.
mesaj birleştirme:: 28 Ocak 2014, 09:18:08
-------------
o şekilde kullanamazsın :
// Clear Interrupt
TIM_ClearITPendingBit(TIM6,TIM_IT_Update); // Clear Update interrupt flag
Bayrağı temizlemen lazım şu şekilde.
Alıntı yapılan: camby - 28 Ocak 2014, 09:17:17
o şekilde kullanamazsın :
// Clear Interrupt
TIM_ClearITPendingBit(TIM6,TIM_IT_Update); // Clear Update interrupt flag
Bayrağı temizlemen lazım şu şekilde.
Hocam bayrakları siliyorum temsili olarak o şekilde yazdım.
İnterrupt'ın kendi fonksiyonunda kendisini kapatsam/durdursam neden sorun olduğunu anlamadım. Datasheet'in neresinde yazar bu bilgi?
Datasheette bu soruna çözüm aramak samanlıkta iğne aramak gibi , ama bakılacak yer tabi referance manuel.
Daha iyi yöntem enable disable işlerinin yapıldığı örnek kodlara bakmak internette , STM hazır kodlarına bakmak varsa böyle bir şey.
Başka bir uygulamada şu şekilde yapmışım :
//====== Coil Test ============================================================
void Coil_Test(void)
{
if ( Coil0 == 255 )
{
// TIM counter enable
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
else
{
// TIM counter enable
TIM_Cmd(TIM1, DISABLE);
TIM_Cmd(TIM3, DISABLE);
}
if ( Coil1 == 255 )
{
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // Ref_Out Enable
}
else
{
TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE); // Ref_Out Disable
}
}//============================================================================
mesaj birleştirme:: 28 Ocak 2014, 10:21:21
Bunlar de test edildi sorunsuz çalışıyor , kodlarda bir şeyler gözden kaçmış olabilir.
Aynı şeyleri yaptım bende ama tekrar bir gözden geçireyim. Zaten bu şekilde kullanılıyorsa muhakkak benim kodlarımda sorun vardır.
Karşılaştırmak adına , açıp kapattığım bir timer'ın init fonksiyonu :
//====== TIM6 Init ( MODBUS Timer ) ===========================================
void TIM6_Init(uint32_t MODBUS_3_5_Delay)
{
// Timer6 clock 84 MHZ , Prescaler 84 -> 1 us'de bir deger 1 artar.
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // Struct
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // Clock Enable
TIM_DeInit(TIM6);
TIM_TimeBaseStructure.TIM_Period = MODBUS_3_5_Delay-1; // Ayarlar
TIM_TimeBaseStructure.TIM_Prescaler = 84-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // TIM_CKD_DIV1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); // Interrupt
NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn; // NVIC Ayarlari
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}//============================================================================
mesaj birleştirme:: 29 Ocak 2014, 10:28:08
Kesme üretme süresi başka bir fonksiyon tarafından belirleniyor.
TIM_TimeBaseStructure.TIM_Period = MODBUS_3_5_Delay-1; // Ayarlar
Çok önemli değil burası 1000 olsa , 1ms 'de bir kesme üretecek.
Aynısını yazdım bende, normalde açıp kapatmasam zaten problem yok.
Kodlar karman çorman oldu düzenleyip buraya ekleyeyim.
Çalıştı bu. Başka bir kesmede aktif pasif fonksiyonlarını kaldırmayı unutmuşum ahh kafam ahh.
geçmiş olsun o zaman : ) .
Şu basit şeylerden kaybettiğim zamanı birleştirsem yeni bir hayat sürebilirim. Teşekkürler :)
Kenar tespit...
Timer2 i main fonksiyonu içerisinde init ediyorum kesmeleri açıp timerı başlatıyorum, sonrasında PWM in olduğu TIM1 kesmesi içerisinde sürekli aşağıdaki init fonksiyonunu çağırmam lazım yoksa PWM in düşen kenarına yetişemiyor. (TIM1 ARR load değeri 3199) Sürekli init etmeden başka kullanım şekli var mı?
void TIM1_UP_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
TIM_TimeBaseStructure.TIM_Period = 3150; //ARR degeri + 1 . Buraya yazilan degere gelince timer kesme olusturur.
TIM_TimeBaseStructure.TIM_Prescaler= 399; //On bölücü degeri + 1
TIM_TimeBaseStructure.TIM_ClockDivision=0; //Saat bölücü
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //Timer modu. Yukari sayici.
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //Timer yapisi init.
GPIOD->ODR ^= 1 << 3;
}
inite gerek yok , enable - disable etmen yeterli
Girerken disable yapıp çıkarken enable mı yapacağım hocam?
Evet , Tim1 handler içinde daha önceden init edilmiş Tim2'yi enable edip ,
tim2 handler içinde de disable edebilirsin. Bu da düşen kenar kesmesi oluyor. Tim2 handler içinde eğer biliyorsa bir sonraki cycle için tim2 periodu değiştirilebilir.
PWM periyodu 40ms, Timer1 kesmesi içerisinde toggle yapıyorum toggle periyodu 4-5 saniye :o
PWM normal çalışıyor kesmesi gelemiyor biraz saç yolup geliyorum hocam :)
nasıl olur , 40ms de bir toggle olması lazım değil mi ?
Olmayınca olmuyor işte hocam. PWM çalışıyor TIM2 kesmesi geliyor TIM1 kesmesi geliyor ama geç geliyor. Bayraklarıda siliyorum ama saçma sapan davranıyor.
Enteresan bir şekilde şu oldu.
Kesme içerisindeki
GPIOB->ODR ^= 1 << 15; satırını silip tekrar yazdım, düzeldi. Ciddi ciddi derleyici bozuk diyeceğim artık. Keil 4.70 :o
Bu tip seyler ve cok daha fazlasi oluyor hep keil da. Sebebi naska yerdeki bir sey oluyor ama hata da vermiyor , sorunu bulmak cok zorlasiyor.
Sevmiyorum keil i.
Hocam saçma gelecek ama gerçekten kullandığım keil 4.70 problemliymiş. Başka fonksiyonları çağırırkende problem yaşadım üstelik derliyorum hexi işlemciye atıyorum kodun bir kısmı normal çalışırken olması gereken yer doğru çalışmıyor.
Bugün kesin tespit ettim. 4.70de derlediğim ve düzgün çalışmayan programı 4.72a versiyonunda hiçbir değişiklik yapmadan (aynı pc'de 4.70'i silip 4.72a yükledim) derledim çipe yükledim.
Sonuç? Saatlerdir çalışmayan kod gayet güzel çalıştı. Böyle problemlerle uğraşmak insanın zoruna gidiyor.
Birkaç bin dolarlık derleyici yapıyorlar bi işe yaramıyor ne kıymeti kaldı ki?
Siz hangi derleyiciyi kullanıyorsunuz?
4.60 dan 5.1 gectim yeni.
Projemi tasirken cok sorun yasadim ama simdi stabil.
Sorun bizim yanlis yerlerde kullandigimiz headerlar define lar vsvs
Sikinti keil in hata vermeden derledigi projelerde sacmalamasi.
Doğrudur hocam bişeyleri bilmeden eksik yapıyorsak derleyici uyarması lazım ki düzeltelim. Bende şuan 4.72 kullanıyorum. 5.01 den memnun musunuz? Geçmeli miyim? Orada bu tür hatalar oluyor mu?
5.1 de`de olsa .h dosyasi icinde define ile tanimlanmis bir degeri , .c dosyasi icinde tekrar define edince : hic hata vermeden tertemiz derleniyor. Ama olmadik yerlerde olmadik hatalar cikiyor , kimi zaman adc calismiyor , kimi zaman dma , debug zaten sapitiyor , sikintiyi bulmasi da cok zor oluyor. Hadi diyelim biz iyi bilmiyoruz bir warning bile vermiyor. Bahsettigim define hse degeri. 1 seneyi askin surekli keil kullandim simdi 7000 tl verip keil aldik ama bunlar delirtiyor.