SIM900D के उदाहरण पर जीएसएम-मॉड्यूल के साथ काम करें

इतना समय पहले नहीं, एक मित्र ने मुझे एक माइक्रोकंट्रोलर के लिए फर्मवेयर बनाने से संबंधित नौकरी की पेशकश की, जिसे SIM900D GSM मॉड्यूल का उपयोग करके सर्वर के साथ संवाद करना था। इससे पहले, मेरे पास प्रोग्रामिंग माइक्रोकंट्रोलर्स के साथ कोई व्यवसाय नहीं था, और मैंने अपने छात्र दिनों में आखिरी बार सी में प्रोग्राम किया था, लेकिन मेरी जिज्ञासा बढ़ गई और मैंने काम करना शुरू कर दिया। लोहे के इस टुकड़े पर प्रलेखन इंटरनेट पर मौजूद है , हालांकि, कोड में टीसीपी / आईपी के साथ काम करने के अच्छे उदाहरण नहीं मिल सके। प्रलेखन में शामिल होने, सिगरेट और चाय पर स्टॉक करने और रेक के बीच पैंतरेबाज़ी करने के लिए कुछ भी नहीं बचा था। एक रेक बहुत था। दरअसल, इसीलिए मैंने यह लेख लिखा है - दूसरों के लिए इसे आसान बनाने के लिए।

बहुत सारे AT कमांड होंगे, बहुत ज्यादा कोड नहीं, और बहुत सारे अक्षर।

क्या जरूरत थी


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

नतीजा क्या हुआ


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

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

और यह कैसा दिखता है?


विंडोज 7 के तहत प्रोग्रामिंग और परीक्षण किया गया था। परिणामस्वरूप कोड इस लेख के लिए मुख्य सामग्री बन गया। मैं कोड को पूरी तरह से उद्धृत नहीं करूंगा और उस पर टिप्पणी नहीं करूंगा, बल्कि इसके बजाय मैं जीएसएम मॉड्यूल के साथ स्थापित करने और काम करने के लिए एल्गोरिदम दिखाऊंगा।

कोड द्वारा आवश्यक कार्य:

कोड प्रदान करता है कि कार्य हैं:

सीरियल पोर्ट के साथ कैसे काम करें


यह काफी सरल है। लक्ष्य माइक्रोकंट्रोलर के तहत USART के माध्यम से डेटा भेजने / प्राप्त करने के लिए मैक्रो हैं, लेकिन चूंकि यह एक स्थिर कंप्यूटर से इस तरह के कोड को डीबग करना आसान है, इसलिए मुझे USB <-> USART एडाप्टर और जीएसएम मॉड्यूल के साथ प्रदान किया गया था। यह केवल विंडोज के तहत सीरियल पोर्ट के साथ काम करने का तरीका जानने के लिए बना रहा। यह सरल निकला। संक्षेप में, सीरियल पोर्ट ओएस में एक नियमित फ़ाइल के रूप में दिखाई देता है, जानकारी ReadFile और WriteFile फ़ंक्शन द्वारा प्रेषित की जाती है। आपको केवल SetCommTimeouts और SetCommState फ़ंक्शन का उपयोग करके कुछ पैरामीटर सेट करने की आवश्यकता है।

