卿枫~凌 发表于 2018-12-20 16:50:37

利用DWT进行精准us延迟

我使用STM32L151芯片,采用内部MSI时钟,4.194MHz,在利用DWT进行us延时的时候发现差距特别大,代码如下
void PUB_DelayInit(WORD32 SYSClock)
{
    SystemCoreClock = SYSClock;

    DEM_CR      |= (unsigned int)DEM_CR_TRCENA;   // 开启DWT调试
        DWT_CYCCNT   = (unsigned int)0u;                // 清零
        DWT_CR      |= (unsigned int)DWT_CR_CYCCNTENA;// 使能
}

void PUB_DelayUs(WORD16 us)
{
    WORD32 tCnt, tDelayCnt;
        WORD32 tStart;
               
        tStart = DWT_CYCCNT;                            // 刚进入时的计数器值
        tCnt = 0;
        tDelayCnt = us * (SystemCoreClock/1000000.0);        // 需要的节拍数                      

        while(tCnt < tDelayCnt)
        {
                tCnt = DWT_CYCCNT - tStart;               
        }
}


先进行PUB_DelayInit(4194000);然后调用PUB_DelayUs(5),示波器观察是10us,不知道为什么会出现这种情况呢?和网上说的精度差距有点大

radio2radio 发表于 2018-12-21 00:40:21

本帖最后由 radio2radio 于 2018-12-21 00:42 编辑

我的精准us延迟是这样得到的:


//-----uS delay ( >=1us)---------------
void vDelayUS(uint32_t u32DelayUS)
{
        uint32_t i;
       
        if (u32DelayUS <= 15)
        {
                switch(u32DelayUS)
                {
                        case 1:
                                __NOP();
                                __NOP();
                                __NOP();
                                return;
                       
                        case 2:
                                i = 3;
                                __NOP();
                                break;
                        case 3:
                                i = 6;
                                __NOP();
                                __NOP();
                                __NOP();
                                break;
                        case 4:
                                i = 10;
                                __NOP();
                                __NOP();
                                break;
                        default:
                                i = (u32DelayUS - 2) << 2;
                                i++;
                                i++;
                }
loop:        if (--i > 0) goto loop;
                return;
        }
        // >=16us
        u32DelayUS = (DELAY_US_FACTOR * u32DelayUS) >> 12;
        for (i = 0;i < u32DelayUS; i++) {}
}

上面的代码是在NXP的MCU上面,调试以后得到的。 注意,
1. CPU的时钟频率,直接影响结果。
2. 编译器的优化选择项,直接影响结果。
3. 使用时,必须用示波器,校准。


卿枫~凌 发表于 2018-12-21 10:12:34

radio2radio 发表于 2018-12-21 00:40
我的精准us延迟是这样得到的:




还有这种操作,厉害了

toofree 发表于 2018-12-21 11:07:06

本帖最后由 toofree 于 2018-12-21 11:12 编辑

楼主,设置延时时间长一点。
就这么个程序,做乘除法都得一段时间,还有程序进出的进栈、出栈时间。或者把IO电平反转放在紧挨着while的前后,看看相隔多长时间。
另外SystemCoreClock不应该是PUB_DelayInit(4194000)用户指定的吧,除非确定实际时间就是这个,一般是库函数中设置了。

页: [1]
查看完整版本: 利用DWT进行精准us延迟