2012-11-14 16 views
8

पर सी में नैनोसेकंद देरी उत्पन्न करना मैं STM32F2 नियंत्रक का उपयोग कर रहा हूं और मैं 8 बिट समांतर इंटरफ़ेस के माध्यम से ST7036 एलसीडी डिस्प्ले के साथ इंटरफेसिंग कर रहा हूं।एसटीएम 32

डेटाशीट का कहना है कि एड्रेस होल्ड और सेटअप समय के बीच 20 नैनो दूसरी देरी होनी चाहिए।

मैं सी में 20 नैनोसेकंद देरी कैसे उत्पन्न करूं?

+0

क्या आपने 'nanosleep() 'फ़ंक्शन की कोशिश की है? नोट: इसका उपयोग करने के लिए आपको '' शामिल करने की आवश्यकता है। –

+0

आपको एनएस देरी करने की आवश्यकता नहीं है। ये डेटाशीट द्वारा न्यूनतम देरी हैं, लेकिन आप और अधिक कर सकते हैं। इसके अलावा, आप एसपीआई या आई 2 सी का उपयोग क्यों नहीं करना चाहते हैं? यह बहुत आसान है और आप एक पैकेट में डेटा भेज सकते हैं। तो आप अन्य कार्यों के लिए नियंत्रक मुक्त कर देंगे। – Bulkin

उत्तर

8

Stm32f2 का पहला विनिर्देश मुझे 120 मेगाहर्ट्ज की घड़ी आवृत्ति मानता है। प्रति घड़ी चक्र के बारे में 8ns है। आपको लगातार लिखने या पढ़ने/लिखने के संचालन के बीच लगभग तीन एकल चक्र निर्देशों की आवश्यकता होगी। सी में, a++; शायद होगा (यदि कोई ढेर में स्थित है)।

+0

हाँ - बिल्कुल - सभी उत्तरों लेकिन यह एक समाधान प्रदान करता है जो आवश्यकतानुसार 100x अधिक समय लेगा ... 20ns केवल कुछ चक्र हैं, असेंबली में कुछ एनओपी पर्याप्त से अधिक होंगे ... –

+0

यह नहीं होगा विशेष रूप से उस उद्देश्य के लिए डिज़ाइन किए गए चक्र गणना रजिस्टर का उपयोग करके देरी को सत्यापित करने के लिए अच्छा है, भले ही देरी विधि का उपयोग किया जाए? अन्यथा, मुझे लगता है कि इसे एक ऑसिलोस्कोप और कुछ डिजिटल पिन के साथ सत्यापित किया जा सकता है। – bunkerdive

+0

ऊपर 'stopwatch_delay() 'फ़ंक्शन मेरे लिए यह पूरी तरह से पूरा करता है, और इसे अलग-अलग देरी की लंबाई के लिए सत्यापित या उपयोग किया जा सकता है। – bunkerdive

11

अपनी देरी पूरी करने के लिए नीचे stopwatch_delay(ticks का उपयोग करें)। यह STM32 के DWT_CYCCNT रजिस्टर का उपयोग करता है, जिसे विशेष रूप से पता 0xE0001004 पर स्थित वास्तविक घड़ी टिकों की गणना करने के लिए डिज़ाइन किया गया है।

देरी सटीकता को सत्यापित करने (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 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 nClkTicksPerMicrosec; 

    nDiffTicks = nStop - nStart; 
    nDiffTicks *= 1000;        // Scale diff by 1000. 
    nClkTicksPerMicrosec = SystemCoreClock/1000000; // Convert (clkTicks/sec) to (clkTicks/microsec), SystemCoreClock = 168000000 

    return nDiffTicks/nClkTicksPerMicrosec;   // nanosec = (ticks * 1000)/(clkTicks/microsec) 
} 

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

    STOPWATCH_START; 
    run_my_function(); 
    STOPWATCH_STOP; 

    timeDiff = CalcNanosecondsFromStopwatch(m_nStart, m_nStop); 
    printf("My function took %d nanoseconds\n", timeDiff); 
} 
+0

क्या आप वाकई यह काम करेंगे? एक निर्देश चक्र लगभग 5ns होगा .. जाहिर है कोड 5 से अधिक निर्देशों का उपयोग करता है। तो न्यूनतम समय 25ns होगा ... हार्डवेयर में उपयोग की जाने वाली देरी, हालांकि, 25ns से कम हो सकती है। – richieqianle

+0

हां। कोड को आवश्यकतानुसार संशोधित किया जाना है। कोई निश्चित रूप से आवश्यक न्यूनतम टुकड़ों का उपयोग कर सकता है, या आदर्श रूप से इस कोड का उपयोगकर्ता 'मुख्य() '(उदाहरण के लिए' run_my_function()' है) के अंदर लूप में '__no_operation()' एक हजार बार चलाएगा 1000 रनों के लिए नैनो-सेकंड स्टॉपवॉच, और उसके बाद उस नंबर को 1000 तक विभाजित करें ताकि यह देखने के लिए कि एक एकल पाइपलाइन '__no_operation()' कॉल सिस्टम पर कितनी देर तक लेता है ... और फिर वांछित के रूप में उपयोग करें। – bunkerdive

+1

बस एक टिप्पणी, 1000 एनओपी/1000 1 एनओपी के बराबर नहीं हो सकता है। वैसे भी महान व्याख्या! – richieqianle

0

आपको अपने चिप में उपलब्ध एफएसएमसी परिधीय में देखना चाहिए। जबकि कॉन्फ़िगरेशन जटिल हो सकता है, विशेष रूप से यदि आप किसी मेमोरी भाग में नहीं जा रहे हैं जिसे इसे डिज़ाइन किया गया था, तो आप पाएंगे कि आपके समांतर इंटरफेस डिवाइस मेमोरी इंटरफ़ेस मोड में से एक के लिए बहुत अच्छी तरह से मानचित्र हैं।

बाहरी मेमोरी नियंत्रकों के इस प्रकार के पास विभिन्न मेमोरी चिप्स की श्रेणी का समर्थन करने के लिए कॉन्फ़िगर करने योग्य समय विकल्पों का एक गुच्छा होना चाहिए ताकि आप अपने डेटाशीट द्वारा आवश्यक समय की गारंटी दे सकें।

ऐसा करने में सक्षम होने का अच्छा लाभ यह है कि आपका एलसीडी किसी भी पुराने मेमोरी मैप किए गए परिधीय की तरह प्रतीत होता है, जो निचले स्तर के अंतरफलक विवरण को दूर करता है।

संबंधित मुद्दे