ARMアヌキテクチャ甚のSTM32およびmikroCコンパむラの最初のステップ-パヌト3-UARTおよびGSMモゞュヌル

さお、マむクロコントロヌラヌのプログラミングに぀いお少し孊んだので、それを倖郚の䞖界ず接続しおみたしょう。 STM32ハヌドりェアむンタヌフェむスモゞュヌルは、倚くの異なる倖郚むンタヌフェむスをサポヌトしおいたす。 最も䞀般的に䜿甚されるUARTむンタヌフェヌスから始めたしょう。 ここずここでどんな皮類のむンタヌフェヌスが読めるか。



MKをUART経由でコンピュヌタヌに接続しおみたしょう。 これを行うには、PL2303チップに基づいた単玔なUSB-UART TTL3.3VMKが3.3 Vレベルであるこずを忘れないでくださいコンバヌタヌを䜿甚したす。

画像

STM32には3぀のUARTむンタヌフェむスがありたす。 䜿甚する前に、MKでシリアルトランシヌバヌを構成する必芁がありたす。 これを行うには、次のコマンドを䜿甚したす。



UART_Init(baud_rate);
      
      





このコマンドは、暙準パラメヌタヌハヌドりェアパリティなしの8デヌタビットでbaud_rate速床たずえば、9600たたは19200 kbsでUARTを起動したす。



非暙準モヌドでUARTを起動する必芁がある堎合は、次を䜿甚したす。



 UARTx_Init_Advanced(baud_rate, data_bits, parity, stop_bits);
      
      





ここに





デヌタバむトをUARTに転送するには、次を䜿甚したす。



 UARTx_Write(unsigned int _data); UARTx_Write(char _data);
      
      





たたは、デヌタの配列の堎合テキストたたは倀のセットに関係なく、関数に枡したす。



 UARTx_Write_Text(char * UART_text);
      
      





配列ぞのポむンタヌを䜿甚したす。



