반응형

어느샌가 1us 마다 정확하게 delay 시키는 함수 및 방법이 궁금해서 아래와 같이 자료를 정리한다.

 

결과적으로 STM32F103에서 제공하는 timer interrupt event 처리로 1ms 마다 거의 정확하게 delay 함수를 사용할 수 있지만, 1us 마다 delay 함수 사용하는 것은 사용자 MCU 및 컴파일러 환경에 따라 달라지는 것을 확인할 수가 있다. 그럼에도 불구하고 거의 1us에 가깝게 GPIO toggling할 수 있는 방법을 찾고자 한다면 괜찮지 않을까?

 

구글링에서 검색되는 delay_us 함수 중에 가장 많이 검색되는 function structure는 아래와 같다.

 

void Delay_us(__IO u32 nCount)
{
    for (; nCount != 0;nCount--);
}

void Delay_us(__IO uint32_t nCount)
{
	if(nCount>1){
			uint32_t count=nCount*8-6;
			while(count--); //asm volatile("nop");
	}
	else{
		uint32_t count=2;
		while(count--); // asm volatile("nop");
	}
}

 

실험을 해보니, 굳이 번거롭게 및 제법 있어보이게(?) 어셈블러 코드 같은거 갖다 쓰는데, 나와 같이 평범한 사람들은 그냥 아래와 같은 간단한 코드를 사용하면 된다.

 

#define NOP_1   asm volatile("NOP")
#define NOP_2  NOP_1; NOP_1
#define NOP_4  NOP_2; NOP_2
#define NOP_10   NOP_4; NOP_4; NOP_2
#define NOP_20  NOP_10; NOP_10
#define NOP_40  NOP_20; NOP_20

void delay_1us(bool state){ // High & LOW

	if (state)
	{
		NOP_20;
	}

	else{
		NOP_40;
	}
}

void GPIO_Toggle(){

	GPIO_ResetBits(GPIOC, GPIO_Pin_0);
	delay_1us(LOW);
	GPIO_SetBits(GPIOC, GPIO_Pin_0);
	delay_1us(HIGH);
}

 

이클립스 개발 환경에서 default option으로 컴파일을 하고, delay_us(1)마다 GPIO toggling을 하면 아래와 같은 파형이 관찰된다. 아울러 High / Low level timing도 서로 다른 것도 확인할 수가 있다.

 

그래서 정확하게 delay_us(1) 마다 GPIO toggling을 하는 방법은 아래와 같이, 컴파일 옵션 중에 Optimization Level을 "Optimize size (-Os)"를 선택하고 컴파일을 하면 다음과 같은 파형(High 및 LOW)을 얻을 수가 있다.

 

반응형

+ Recent posts