ARM loop blocking delay function

     The key of the serial drive is that both parties can detect and set the level on the relevant pins according to the established timing. For example, the basic timing protocol such as single bus and I2c that can be simulated by GPIO requires both master and slave sides, which must be connected at the link interface. Timing synchronization is performed in strict accordance with the delay unit of microsecond level. Therefore, in such a case that is sensitive to time requirements, it is generally considered to delay the time window by means of circular waiting detection, and the approximate subtle blocking waiting will generally not cause too much impact on the user experience of the entire system Influence. The following is the method of subtle delay accumulated in practical experience.

1. ARM-CORTX-M0  

   The delay on the M0 HC32F110L can be accurate to subtle. You can use systic or while blocking the loop to wait.

/******************************************************************************
 * systic 
 * xus:
 *     use this delay function when time >= 20 
*******************************************************************************/
void jbf_systic_us_ex(uint32_t xus)
{ 
 	SysTick->LOAD = (xus - 18) * (JBF_SISTICK_VALUE / 1000000);
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;
	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
	SysTick->CTRL &= ~(0x01 << SysTick_CTRL_ENABLE_Pos);
}
/******************************************************************************
 * 24M 1US delay,
 * ??????????????1us??????
*******************************************************************************/
 
void jbf_delay_24M_us(void)
{
	int xus = 1;
	while( xus--)
	{
		__NOP();__NOP();
	}
	 
}

void jbf_delay_24M_xus(uint16_t xus)
{
	uint16_t j;
	while (xus--)
	{
		j = 2; //
		while (j--)
		;
	}
}

2. ARM-CORTEX-M4

/**********************************************************
 * DEC:  200M MPLL us delay function.
 * PARAM: n = nus
 * RETURN: none
***********************************************************/
void delay_nus(uint16_t n)
{
  uint16_t j;
  while(n--)
  {
    j = DELAY_ADJUSTMENTS;// 
    while(j--);
  }
}
extern uint32_t SystemCoreClock;        /*!< System clock frequency (Core clock) */
/***
 * 
 * base interval is 60 when LOAD  = 1, LOAD + 1 lead the timme plus 30us
 * if the value lager than 60, and times of 30, then use this function
 * (time - 60) / 30 - 1;
 * time = 180 , load = (180 - 60) / 3 + 1 = 5;
 * 
 */

void delay_30Tnus(uint16_t n)
{
  uint32 _load =  (n - 60) / 10 / 3 + 1;
	SysTick->LOAD = _load;
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;
	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
	SysTick->CTRL &= ~(0x01 << SysTick_CTRL_ENABLE_Pos);
}
 
/**********************************************************
 * DEC:  200M MPLL ms delay function.
 * PARAM: n = mus
 * RETURN: none
***********************************************************/
void delay_nms(uint16_t n)
{
  while(n--)
  {
    delay_nus(1000);
  }
}

In fact, two methods are more common, one is systic, this really depends on the frequency allocated by systic, if the frequency itself is very low, then there are still some errors in the subtle precision line.

Another way is to use the addition cycle of the CPU to do the delay. It seems that this is also available to a certain extent. The key is to find a good multiple of the instruction cycle. The actual debugging with an oscilloscope can prove the most accurate delay.

/*DELAY   HC32F60,pclk 200MHZ*/

#define DELAY_ADJUSTMENTS 12 

void delay_nus(uint16_t n)
{
  uint16_t j;
  while(n--)
  {
    j = DELAY_ADJUSTMENTS;// 
    while(j--);
  }
}

Guess you like

Origin blog.csdn.net/loveboon1/article/details/131900270