ATmega328 पर AVR टाइमर स्पीडअप


9

जब ATmega328 पर 64 के क्लॉक प्रिस्क्रेलर पर चल रहा है, तो मेरी एक टाइमर निष्पादन में एक विशेष समय पर अज्ञात कारणों से गति करता है।

मैं Tme5940 द्वारा आवश्यक क्लॉकिंग उत्पन्न करने के लिए ATmega328 पर दो टाइमर का उपयोग कर रहा हूं (नीचे क्यों देखें, यह सवाल के लिए सार है)। TIMER0फास्ट पीडब्लूएम का उपयोग करके एक घड़ी संकेत उत्पन्न करता है OC0Bऔर इसे निम्नानुसार सेट किया जाता है:

TCCR0A = 0
    |(0<<COM0A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM0A0)    // 
    |(1<<COM0B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM0B0)
    |(1<<WGM01)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(1<<WGM00)
    ;
TCCR0B = 0
    |(0<<FOC0A)     // Force Output Compare A
    |(0<<FOC0B)     // Force Output Compare B
    |(1<<WGM02)     // Bit 3 – WGM02: Waveform Generation Mode
    |(0<<CS02)      // Bits 2:0 – CS02:0: Clock Select
    |(1<<CS01)
    |(0<<CS00)      // 010 = clock/8
    ;
OCR0A = 8;
OCR0B = 4;
TIMSK0 = 0;

TIMER2प्रत्येक 256 TIMER0चक्रों में एक खाली पल्स उत्पन्न करने के लिए एक डेटा लाइन को ट्विंडल करता है और इसे निम्नानुसार सेट किया जाता है:

ASSR = 0;
TCCR2A = 0
    |(0<<COM2A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM2A0)    // 
    |(0<<COM2B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM2B0)
    |(0<<WGM21)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(0<<WGM20)
    ;
TCCR2B = 0
    |(0<<FOC2A)     // Force Output Compare A
    |(0<<FOC2B)     // Force Output Compare B
    |(0<<WGM22)     // Bit 3 – WGM02: Waveform Generation Mode
    |(1<<CS22)      // Bits 2:0 – CS02:0: Clock Select
    |(0<<CS21)
    |(0<<CS20)      // 100 = 64
    ;
OCR2A = 255;
OCR2B = 255;
TIMSK2 = 0
    |(1<<TOIE2);    // Timer/Counter0 Overflow Interrupt Enable

TIMER2अतिप्रवाह (प्रत्येक 256 चक्र) पर एक ISR कहता है। ISR मैन्युअल रूप से एक खाली पल्स, और एक लैचिंग पल्स उत्पन्न करता है यदि आवश्यक हो:

volatile uint8_t fLatch;

ISR(TIMER2_OVF_vect) {
    if (fLatch) {
        fLatch = 0;
        TLC5940_XLAT_PORT |=  (1<<TLC5940_XLAT_BIT);        // XLAT -> high
        for (int i=0;i<10;i++)
            nop();
        TLC5940_XLAT_PORT &= ~(1<<TLC5940_XLAT_BIT);        // XLAT -> high
    }
    // Blank
    TLC5940_BLANK_PORT |= (1<<TLC5940_BLANK_BIT);
    for (int i=0;i<10;i++)
        nop();
    TLC5940_BLANK_PORT &= ~(1<<TLC5940_BLANK_BIT);
}

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

for (;;) {
    if (!fLatch) {
        sendSerial();
        fLatch = 1;
        _delay_ms(1);
    }
    nop();
}

sendSerial()कुछ एसपीआई भेजता है ( संक्षिप्तता के लिए pastebin पर कोड )। मेरा मुद्दा यह है कि sendSerial()पूरा होने के बाद , fLatchकम (संसाधित) होने की प्रतीक्षा करते समय क्लॉकिंग टाइमर की गति बढ़ जाती है। यहाँ लॉजिक एनालाइज़र ट्रेस है (मैंने उन क्षेत्रों को काट दिया है जहाँ ग्राफिक को छोटा बनाने के लिए एक ही संकेत जारी रहता है):

यहां छवि विवरण दर्ज करें

बाईं ओर, चैनल 0 और 1 एसपीआई डेटा के टेल एंड को दिखाते हैं। इसके अलावा बाईं ओर, चैनल 4 पर, आप एक खाली पल्स देख सकते हैं। चैनल 2 पर क्लॉकिंग पल्स चग्स के रूप में अपेक्षित। जहां छवि में अंतराल है, उसके आसपास ही दिनचर्या के अंदर fLatchसेट किया 1गया main()है। और जल्द ही बाद TIMER0में एक कारक के बारे में 4 से गति करता है। आखिरकार, खाली पल्स और लैचिंग पल्स का प्रदर्शन किया जाता है (चैनल 3 और 4, छवि का सही तीसरा), और अब क्लॉकिंग पल्स अपनी नियमित आवृत्ति, और सीरियल डेटा को फिर से शुरू करता है। पुनः भेजा गया। मैंने delay_ms(1);लाइन को अंदर लेने की कोशिश की main(), लेकिन वही परिणाम प्राप्त हुए हैं। क्या चल रहा है? मुझे ध्यान देना चाहिए कि ATmega को 20Mhz क्रिस्टल से बंद करके रखा गया है और फिर निम्न कोड का उपयोग करके 64x तक धीमा कर दिया गया है:

