Przykład obsługi modemu GSM Quectel M10 w systemie z mikrokontrolerem STM32
W przykładowej aplikacji pokażemy jak wysłać wiadomość SMS korzystając z modemu Quectel M10 (w prezentowanym przykładzie w module EB-M10 z oferty firmy Soyter) sterowanego przez mikrokontroler STM32. W przykładzie wykorzystano zestaw uruchomieniowy STM32Butterfly2 oraz moduł EB-M10, połączenia pokazane są na rysunku 1. Należy pamiętać, aby zasilacz systemu dysponował odpowienią wydajnością (moduł M10 potrzebuje do 2 A).
Rys. 1. Sposób połączenia modułu EB-M10 i zestawu startowego STM32Butterfly2
Komunikacja z modemem
Do komunikacji z modemem wystarczy jeden interfejs UART oraz jedna linia GPIO służąca do włączania modemu. Po dołączeniu zasilania do modemu należy odczekać 2 sekundy, następnie można uruchomić modem podając stan wysoki na linię PWRKEY. Od tej pory możemy komunikować się z modemem przez UART. Modem nie wymaga użycia konkretnej prędkości interfejsu UART, ponieważ automatycznie ją rozpozna (zakres prędkości to 4800…115 200 bps), należy tylko wysłać trzykrotnie sekwecję AT\x0D. W przykładowym zestawie uruchomieniowym procesor STM32 taktowany jest kwarcem o częstotliwości 14,7456 MHz, a szyna APB1 zegarem o częstotliwości 58,9824 MHz, stąd funkcja konfigurująca USART2 wygląda następująco:
void USART2_Init (void) { int i; // Enable AFIO, GPIOD clocks RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPDEN; // Remap USART2 to PD5, PD6 AFIO->MAPR |= AFIO_MAPR_USART2_REMAP; // PD5 - tx, PD6 - rx GPIOD->CRL &= ~(0xFF << 20); GPIOD->CRL |= (0xB << 20) | (0x4 << 24) | (0x3 << 28); // Enable USART2 clk RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // Set baudrate to 115200 (NOTE: 14.7456 MHz resonator is used!!!) USART2->BRR = 0x200; // Configure USART2 USART2->CR1 = (( 1UL << 2) | // Enable RX ( 1UL << 3) | // Enable TX ( 0UL << 12) ); // 1 start bit, 8 data bits USART2->CR2 = 0x0000; // 1 stop bit USART2->CR3 = 0x0000; // No flow control for (i = 0; i < 0x1000; i++) __NOP(); // Avoid unwanted output USART2->CR1 |= USART_CR1_UE; // Enable USART }
Wysyłając rozkaz do modemu musimy zakończyć go znakiem CR (0x0D), odpowiedź modemu będzie rozpoczęta i zakończona sekwencją CRLF (0x0D, 0x0A), przykładowo:
wysyłamy: ATE0<CR>
odbieramy: <CR><LF>OK<CR><LF>
Jeśli karta SIM wymaga podania kodu PIN wysyłamy go rozkazem AT+CPIN=xxxx, gdzie w miejsce znaków ‘xxxx’ wprowadzamy numer PIN. W przykładzie użyto startera SIM, który nie wymaga kodu PIN. Funkcja inicjalizująca modem:
void M10_Init() { unsigned int i; char res[128]; // PWRON = 1 del(60); GPIOD->ODR |= (1 << 7); // LED on GPIOB->ODR &= ~1; // Wait for Quectel M10 to start del(60); for (i=0; i < 3; i++) { M10_SendCmd("AT\x0D", &res[0]); del(3); } // LED off GPIOB->ODR |= 1; // Echo off M10_SendCmd("ATE0\x0D", 0); }
Teraz możemy przystąpić do wysłania wiadomości. Przykładowy program czeka w nieskończonej pętli na naciśnięcie joysticka, po naciśnięciu wysyłana jest wiadomość SMS (w przykładzie użyto numeru +48123123123, oczywiście przy uruchamianiu przykładu należy wstawić tam właściwy numer odbiorcy).
int main() { USART2_Init(); M10_Init(); while(1) { if ((GPIOC->IDR & (1 << 7)) == 0 ) { M10_SendSMS("+48123123123", "Quectel M10 test..."); } } }
Funkcja wysysłająca wiadomość:
void M10_SendSMS(char * telephone, char * message) { char res[128], cmd[256]; // LED on GPIOB->ODR &= ~1; // Set text mode M10_SendCmd("AT+CMGF=1\x0D", &res[0]); // Send SMS message sprintf(cmd, "AT+CMGS=\"%s\"\x0D", telephone); M10_SendCmd(cmd, 0); sprintf(cmd, "%s\x1A", message); M10_SendCmd(cmd, &res[0]); // LED off GPIOB->ODR |= 1; }
W tej funkcji wysyłamy najpierw polecenie AT+CMGF=1, które określa format wysyłanej wiadomości jako tekstowy, następnie wysyłamy polecenie AT+CMGS=”+48xxxxxxxxx”\0x0D po którym wysyłamy treść wiadomości, na koniec wysyłamy znak Ctrl+Z, czyli 0x1A (26 dziesiętnie). Po chwili wiadomość powinna dotrzeć do odbiorcy.
W powyższym przykładzie założono optymistyczny wariant, czyli mamy zasięg, komunikacja przebiega bez problemów itd. W rzeczywistych aplikacjach koniecznie należy uwzględnić wszelkie możliwe problemy, czyli m.in. trzeba sprawdzać odpowiedzi modemu i reagować na ewentualne błędy!