stm32f302 encoder interrupt problemi

Başlatan superconductor, 30 Kasım 2015, 15:37:26

superconductor

Merhaba,

stm32f302rbt6 mcu ile iki adet quadratic encoder okuyorum. Encoder okuma kısmında sıkıntı yok fakat chipin encoder arayüzüne bağlı timerlarından sadece bir tanesi 32 bit olduğundan, ikisinide 16 bitlik timerlara bağlayıp, timerin taşma kesmesi ile encoder sayacına 65536 ekleyip çıkarıyorum. Böylece maksimum sayma miktarı artıyor.


void TIM4_IRQHandler(void)
{
	int x = TIM_GetCounter(TIM4);
	
	if(x < 32767)
	{
		encoderCount_1 += 65536;
		encoderEx1++;
	}
	else if (x > 32767)
	{
		encoderCount_1 -= 65536;
		encoderEx1--;
	}
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}



Genelde olması gerektiği gibi 65535 den 0'a geçiş anında (yada tam tersi) kesme oluşup, geçiş yönüne göre 65536 eklenip çıkarılıyor. Fakat bazen geçiş anında kesme rutini bir defadan daha çok çalışıyor. Bu durumu  encoderEx1 değişkenini izleyerek saptadım.

Kesme rutininin bir kereden daha fazla çalışmasına ne neden olabilir çözemedim. Kesme önceliklerim :


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //4 bit preemption
	NVIC_SetPriority(SysTick_IRQn, 5);

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);


        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

z

Her bir encoder girişi ile şase arasına 100pF kapasitör ekle.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

skara1214

birde encoder girişinde 4 bitlik filtre var bunuda kullanın belki işe yarar
Herkes ölür ama herkes gerçekten yaşamaz

superconductor

İnput compare girişindeki filtre açık ve en yüksek değerinde. Bülent hocanın 100pf önerisini deneyeceğim.

magnetron

TIM_ClearFlag(TIM4, TIM_FLAG_Update);

interrupt içinde bunu yazmayı denediniz mi hocam ?

superconductor

Sorunu çözdüm. Donanımsal filtreyi ayarlarken aşağıdaki kodu yazıyordum;
TIM_ICInitStructure.TIM_Channel 	= TIM_Channel_1 | TIM_Channel_2; 
	TIM_ICInitStructure.TIM_ICFilter 	= 0x0f;
	TIM_ICInitStructure.TIM_ICPolarity 	= TIM_ICPolarity_BothEdge;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM4, &TIM_ICInitStructure);


Sonra debug ile tim4 registerlerine bakarken ic2f register değerinin 0x0f olması gerekirken 0x00 olduğunu farkettim. Araya "|" koymadan TIM_Channel_1 ve TIM_Channel_2 için ayrı ayrı init edince registere 0x0f yazdı. Yukarıdaki gibi init edince neden iki registere de yazmadı fikri olan varmı? 





z

Sorunu nasıl çözdün?

Benzer sorun başımda ve sadece 100p ile çözebildim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

superconductor

Hocam std peripheral library kullanıyorum. Yukarıda anlattığım gibi donanımsal filtre için init structure'a yazarken TIM_Channel_1 | TIM_Channel_2 şeklinde yazıyordum. Normalde hem channel1 hemde channel2  için gerekli register lara 0x0f yazması gerekli (en yüksek filtre değeri). Fakat farkettimki sadece channel 1 için yazıyor. Channel2 filtresine birşey yazmıyor. Bende ayrı ayrı init ettim şöyle; 

Bunun yerine;
TIM_ICInitStructure.TIM_Channel 	=TIM_Channel_1 | TIM_Channel_2; 
	TIM_ICInitStructure.TIM_ICFilter 	= 0x0f;
	TIM_ICInitStructure.TIM_ICPolarity 	= TIM_ICPolarity_BothEdge;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM4, &TIM_ICInitStructure);



Bunu yazdım;
TIM_ICInitStructure.TIM_Channel 	= TIM_Channel_1; 
	TIM_ICInitStructure.TIM_ICFilter 	= 0x0f;
	TIM_ICInitStructure.TIM_ICPolarity 	= TIM_ICPolarity_BothEdge;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM4, &TIM_ICInitStructure);		
	
	TIM_ICInitStructure.TIM_Channel 	= TIM_Channel_2; 
	TIM_ICInitStructure.TIM_ICFilter 	= 0x0f;
	TIM_ICInitStructure.TIM_ICPolarity 	= TIM_ICPolarity_BothEdge;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM4, &TIM_ICInitStructure);


Normalde ilkininde çalışması gerekirdi diğer init structerlarıda aynı şekilde yazıyorum böyle birşeyle daha önce karşılaşmadım TIM_ICInit fonksiyonu eksik yazılmış olabilir.

Bu şekilde iki input capture filtresinide ayarladı. Sizde IC1F ve IC2F register değerlerini kontrol edin büyük olasılıkla problem buradadır. Bu arada benim sıkıntıyı 100pf gidermemişti. Skop ile encoder sinyallerine baktığımda, motora giden pwm işaretin, enkoder sinyallerinin geçiş durumlarında mhz seviyelerinde çınlamaya neden olduğunu gördüm.