11

STM32F2コントローラを使用しており、 8 ビット パラレル インターフェイスを介してST7036 LCD ディスプレイと接続しています。

データシートには、アドレス ホールドとセットアップ時間の間に 20 ナノ秒の遅延が必要であると記載されています。

C で 20 ナノ秒の遅延を生成するにはどうすればよいですか?

4

3 に答える 3

15

以下の ) を使用stopwatch_delay(4して、約 24ns の遅延を実現します。これは、アドレス 0xE0001004 にある実際のクロック ティックをカウントするように特別に設計された STM32 の DWT_CYCCNT レジスタを使用します。

遅延の精度を確認するには ( を参照main)、 を呼び出しSTOPWATCH_STARTて を実行しstopwatch_delay(ticks)、 を呼び出しSTOPWATCH_STOPて で確認しCalcNanosecondsFromStopwatch(m_nStart, m_nStop)ます。必要に応じて調整ticksします。

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);
}
于 2013-10-01T19:38:19.107 に答える
9

私が最初に見つけた Stm32f2 の仕様では、120 MHz のクロック周波数が想定されています。これは、クロック サイクルあたり約 8ns です。連続する書き込みまたは読み取り/書き込み操作の間には、約 3 つのシングル サイクル命令が必要です。C では、a++;おそらくそうします (a がスタックにある場合)。

于 2012-11-14T13:24:26.860 に答える