簡単なプログラムを曞きたしょう



 char ourtext[] = "Hellow world"; char *txt_pnt; void main() { UART1_INIT (19200); delay_ms (5); //  5  txt_pnt = &ourtext; UART1_Write_Text(txt_pnt); while (1) { } {
      
      





RX STM32をTXコンバヌタヌに接続し、 TX STM32をRXコンバヌタヌに接続し、コンピュヌタヌのUSBポヌトに挿入したす。 タヌミナルプログラムを開き PuTTYを䜿甚、シリアルモヌド、ポヌト速床19200 kbsなどおよびUSB-TTLコンバヌタヌの接続時に衚瀺されるCOMポヌトを遞択したすデバむスマネヌゞャヌの[COMおよびLPTポヌト]ブランチで確認できたす。 OPEN。」 タヌミナルりィンドりにテキストが衚瀺されたす。



画像



数バむトのデヌタを連続しお送信するこずにより、前のデヌタの送信が終了したかどうかを制埡する必芁がありたす。 各UARTには独自のステヌタスレゞスタがありたす。



USART1_SR 。 USART1_SRbits.TCビットは転送の終了を担圓し、 UARTx_Write_Textchar * UART_text関数自䜓は、次のバむトを送信する前に、前のバむトの転送の完了を制埡したす。



UARTマむクロコントロヌラヌからデヌタを読み取るには、次の関数を䜿甚したす。



 char UARTx_READ()
      
      





UARTのバッファに受信バむトがあるこずを知るために、次の関数を䜿甚したす。



 UART_Data_Ready()
      
      



受信したバむトがバッファにある堎合は1を返し、ない堎合は0を返したす。 この堎合、コントロヌラヌUARTが䜕かを受け入れたかどうかを垞に監芖する必芁がありたす。 たずえば、ボヌドのLEDを点灯する文字「A」ASCIIコヌド65を受け取ったずきに詊しおみたしょう。



 void main() { GPIO_Digital_Output(&GPIOb_BASE, _GPIO_PINMASK_1); UART1_INIT (19200); delay_ms (5); UART1_Write_Text("WAIT CHAR A"); while(1) { if (UART1_Data_Ready()) //       UART { if (UART1_READ()== 65) //    65 { GPIOb_ODR.b1 = 1; //   } } } }
      
      





垞にUARTレゞスタのステヌタスをポヌリングするこずでMKを占有しないために、割り蟌みを䜿甚できたすおよび䜿甚する必芁がありたす。 次のバむトを受信するず、UARTからハヌドりェア割り蟌みが呌び出され、シリアルむンタヌフェむスで受信したデヌタを凊理できたす。 「RX UART」むベントで割り蟌みを有効にするには、䜿甚するUARTモゞュヌルのレゞスタCR1のRXNEIEビットに論理倀1を曞き蟌む必芁がありたす。



 UART1_init (19200); NVIC_IntEnable(IVT_INT_USART1); //    IVT_INT_USART1 EnableInterrupts(); //   USART1_CR1bits.RXNEIE = 1; //      delay_ms (5);
      
      





タむマヌず同様に、割り蟌みが発生するず、サブルヌチンが呌び出されたす。



 void our_int() iv IVT_INT_USART1 { if (UART1_READ()== 65) GPIOb_ODR.b1 = 1; //   A =   if (UART1_READ()== 66) GPIOb_ODR.b1 = 0; //   B =   }
      
      





UARTを䜿甚するず、MKをコンピュヌタヌだけでなく、倚くの呚蟺機噚にも接続できたす。 たずえば、広く利甚可胜なGSMモゞュヌルSIM800Lを考えおみたしょう。 このモゞュヌルはすでに小さなボヌドにはんだ付けされおいたす。 そのような安䟡は䞭囜で泚文するこずができたす。 モゞュヌルの操䜜に必芁なすべおの信号は、このボヌドのピンに出力されたす。さらに、ボヌドにはSIMカヌド甚のホルダヌがありたす。







唯䞀䞍䟿なのは、このボヌドに3.7〜4.2 Vの電圧を䟛絊する必芁があるため、倖郚リチりム電池を接続するか、4.1 Vの出力電圧に倉換する必芁があるこずです。 、私は、特定の問題ではないず思いたす。



RXモゞュヌルがTX MKに、たたその逆も同様であるこずを忘れずに、モゞュヌルをMKに接続したす。 Mapleミニモゞュヌルの堎合、 RXを26ピンPA9 / UART1TXに、TXを25PA10 / UART1RXに接続したす。



モゞュヌルず通信するために、いわゆるATコマンドが䜿甚されたす。 これは、モデムが理解し、それらに応じお特定のアクションを実行する端末コマンドのセットです。 デヌタシヌトのモゞュヌルのコマンドに慣れるこずができたす。さらに、このモゞュヌルでの䜜業がよく描かれおいる良い蚘事がありたす。



2぀のUARTマむクロコントロヌラヌ、MK-GSM通信甚のUART1ずMK通信甚のUART3コンピュヌタヌ端末を䜿甚したす。



UARTを初期化する



 void main() { UART1_init (19200); //  UART     UART3_init (19200); //  UART    GSM  NVIC_IntEnable(IVT_INT_USART1); //       GSM USART1_CR1bits.RXNEIE = 1; EnableInterrupts(); delay_ms(200); while (1) { } }
      
      





私たちのプログラムは比范的倚数の関数を必芁ずするので、それらを別のSファむルに転送したす。 これを行うには、MicrocでCtrl + Nを抌しお、プロゞェクトに別のファむルを䜜成したす䟋「GSM_SIM800L.」。 コンパむラがいく぀かの関数を別のファむルで怜玢する必芁があるこずを理解するために、メむンs-フ​​ァむルの先頭に行を远加したす同じ方法でラむブラリを接続するこずもできたす。



 #include "GSM_SIM800L."
      
      





たず、ファむル「GSM_SIM800L.s」に、ATモゞュヌルにコマンドを送信し、ATモゞュヌルから応答を受信する関数を䜜成したす。



 static char GSM_TEMP[256]; //    GSM  unsigned short com_status; //    0 -   , 1 - , 2 -     (  ) unsigned short com_mode = 0; 0 -   , 1 -   void Clear_GSM_Bufer () //    GSM { unsigned int cnt; for (cnt=0; cnt<256; cnt++) GSM_TEMP[cnt] = 0; cntas = 0; } short int gsm_send_at (char *at_cmd) //   AT ,  MicroC       { unsigned int brk; //       Clear_GSM_Bufer (); //   com_status = 2; //  " " com_mode = 0; //     UART1_Write_Text (at_cmd); //   AT -  while (com_status == 2 && brk < 50000) //  com_status   1  0 { brk++; delay_us(2); } com_mode = 1; //    ,    return com_status; //   } void gsm_read() iv IVT_INT_USART1 { GSM_TEMP[cntas] = UART1_READ(); //    UART   GSM_TEMP if (cntas> 255) cntas = 0; else cntas++; //              if (com_mode == 0) //      { if (strstr(GSM_TEMP, "OK\r\n") != 0) com_status = 1; //  - com_status = 1 if (strstr(GSM_TEMP, "ERROR\r\n") != 0) com_status = 0; //Error - com_status = 0 } }
      
      





MicroCでは、文字列は、文字列の終わりを衚す倀00NULLで終わるchar文字の配列です。 関数ぞの匕数ずしおの文字列は、 char型ぞのポむンタヌによっお指定されたすたずえば、 char * nasha_stroka 。 MicroCは、暙準のC_String.hラむブラリの機胜をサポヌトしおいたす。 たずえば、䞊蚘で䜿甚した関数



 char *strstr(char *s1, char *s2);
      
      





この関数は、ストリング* s1内の* s2ポむンタヌで指定されたサブストリングを怜玢したす。 関数は、芋぀かった郚分文字列* s2ぞのポむンタヌを返したす。 実際には、文字列* s1の先頭* s2から末尟 NULL文字たでの文字列を返したす 。 サブストリング* s2が芋぀からない堎合、関数はNULLを返したす 。 Cのデフォルトでは、名前で配列を枡すこずは、配列の先頭ぞのポむンタヌです。 特定の芁玠の配列cを枡す必芁がある堎合は、 array_name [ind] を䜿甚したす。



始めるには、モゞュヌルに単玔なコマンド「AT \ r」を䞎える必芁がありたす-モゞュヌルは「OK \ r \ n」ず答え、UARTの速床を調敎する必芁がありたす。 ATコマンドは、改行文字"\ r"で終了したす。 コマンドに察するモゞュヌルの応答は耇数の行で構成でき、垞に「OK \ r \ n」たたは「ERROR \ r \ n」で終わりたす。 着信コヌルやSMSメッセヌゞなどのモゞュヌルメッセヌゞは垞に"\ r \ n"で終了し、通垞は最埌の行のみが参考になるずいう事実により、生掻が簡玠化されおいたす。 そのような行の受信、私は非同期応答を呌び出したす完党に正しいわけではありたせんが、そうさせおください。



モゞュヌルの構成に必芁ないく぀かのコマンドを実行したしょう。 簡単にするために、モゞュヌルの応答を制埡したせんが、各コマンドの実行䞭に状態が等しいかどうかを確認するこずは難しくありたせん。





 gsm_send_at ("AT\r"); gsm_send_at ("ATE0\r"); gsm_send_at ("AT+CMGD=1,4\r"); gsm_send_at ("AT+CMGF=1\r"); gsm_send_at ("AT+DDET=1\r");
      
      





モゞュヌルの応答を返す別の関数を䜜成したす芁求のステヌタスだけでなく、必芁なものです。モゞュヌル䞊のデヌタは、ほずんどの堎合、行の䞀郚を2蟺から制限できる応答機胜に関する正芏衚珟を䜿甚しお、ATコマンドぞの応答を蚘述したす既知の文字。



 char *gsm_at_parse (char *at_cmd, char *beg_str, char *end_str) // *at_cmd =   // *beg_str =       // *beg_str =       { char *tempchar; if (gsm_send_at (at_cmd) == 1) //   { tempchar = strstr (GSM_TEMP, beg_str); //  beg_str tempchar = tempchar + strlen(beg_str); *(strstr (tempchar, end_str)) = 0; //  NULL    end_str return tempchar; } }
      
      





たずえば、 「AT + GMM \ r \ n」は、 「\ r \ n SIM_800L \ r \ n \ r \ nOK \ r \ n」ずいう圢匏でモゞュヌル名を返したす。 最初の「\ r \ n」ず最埌の「\ r \ n \ r \ nOK \ r \ n」を 「バむトオフ」



 UART3_Write_Text (gsm_at_parse("AT+GMM\r", "\r\n", "\r\n\r\nOK\r\n")); \\   UART3 (    ,  ) UART3_Write_Text ("\r\n"); UART3_Write_Text (gsm_at_parse("AT+CCLK?\r", ",", "+")); \\      UART3_Write_Text ("\r\n"); UART3_Write_Text (gsm_at_parse("AT+CSPN?\r", ": \"", "\""); \\    GSM. UART3_Write_Text ("\r\n");
      
      





モゞュヌルのATコマンドには、コマンド「AT + CREG\ R」がありたす。 このコマンドは、ネットワヌクぞの登録に関するモゞュヌルのステヌタスを返したす。 すべおが正垞で、モゞュヌルが登録されおいる堎合、応答は次のようになりたす。 「\ r \ n + CREG0,1 \ r \ n \ r \ n \ OK \ r \ n」 0,0-モゞュヌルは登録されおおらず、ネットワヌク怜玢はありたせんたずえば、SIMカヌドが挿入されおいない、 0.2-モゞュヌルは登録されおいたせん、ネットワヌクが怜玢されおいたす。 モゞュヌルのネットワヌクステヌタスをチェックする関数を䜜成し、さらにGSMネットワヌクの信号レベルを返したすこのためにATコマンド「AT + CSQ \ r」がありたす 。



 short int gsm_net_status () { char *tempchar[7]; //   int sgr; //      dBi if ( gsm_send_at("AT+CREG?\r") == 1) //     { if (strstr(GSM_TEMP, "0,1")) //    -   "+CREG: 0,1" { tempchar = GSM_AT_PARSE ("AT+CSQ\r",": ","," ); //  ,    +CSQ: 17,0,     :  , sgr = atoi(tempchar); //     sgr = -115 + (sgr * 2); //    dBi return sgr; //   } } return 0; //   0 -      . }
      
      





これでモゞュヌルが機胜したした。 圌に電話するず、圌は次のような行を発行したす

"\ r \ n RING \ r \ n + CLIP" + 380XXXXXXXX "、145、" ",," "、0 \ r \ n" 。 着信SMSの堎合、応答は"\ r \ n + CMTI" SM "、10 \ r \ n"になりたす。ここで、10はSMSが10番のメモリに栌玍されるこずを意味したす。 割り蟌みハンドラでそれらを受け入れお凊理したす。 私は、私が最も必芁ずする答えの認識を曞きたした。 原則ずしお、これがどのように行われるかは、以䞋のコヌドから明らかです。



 char *eol //  ,   "\r\n" char callingnumber[14]; //   , 13   NULL  char last_sms[4]; //    char dtmf_in[2]; //  DTMF  unsigned short callnow; //   unsigned short active_call; //   unsigned short sms; //    void gsm_read() iv IVT_INT_USART1 { GSM_TEMP[cntas] = UART1_READ(); if (cntas> 255) cntas = 0; else cntas++; if (com_mode == 0) { if (strstr(GSM_TEMP, "OK\r\n") != 0) com_status = 1; if (strstr(GSM_TEMP, "ERROR\r\n") != 0) com_status = 0; } //        if (com_mode == 1) { if (cntas> 2) eol = strstr(&GSM_TEMP[2], "\r\n"); else eol = 0; //    if (eol != 0) //    { if (strstr(&GSM_TEMP, "+CLIP") != 0) //     "+CLIP"       { callnow=1; //   temp = strstr(GSM_TEMP, "\"+"); //     + -     strncpy (callingnumber, temp+1, 13); //    callingnumber[]  ,  13  } if (strstr(&GSM_TEMP, "CARRIER") != 0) //   "NO CARRIER" { *callingnumber=0; //      ( NULL   ) callnow=0; //     active_call=0; } if (strstr(&GSM_TEMP, "DTMF") != 0) { temp = strstr(GSM_TEMP, " "); //SIM800    DTMF ,          DTMF . strncpy(dtmf_in,temp+1,1); //   dtmf_in[] } if (strstr(GSM_TEMP, "CMTI")!=0) //    { temp = strstr(GSM_TEMP, ","); // ",",       strncpy (last_sms, temp + 1, eol - (temp + 1)); //   last_sms[] sms=1; //   } Clear_GSM_Bufer (); //  } } }
      
      





プログラムルヌプ内のcallnow倉数の倀を監芖するこずにより、着信呌び出しに぀いお調べるこずができたす。 コマンド「ATA \ r」で電話を取り、コヌルをドロップしたす- 「ATH0 \ r」 。



 har *nashomer[14] = "+380931234567" if (callnow == 1) { if (strcmp(&callingnumber, "nashomer")==0) // strcmp (*s1, *s2) -  2 ,  0    s1 = s2 { gsm_send_at ("ATA\r"); // AT  " " active_call = 1; //      . } else { gsm_send_at ("ATH0\r"); // AT  " " callnow = 0; //    } }
      
      





同様に、 sms倉数の倀を制埡しお、着信SMSメッセヌゞに぀いお孊習したす。 コマンド「AT + CMGR = 2 \ r」で読み取るこずができたす。ここで、N = SMSメッセヌゞの数です。 応答ずしお、モゞュヌルは「\ r \ n + CMGR」のような文字列を返したす。RECREAD "、" + 380XXXXXXXX "、" "、" 17/02 / 1,115746 + 2 "\ r \ n hellow habrahabr \ r \ n \ r \ nOK \ r \ n "。 この行を解析するには、関数を䜜成したす。



 char *gsm_read_sms (char *sms_num, unsigned short int sms_field) //    ( )      ( ), //1 -  , //2 -   , //3 -   { char sms_at[30]; short int res_at; strcat (sms_at, "AT+CMGR="); strcat (sms_at, sms_num); strcat (sms_at, "\r"); res_at = gsm_send_at (sms_at); if (res_at == 1 && sms_field == 1) { *(strstr (GSM_TEMP, "\",\"\",\"")) = 0; sms = 0; return strstr(GSM_TEMP, "\"+") + 1; } if (res_at == 1 && sms_field == 2) { *(strstr(strstr(GSM_TEMP, "\",\"\",\"") + 6, "+")) = 0; sms = 0; return strstr(GSM_TEMP, "\",\"\",\"") + 6; } if (res_at == 1 && sms_field == 3) { *(strstr (GSM_TEMP, "\r\n\r\nOK\r\n")) = 0; sms = 0; return strstr(GSM_TEMP, "\"\r\n") + 3; } return 0; //   0 }
      
      





䟋



 UART3_Write_Text (gsm_read_sms("5",1)); //         5 UART3_Write_Text (gsm_read_sms("2",3)); //        2
      
      





SMSを送信するには、ATコマンド「AT + CMGS =」+ 380XXXXXXXX \ r "を䜿甚したす。このコマンドは、文字を返したす " \ r \ n> "-入力する招埅状。この招埅状をモゞュヌルの応答でキャッチできたす。 100ミリ秒。SMSテキストをUARTに送信したす。UARTはASCIIコヌド26の文字で終了する必芁がありたす



 UART1_Write_Text ("AT+CMGS=\""); UART1_Write_Text (nomer); //    UART1_Write_Text ("\"\r"); Delay_ms (100); UART1_Write_Text (text); //   UART1_Write (26);   
      
      





この蚘事では、GSMモゞュヌルずSTM32 MKのUARTむンタヌフェむスの䞡方の機胜のごく䞀郚に぀いおのみ説明したす。 それにもかかわらず、䞊蚘の情報がマむクロコントロヌラに実装されたシリアルむンタヌフェヌスの動䜜を理解するのに圹立぀こずを願っおいたす。



次の蚘事では、I2Cバスずは䜕か、その操䜜方法、およびHD44780コントロヌラヌに基づくLCDむンゞケヌタヌを、パラレルバスおよびI2C I / Oラむン゚クスパンダヌを介しおSTM32に接続する方法に぀いお説明したす。



All Articles