CLKPR = 1<<CLKPCE;
CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0);

यह किसके लिए है: मैं TLC5940 एलईडी ड्राइवर को नियंत्रित करने के साथ प्रयोग कर रहा हूं : इन चिप्स को एक बाहरी घड़ी और क्लॉकिंग चक्र के अंत में रीसेट की आवश्यकता होती है।


यदि आपके पास एक डीबगर है, तो टाइमर बहुत तेज़ होने पर अपने कोड को रोकने का प्रयास करें और उस टाइमर के कॉन्फ़िगरेशन रजिस्टर को वापस पढ़ें। एक बार जब आप गलत मान के साथ मिल जाते हैं, तो इस रजिस्टर परिवर्तन पर एक ब्रेकपाइंट को ट्रिगर करें और देखें कि आपके कोड का कौन सा हिस्सा गलत प्रदर्शन कर रहा है। मुझे लगता है कि यह समस्या एक बाहरी पुस्तकालय में स्थित है जिसे आप उपयोग कर सकते हैं और उस टाइमर का उपयोग आंतरिक सामान जैसे देरी के लिए करते हैं।
ब्लुप

दो समस्याएं: क) मेरे पास जेटीजी प्रोग्रामर नहीं है, इसलिए मेरे पास चिप डी डिबग करने का एक तरीका नहीं है) मैं ऊपर दिखाए गए सेटअप के बाद टाइमर रजिस्टर मूल्य को कभी नहीं बदलता, इसलिए मुझे टाइमर रजिस्टर मूल्यों की उम्मीद नहीं है वास्तव में बदल जाते हैं। क्या वह भोला है?
5

1
वास्तव में आपके द्वारा उपयोग की जाने वाली एक लाइब्रेरी UART सेटिंग बदल सकती है। मैं देखता हूं कि आप एक SendSerial () फ़ंक्शन का उपयोग करते हैं। क्या यह आपके कोड का हिस्सा है या यह एक बाहरी पुस्तकालय है? यह आप नहीं हो सकते हैं जो सेटिंग्स को बदलते हैं, लेकिन एक पुस्तकालय के अंदर कोड का एक टुकड़ा। मेरा सुझाव है कि आप कॉन्फ़िगरेशन मापदंडों को आउटपुट करने के लिए अपने सीरियल पोर्ट का उपयोग करें और यह जानने की कोशिश करें कि क्या बदला है। आप उपयोग किए गए पुस्तकालयों (यदि कोई हो) के स्रोत को देख सकते हैं और सुनिश्चित कर सकते हैं कि वे उस टाइमर का भी उपयोग नहीं करते हैं।
Blup1980

1
इसके अलावा क्या @ Blup1980 ने एक और बात का सुझाव दिया है जो कि कोशिश करने लायक हो सकता है TLC5940 को हटा रहा है यह सुनिश्चित करने के लिए कि यह घड़ी की रेखा के साथ कुछ भी नहीं कर रहा है।
पीटरजे

@ Blup1980 मुझे यकीन नहीं है कि मैं UART की प्रासंगिकता देखता हूं: मैं SPI के लिए USART का उपयोग नहीं कर रहा हूं, बस "नियमित" SPI सुविधाएं। sendSerial()एसपीआई के माध्यम से डेटा भेजने वाला मेरा कोड है: यह TCCR(टाइमर नियंत्रण) रजिस्टर को नहीं छूता है ।
स्वर्गदूत

जवाबों:


1

एक त्वरित डिबग के लिए, मैं TLC5940 के लिए Arduino लाइब्रेरी का उपयोग करके एक ही काम करने की कोशिश करूंगा और देखूंगा कि यह तेज हो रहा है या नहीं। यदि यह पुस्तकालय के साथ काम करता है, तो आप इसके स्रोत की जांच कर सकते हैं और आपकी तुलना कर सकते हैं। चूंकि आप AVR से परिचित हैं, इसलिए आपको आसानी से Arduino स्रोत को देशी AVR में बदलना चाहिए।

बस अगर आपको पता नहीं है कि संकलित Arduino स्केच को AVR में कैसे अपलोड किया जाए: जब आप अपना स्केच संकलित करते हैं, तो यह एक हेक्स फ़ाइल बनाता है (आप सेटिंग्स में वर्बोज़ मोड चालू करके फ़ाइल का सटीक स्थान देख सकते हैं)। आप अपने पसंदीदा प्रोग्रामर के साथ उस हेक्स को अपने AVR पर अपलोड कर सकते हैं।

आशा है ये मदद करेगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.