ARM 循环阻塞延迟函数

文章介绍了在ARM-Cortex-M0和M4处理器上实现微妙延迟的方法,包括使用SysTick定时器和循环等待技术。通过精确控制时间和指令周期,确保串行驱动中的时序同步,尤其是在对时间敏感的协议如单总线、I2C中。提供了具体的代码示例来展示如何实现微妙级别的延迟。
摘要由CSDN通过智能技术生成

     串行驱动的关键是双方能够按照既定的时序进行检测、设置相关引脚上的电平,比如单总线、I2c这样基本的可以用GPIO模拟的时序协议,需要主从双方,必须在链路接口内严格按照微妙级的延迟单位进行时序同步。 所以,在这种对时间要求很敏感的情况下,一般都会考虑到用循环等待检测的方式来拖住时间窗,而且近似微妙的阻塞等待一般也不会对整个系统的用户体验造成太大的影响。 下面是在实际经验中积累的,微妙延迟的方法。

1. ARM-CORTX-M0  

   M0 HC32F110L上的延迟,可以精准到微妙。可以用systic,也可用while阻塞循环等待。

/******************************************************************************
 * 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);
  }
}

实际就两种方式比较通用的,一个是systic,这个真的要看systic分到的频率了, 如果本身频率很低,那么在微妙的精度行还是有些误差的。

另一种方式就是利用CPU的加法周期来做延迟,这个目前看来也有一定的可用性,关键是要找好指令周期的倍数。拿示波器实际调试可以作证得出最精准的延迟。

/*DELAY   HC32F60,pclk 200MHZ*/

#define DELAY_ADJUSTMENTS 12 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值