首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在STM32上生成C语言的纳秒延迟

在STM32上生成C语言的纳秒延迟
EN

Stack Overflow用户
提问于 2012-11-14 20:54:36
回答 3查看 13.1K关注 0票数 11

我正在使用STM32F2控制器,并通过8位并行接口与ST7036液晶显示器接口。

数据手册说,在地址保持和设置时间之间应该有20纳秒的延迟。

如何在C中生成20纳秒的延迟?

EN

回答 3

Stack Overflow用户

发布于 2013-10-02 03:38:19

使用下面的stopwatch_delay(4)来完成大约24 of的延迟。它使用STM32的DWT_CYCCNT寄存器,该寄存器专为计数实际时钟节拍而设计,位于地址0xE0001004。

要验证延迟准确性(参见main),可以调用STOPWATCH_START,运行stopwatch_delay(ticks),然后调用STOPWATCH_STOP并使用CalcNanosecondsFromStopwatch(m_nStart, m_nStop)进行验证。根据需要调整ticks

代码语言:javascript
复制
uint32_t m_nStart;               //DEBUG Stopwatch start cycle counter value
uint32_t m_nStop;                //DEBUG Stopwatch stop cycle counter value

#define DEMCR_TRCENA    0x01000000

/* Core Debug registers */
#define DEMCR           (*((volatile uint32_t *)0xE000EDFC))
#define DWT_CTRL        (*(volatile uint32_t *)0xe0001000)
#define CYCCNTENA       (1<<0)
#define DWT_CYCCNT      ((volatile uint32_t *)0xE0001004)
#define CPU_CYCLES      *DWT_CYCCNT
#define CLK_SPEED         168000000 // EXAMPLE for CortexM4, EDIT as needed

#define STOPWATCH_START { m_nStart = *((volatile unsigned int *)0xE0001004);}
#define STOPWATCH_STOP  { m_nStop = *((volatile unsigned int *)0xE0001004);}


static inline void stopwatch_reset(void)
{
    /* Enable DWT */
    DEMCR |= DEMCR_TRCENA; 
    *DWT_CYCCNT = 0;             
    /* Enable CPU cycle counter */
    DWT_CTRL |= CYCCNTENA;
}

static inline uint32_t stopwatch_getticks()
{
    return CPU_CYCLES;
}

static inline void stopwatch_delay(uint32_t ticks)
{
    uint32_t end_ticks = ticks + stopwatch_getticks();
    while(1)
    {
            if (stopwatch_getticks() >= end_ticks)
                    break;
    }
}

uint32_t CalcNanosecondsFromStopwatch(uint32_t nStart, uint32_t nStop)
{
    uint32_t nDiffTicks;
    uint32_t nSystemCoreTicksPerMicrosec;

    // Convert (clk speed per sec) to (clk speed per microsec)
    nSystemCoreTicksPerMicrosec = CLK_SPEED / 1000000;

    // Elapsed ticks
    nDiffTicks = nStop - nStart;

    // Elapsed nanosec = 1000 * (ticks-elapsed / clock-ticks in a microsec)
    return 1000 * nDiffTicks / nSystemCoreTicksPerMicrosec;
} 

void main(void)
{
    int timeDiff = 0;
    stopwatch_reset();

    // =============================================
    // Example: use a delay, and measure how long it took
    STOPWATCH_START;
    stopwatch_delay(168000); // 168k ticks is 1ms for 168MHz core
    STOPWATCH_STOP;

    timeDiff = CalcNanosecondsFromStopwatch(m_nStart, m_nStop);
    printf("My delay measured to be %d nanoseconds\n", timeDiff);

    // =============================================
    // Example: measure function duration in nanosec
    STOPWATCH_START;
    // run_my_function() => do something here
    STOPWATCH_STOP;

    timeDiff = CalcNanosecondsFromStopwatch(m_nStart, m_nStop);
    printf("My function took %d nanoseconds\n", timeDiff);
}
票数 15
EN

Stack Overflow用户

发布于 2012-11-14 21:24:27

我发现的Stm32f2的第一个规范假设时钟频率为120 MHz。这大约是每个时钟周期8 8ns。在连续的写或读/写操作之间需要大约三条单周期指令。在C中,a++;可能会这样做(如果a位于堆栈中)。

票数 9
EN

Stack Overflow用户

发布于 2018-01-30 01:56:15

您应该查看芯片中可用的FSMC外设。虽然配置可能很复杂,特别是如果您没有插入它设计的内存部分,但您可能会发现并行接口设备很好地映射到其中一种内存接口模式。

这些类型的外部内存控制器必须有一堆可配置的时序选项,以支持各种不同的内存芯片,因此您将能够保证数据手册所需的时序。

能够做到这一点的好处是,您的LCD将看起来像任何旧的内存映射外围设备,抽象出较低级别的接口细节。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13379220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档