Nuvoton M031 SysTick

Başlatan Kırambor, 05 Temmuz 2022, 23:29:26

Kırambor

Merhabalar,

Nuvotona çalışmaya devam ediyorum. Yapmak istediğim butona basıp bir ledi yakmak. Bunun için bir state machine kurdum. Butona 10k pull up direnci bağladım. STM32'de HAL_GetTick() diye bir fonksiyon var ve tick sayısını döndürüyor. Onun Nuvoton'daki karşılığını bulamadım. O yüzden STM32'nin kütüphanesinden kopya çekerek Inc_Tick() ve Get_Tick() fonksiyonları yazdım.

Kod şu şekilde:

#include "M031Series.h"

#define TIME (2000)

uint8_t buttonFT=0,ledState;
uint32_t firstLedTime,secondLedTime;
volatile uint32_t u32_Tick;

void SYS_Init(void);
void SysTick_Handler(void);
void Inc_Tick(void);
uint32_t Get_Tick(void);

void SYS_Init()
{
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable clock source */
    CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

    /* Waiting for clock source ready */
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

    /* Disable PLL first to avoid unstable when setting PLL */
    CLK_DisablePLL();

    /* Set PLL frequency */
    CLK->PLLCTL = (CLK->PLLCTL & ~(0x000FFFFFul)) | 0x0008C03Eul;

    /* Waiting for PLL ready */
    CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);

    /* If the defines do not exist in your project, please refer to the related clk.h in the Header folder appended to the tool package. */
    /* Set HCLK clock */
    CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

    /* Set PCLK-related clock */
    CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV1 | CLK_PCLKDIV_APB1DIV_DIV1);

    /* Enable IP clock */
    CLK_EnableModuleClock(ISP_MODULE);
    CLK_EnableSysTick(CLK_CLKSEL0_STCLKSEL_HCLK, 0);

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
    SystemCoreClockUpdate();

    /* Lock protected registers */
    SYS_LockReg();
}


void SysTick_Handler(void)
{
	Inc_Tick();
}

void Inc_Tick()
{
	u32_Tick++;
}

uint32_t Get_Tick()
{
	return u32_Tick;
}


int main(void)
{	
	SYS_Init();
	SysTick_Config(1000);
	
	GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
	GPIO_SetMode(PC,BIT1,GPIO_MODE_INPUT);

	
	while(1)
	{
			if(PC1 == 0)
			{
				if(buttonFT==0)
				{
					buttonFT = 1;
					ledState = 1;
				}	
			}
	
		switch(ledState)
		{
			case 0:{ledState=0;} break;
			case 1:{firstLedTime = Get_Tick(); ledState = 2;} break;
			case 2:
			{
				secondLedTime = Get_Tick();
				if(secondLedTime - firstLedTime > TIME)
				{
					PB14 = 1;
					ledState =0;
				}
			}
			break;
		}		
	}
}

Fakat nedense ledi yakmayı başaramıyorum. Acaba millis ya da HAL_GetTick fonksiyonlarının karşılığı Nuvoton'da var mı? Ben aradım fakat bulamadım malesef. Problemi çözmemde yardımcı olabilirseniz sevinirim.

power20

#1
Yazdığınız fonksiyon bir sayıyı artırmaktan ve sorgulamaktan ibaret. Sayı istediğiniz değere gelmişse bazı işler yapılacak.

Fakat orijinal fonksiyon interrupt ile çalışıyor olsa gerek. İnterrupt olursa otomatik çalışır.  Siz ana program ile artırmaya çalışmazsınız. 

Çözüm olarak timer interrupt ayarlayabilirsiniz. Sayı arka planda artmaya devam edecektir. Sorgulama ve karar verme işlemini de interrupt içinde yapmanız yerinde olur. Yoksa ana döngüde beğendiğiniz sayı tesadüfen sorgulama esnasına denk gelirse karar verilebilir. Denk gelmeye dayalı zayıf bir mekanizma olur. Kesin çözüm artırma işinin yapıldığı yerde karar vermektir



Kırambor

Alıntı yapılan: Kılıç - 06 Temmuz 2022, 00:02:47Yazdığınız fonksiyon bir sayıyı artırmaktan ve sorgulamaktan ibaret. Sayı istediğiniz değere gelmişse bazı işler yapılacak.

Fakat orijinal fonksiyon interrupt ile çalışıyor olsa gerek. İnterrupt olursa otomatik çalışır.  Siz ana program ile artırmaya çalışmazsınız. 

Çözüm olarak timer interrupt ayarlayabilirsiniz. Sayı arka planda artmaya devam edecektir. Sorgulama ve karar verme işlemini de interrupt içinde yapmanız yerinde olur. Yoksa ana döngüde beğendiğiniz sayı tesadüfen sorgulama esnasına denk gelirse karar verilebilir. Denk gelmeye dayalı zayıf bir mekanizma olur. Kesin çözüm artırma işinin yapıldığı yerde karar vermektir



Hocam SysTick_Handler(), SysTick interrupt fonksiyonu değil mi? Ben de internet CMSIS M0 uygulamalarına bakarak yaptım. Hatta SysTick_Config() fonksiyonunda 1kHz yani 1ms olacak şekilde hesap yaptım. Yanlış mı kullanımı acaba?

power20

#3

SysTick fonksiyonunun interrupt olduğuna dair bilgi göremedim. (Anlayamamış olabilirim)
interrupt olmasını belirtecek bir şey yazıldı mı ki ?
İsmi nedeniyle derleyici tarafından otomatik olarak interrupt olarak ayarlanan bir fonksiyon mudur?  Öyle olsa bile ne zaman çalışacak? Periyodu nedir? bunları belirtmek gerekir



quarko

SysTick_Handler, ARM Cortex ine ait bir interrupt rutini. Öncelikle SysTick interruptına doğru bir şekilde girip girmediğini kontrol et. Debug yaparak bunu kontrol edebilirsin. Emin olduktan sonra da state machine kısmını adım adım breakpoint koyarak istediğin noktalara gelip gelmediğini test edebilirsin.


Bir de 1ms de bir SysTick interruptı almak istiyorsan şu şekilde fonksiyonu çağırman gerekiyor diye biliyorum. Buradan bir başla bakalım.

SysTick_Config(SystemCoreClock / 1000);
"Aslanlar kendi hikayelerini yazmadıkça, avcıların kahramanlık hikayelerini dinlemek zorundayız."

Kırambor

#5
Alıntı yapılan: quarko - 06 Temmuz 2022, 11:29:24SysTick_Handler, ARM Cortex ine ait bir interrupt rutini. Öncelikle SysTick interruptına doğru bir şekilde girip girmediğini kontrol et. Debug yaparak bunu kontrol edebilirsin. Emin olduktan sonra da state machine kısmını adım adım breakpoint koyarak istediğin noktalara gelip gelmediğini test edebilirsin.


Bir de 1ms de bir SysTick interruptı almak istiyorsan şu şekilde fonksiyonu çağırman gerekiyor diye biliyorum. Buradan bir başla bakalım.
.

SysTick_Config(SystemCoreClock / 1000);

EDIT:Systick fonksiyonum olması gerektiği gibi çalışıyor şuan.

Kırambor

Benzer bir problemle karşılaşan olursa diye yanıtlıyorum tekrar. Ben geliştirme kiti kullanıyorum malesef led pinine low vermem gerekiyormuş yakabilmem için kartın üstündeki led bağlantısından dolayı.