यहाँ पोर्ट इनिशियलाइज़ेशन फंक्शन कैसा दिखता है:
 uint16_t init_serial_port(char *port_name) { COMMTIMEOUTS timeouts; DCB parameters; int result; serial_port_handle = CreateFile(port_name, // "\\\\.\\COMx" GENERIC_READ | GENERIC_WRITE, 0, //         NULL, OPEN_EXISTING, 0, NULL); if (serial_port_handle == INVALID_HANDLE_VALUE) { printf("Error opening a serial port!\n"); return 1; } //        timeouts.ReadIntervalTimeout = 100; //          timeouts.ReadTotalTimeoutMultiplier = 0; //     ,      //   timeouts.ReadTotalTimeoutConstant = 1000; //   ,      ,     . timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 1000; result = SetCommTimeouts(serial_port_handle, &timeouts); if (result == 0) { printf("Error setting timeouts for serial port!\n"); close_serial_port(); return 1; } //        -   // ,   , 1 -. memset(¶meters,0,sizeof(parameters)); parameters.DCBlength = sizeof(DCB); GetCommState(serial_port_handle, &parameters); parameters.BaudRate = (DWORD)BAUD_RATE; parameters.ByteSize = 8; parameters.Parity = NOPARITY; parameters.StopBits = ONESTOPBIT; parameters.fAbortOnError = TRUE; parameters.fDtrControl = DTR_CONTROL_DISABLE; parameters.fRtsControl = RTS_CONTROL_DISABLE; parameters.fBinary = TRUE; parameters.fParity = FALSE; parameters.fOutX = FALSE; parameters.fInX = FALSE; parameters.XonChar = (uint8_t)0x00; parameters.XoffChar = (uint8_t)0xff; parameters.fErrorChar = FALSE; parameters.fNull = FALSE; parameters.fOutxCtsFlow = FALSE; parameters.fOutxDsrFlow = FALSE; parameters.XonLim = 128; parameters.XoffLim = 128; result = SetCommState(serial_port_handle, &parameters); if (result == 0) { printf("Error setting serial port parameters!\n"); close_serial_port(); return 1; } return 0; } 


जीएसएम मॉड्यूल के साथ संचार कैसे होता है


सीरियल पोर्ट कॉन्फ़िगर होने के बाद, एटी कमांड्स को भेजा जा सकता है। पहला कमांड अनुक्रम "AT\r" होना चाहिए, जिससे मॉड्यूल सीरियल पोर्ट पर बॉड दर को स्वचालित रूप से कॉन्फ़िगर कर सके। इसके बाद पोर्ट से प्राप्त किया जा सकने वाला उत्तर "AT\r\r\nOK\r\n" जैसा दिखेगा।

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

 void at_send(char *cmd, uint16_t size) { uint16_t result; cmd[size - 1] = '\r'; result = puts_serial(cmd, size); return; } uint16_t at_recv(uint8_t *buffer, uint16_t size) { uint16_t result; result = gets_serial(buffer, size); return result; } 

कमांड भेजने और प्रतिक्रिया प्राप्त करने के लिए सहायक कार्य कुछ इस तरह दिखते हैं।

मॉड्यूल प्रारंभिक


मॉड्यूल को स्थापित करने के लिए कोड में सबसे बड़ा कार्य जिम्मेदार है। प्रारंभ में कई एटी कमांड्स भेजे जाते हैं। मैं मॉड्यूल को भेजे गए आदेश में उनका वर्णन करूंगा। मैं विशेष रूप से तर्कों और उत्तर विकल्पों का विस्तार से वर्णन नहीं करता हूं, क्योंकि वे प्रलेखन में पाए जा सकते हैं।

इन आदेशों को निष्पादित करने के बाद, मॉड्यूल ऑपरेशन के लिए तैयार हो जाएगा। अच्छी तरह से या नहीं। यहाँ यह कितना भाग्यशाली है

स्थापना और वियोग


कनेक्शन "AT+CIPSTART=index,"mode","address","port"" कमांड "AT+CIPSTART=index,"mode","address","port""

ध्यान दें कि UDP प्रोटोकॉल का उपयोग करते समय, डिफ़ॉल्ट रूप से, डेटाग्राम को केवल एक पते से भेजा और प्राप्त किया जाएगा। UDP को पूर्ण रूप से उपयोग करने और किसी भी पते से डेटा भेजने / प्राप्त करने के लिए, आप "AT+CIPUDPMODE" कमांड द्वारा कॉन्फ़िगर किए गए तथाकथित उन्नत UDP मोड का उपयोग कर सकते हैं। विवरण के लिए, प्रलेखन देखें।

कमांड के जवाब में, आप कई उत्तर प्राप्त कर सकते हैं। यदि सब कुछ ठीक है, तो मानक "OK" बाद "OK" थोड़े समय के बाद, आप तीन में से एक उत्तर प्राप्त कर सकते हैं:

आप "AT+CIPCLOSE=index" कमांड के साथ कनेक्शन समाप्त कर सकते हैं। आप "AT+CIPSHUT" का उपयोग करके सभी कनेक्शनों को डिस्कनेक्ट कर सकते हैं और GPRS इंटरफ़ेस को निष्क्रिय कर सकते हैं।

डेटा ट्रांसफर


डेटा को "AT+CIPSEND=index,length" कमांड के साथ प्रेषित किया जाता है, जहां index उस कनेक्शन को इंगित करता है जिसके माध्यम से डेटा प्रेषित किया जाना चाहिए, और length डेटा पैकेट की length निर्धारित करती है। वैसे, आप "AT+CIPSEND=?" कमांड का उपयोग करके प्रत्येक कनेक्शन के लिए MTU का पता लगा सकते हैं। ।

यदि सब कुछ ठीक है, तो कमांड के जवाब में मॉड्यूल ">" शीघ्र जारी करेगा, जिसके बाद सीरियल पोर्ट पर डेटा भेजा जाना चाहिए। जैसे ही मॉड्यूल length बराबर बाइट्स की संख्या प्राप्त करता है, यह "index,SEND OK" जैसे कुछ कहेगा। सामान्य तौर पर, आप length पैरामीटर का उपयोग नहीं कर सकते हैं, हालांकि, इस मामले में, डेटा पैकेट के अंत में 0x1A चरित्र का उपयोग करके संकेत दिया जाना चाहिए, टर्मिनल में संयोजन Ctrl + Z। मनमाने डेटा के हस्तांतरण के लिए, यह विकल्प स्पष्ट रूप से उपयुक्त नहीं है।

जैसा कि आप देख सकते हैं, डेटा ट्रांसफर बहुत जटिल प्रक्रिया नहीं है। इसलिए, हम सबसे दिलचस्प - डेटा रिसेप्शन की ओर मुड़ते हैं।

डेटा का स्वागत


जैसे ही जीएसएम मॉड्यूल डेटा प्राप्त करता है, यह सीरियल पोर्ट को "+CIPRXGET:1,index\r\n" के रूप में "+CIPRXGET:1,index\r\n" । मुझे ईमानदारी से पता नहीं है कि यूनिट का क्या मतलब है, क्योंकि मॉड्यूल का यह फ़ंक्शन खराब रूप से प्रलेखित है, लेकिन यह मेरे सभी संदेशों में एक पैकेट प्राप्त करने के बारे में दिखाई देता है।

मैं इस सोच से खुश नहीं था कि मुझे एक या दूसरे तरीके से मॉड्यूल संदेशों की निगरानी करनी होगी। हालांकि, डिबगर के साथ थोड़ा खेलने के बाद, मुझे पता चला कि मॉड्यूल किसी अन्य अतुल्यकालिक संदेश नहीं भेजता है, और यह भी कि किसी भी एटी-कमांड को निष्पादित करने के बाद यह संदेश बफर की शुरुआत में दिखाई देता है। चूँकि मैंने एक मैक्रो को "\r\r\n" लिए खोज कर कमांड से प्रतिक्रिया को अलग करने के लिए संकलित किया, इससे किसी भी तरह से मुझे प्रभावित नहीं हुआ। इसलिए डेटा प्राप्त करने का कार्य काफी सरलता से लागू किया गया था।

तो, आप "AT+CIPRXGET=2,index,length" कमांड के साथ डेटा प्राप्त कर सकते हैं। दो मतलब रिसेप्शन मोड, इस मामले में, बाइट्स केवल सीरियल पोर्ट में डाले जाते हैं। प्रोग्रामेटिक फ्लो कंट्रोल के साथ टकराव को रोकने के लिए, आप एक हेक्स पाठ के रूप में डेटा प्राप्त करने के लिए भी सेट कर सकते हैं। मुझे इसकी आवश्यकता नहीं थी, क्योंकि मैं प्रवाह नियंत्रण का उपयोग बिल्कुल नहीं करता हूं। length पैरामीटर उस डेटा पैकेट का आकार निर्धारित करता है जिसे हम एक बार में प्राप्त करना चाहते हैं।

जवाब में, हमें "+CIPRXGET:2,index,received,excess\r\n__DATA__\r\nOK\r\n" जैसा कुछ मिलता है। received फ़ील्ड में __DATA__ डेटा __DATA__ में बाइट्स की संख्या शामिल होगी, और excess फ़ील्ड में मॉड्यूल बफ़र में अपनी बारी की प्रतीक्षा में बाइट्स की संख्या शामिल होगी। इसलिए यदि received क्षेत्र शून्य है, तो आप ईमानदारी से घोषणा कर सकते हैं कि प्राप्त करने के लिए कुछ भी नहीं है। दरअसल, इसका उपयोग करते हुए, मैंने डेटा प्राप्त करने के लिए एक गैर-अवरुद्ध फ़ंक्शन लागू किया।

निष्कर्ष में


मैं दृढ़ता से अनुशंसा करता हूं कि आपको कोड लिखने से पहले PuTTY के साथ एटी कमांड की आदत हो, जो सीरियल पोर्ट के साथ बहुत अच्छा काम करता है।

मुझे उम्मीद है कि इस लेख में दी गई जानकारी से किसी को अपने SIM900 के लिए कोड लिखने में मदद मिलेगी। यह संभव है कि ऊपर वर्णित जीएसएम मॉड्यूल के साथ काम करने के सिद्धांत, अन्य मॉडलों के मॉड्यूल पर लागू किए जा सकते हैं, और, संभवतः, निर्माता।

Source: https://habr.com/ru/post/In119030/


All Articles