कैसे Arduino सीरियल बफर अतिप्रवाह संभालता है?


27

कैसे Arduino सीरियल बफर अतिप्रवाह संभालता है? क्या यह नवीनतम आने वाले डेटा को फेंक देता है या सबसे पुराना है? बफर कितने बाइट पकड़ सकता है?

serial 

जवाबों:


13

हार्डवेयर सीरियल पोर्ट के लिए आप HardwareSerial.cpp में देख सकते हैं कि बफ़र का आकार विशेष AVR पर उपलब्ध RAM की मात्रा के आधार पर भिन्न होता है:

#if (RAMEND < 1000)
    #define SERIAL_BUFFER_SIZE 16
#else
    #define SERIAL_BUFFER_SIZE 64
#endif

SoftwareSerial.h में सॉफ़्टवेयर सीरियल पोर्ट के लिए रिसीवर बफर आकार _SS_MAX_RX_BUFFको 64 बाइट्स के रूप में परिभाषित किया गया है। दोनों ही मामलों में यह भरा हुआ होने पर प्राप्त डेटा को कतार में सम्मिलित करने का प्रयास करना बंद कर देता है, इसलिए आप कतार से डेटा कैसे प्राप्त कर रहे हैं, इसके आधार पर पुराने और नए डेटा का मिश्रण प्राप्त कर सकते हैं।

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


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

मैंने बस उस कोड (अंडर / यूएसआर / शेयर / आर्दीनो / ​​हार्डवेयर / आर्कडीनो / ​​कोर / अरुडिनो / हार्डवेयरसियर ial.cpp) के माध्यम से देखा और पुष्टि कर सकता है कि आपने यहां क्या लिखा है। मैं केवल इतना ही कहना चाहूंगा कि चूंकि SRAM 2K (RAMEND> 1000) है, इसलिए यदि कथन हमेशा नैनो या Uno पर 16 के बजाय 64 का उपयोग करेगा। इसलिए यदि कोई रिंग बफर के आकार का विस्तार करना चाहेगा जो इसे बदलने की जगह होगी
एसडीसोलर

5

प्राप्त करना

आप HardwareSerial के स्रोत से देख सकते हैं कि यदि कोई आवक बाइट रिंग बफ़र को पूर्ण पाता है तो उसे छोड़ दिया जाता है:

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

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

हाँ, इसे छोड़ दिया जाएगा। कोई सॉफ्टवेयर या हार्डवेयर प्रवाह नियंत्रण नहीं है, जब तक कि आप अपना खुद का कार्यान्वयन न करें।

हालाँकि, 64-बाइट बफर के साथ, और 9600 बॉड में (प्राप्त) डेटा प्राप्त होता है, आपको हर 1.04 ms पर एक बाइट मिलता है, और इस तरह बफर को भरने में 66.6 ms लगते हैं। 16 मेगाहर्ट्ज प्रोसेसर पर आप बफर को अक्सर पर्याप्त रूप से जांचने में सक्षम होना चाहिए कि यह नहीं भरता है। आपको बस इतना करना है कि हार्डवेयरस्फीयर बफर से डेटा को अपने आप में स्थानांतरित करना है, अगर आप इसे अभी प्रोसेस नहीं करना चाहते हैं।

आप #if (RAMEND < 1000)चेक से देख सकते हैं कि 1000+ बाइट रैम वाले प्रोसेसर को 64-बाइट बफर मिलता है, कम रैम में 16-बाइट बफर मिलेगा।


भेजना

आपके द्वारा लिखा गया डेटा एक समान आकार के बफर (16 या 64 बाइट्स) में रखा गया है। भेजने के मामले में यदि बफर कोड "ब्लॉक" भरता है तो सीरियल पोर्ट से अगले बाइट को भेजने के लिए एक रुकावट की प्रतीक्षा करता है।

यदि इंटरप्ट को बंद कर दिया जाता है तो ऐसा कभी नहीं होगा, इस प्रकार आप एक इंटरप्ट सर्विस सर्विस के अंदर सीरियल प्रिंट नहीं करते हैं।


मेरा मानना ​​है कि आप परिमाण के क्रम से दूर हैं: 9600 बॉड में, आपको प्रत्येक ~ 0.1 एमएस पर एक बाइट मिलती है, इसलिए बफर को भरने के लिए केवल 6.6 एमएस लगता है।
एरिक डैंड

1
9600 बॉड में आपको 9600 बिट प्रति सेकंड मिलता है । चूँकि प्रत्येक बाइट 10 बिट्स (8 डेटा + 1 स्टार्ट बिट + 1 स्टॉप बिट) है तो आपको प्रति सेकंड 960 बाइट्स मिलते हैं। 1/960 = 0.001042 s- कि हर 1.04 एमएस में एक बाइट है।
निक गैमन

आह, बिट्स नहीं बाइट्स! सुधारों के लिए धन्यवाद।
एरिक डांड

तो निक, कृपया मेरे लिए इसका उत्तर दें: यदि मेरे पास एक पाई चल रहा है, जो एक सीर। ट्रेडलाइन के रूप में इनपुट के लिए प्रतीक्षा कर रहा है। और इसे सीरियल के माध्यम से Arduino द्वारा रीडिंग लेते हुए, तब उन्हें बैच के रूप में एक बैच के रूप में भेजा जाता है। डेलिमीटर, फिर देरी (120000) का उपयोग करते हुए इसलिए बैच हर दो मिनट में आते हैं, पायथन सराय शायद हर पात्र में तुरंत पढ़ता है जब तक कि यह एक नई पंक्ति का सामना नहीं करता है, जिस बिंदु पर यह पूरी लाइन को वापसी मान के रूप में जारी करता है। इसलिए मुझे अरुदीनो बफर के आकार के बारे में चिंता करने की ज़रूरत नहीं है, भले ही मैं कुल 80 वर्ण भेज रहा हूं, एह? क्या यह एक अच्छी धारणा होगी?
एसडीसोलर

हां, इस परिदृश्य में भेजने वाले बफर का आकार मायने नहीं रखेगा। एक छोटा बफर भेजने (थोड़ा) को धीमा कर देगा, लेकिन अगर आप एक लंबा विलंब कर रहे हैं, तो आप परवाह नहीं करेंगे।
निक गैमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.