Интерес к GSM модулям возникает когда появляется потребность в удаленном управлении каким либо устройством. GSM модуль может выполнять все те же действия, какие может производить сотовый телефон: совершение и прием звонков, передача/прием SMS, соединение с интернетом при помощи технологии GPRS и т.п. Также к данному модулю можно подсоединить микрофон и громкоговоритель и совершать с его помощью мобильные звонки (на сотовые телефоны). Это открывает возможность к множеству интересных проектов, которые можно осуществить с помощью микроконтроллеров. В этой статье мы рассмотрим подключение и взаимодействие GSM модуля (SIM900A) с микроконтроллером ATmega16 (семейство AVR). На собранной конструкции будет продемонстрирована прием и передача сообщений с помощью GSM модуля.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega16 (купить на AliExpress).
- GSM модуль (SIM900 или любой другой) (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- Адаптер на 12В.
- JHD_162ALCD (ЖК дисплей 16x2) (купить на AliExpress).
- Кнопки.
- Резисторы 10 кОм (купить на AliExpress).
- Потенциометр (купить на AliExpress).
- 10 пиновый FRC кабель.
- Источник питания с напряжением 5 Вольт.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Программное обеспечение
CodeVisionAVR (или другое подобное, например, Atmel Studio)
SinaProg – для загрузки программы в микроконтроллер ATmega8 с помощью программатора USBASP. Можно использовать и другую аналогичную программу.
Общие принципы работы GSM модуля
GSM модуль можно использовать даже без микроконтроллера, используя для управления им набор команд управления модемом (AT commands). Как показано на приведенном рисунке GSM модуль имеет в своем составе адаптер последовательного синхронного/асинхронного порта (USART), поэтому он может быть напрямую соединен с компьютером при помощи модуля MAX232. А с использованием контактов Tx (передача) и Rx (прием) его можно подсоединить к микроконтроллеру. Также на плате GSM модуля вы можете видеть другие контакты, такие как MIC+, MIC-, SP+, SP- которые используются для подключения микрофона или громокоговорителя. GSM модуль можно запитать с помощью адаптера на 12В используя разъем для постоянного тока.
Вставьте вашу SIM карту в соответствующий слот модуля и подайте питание, при этом на плате должен загореться светодиод, свидетельствующий о подаче питания. Потом подождите минуту или чуть больше, вы увидите как красный (может использоваться и другой цвет) светодиод будет мигать каждые 3 секунды. Это будет означать что ваш модуль готов к установлению соединения используя вашу SIM карту. После этого вы можете подсоединить к нему сотовый телефон или микроконтроллер.
Управление GSM модулем с использованием набора команд управления модемом (AT commands)
Управлять GSM модулем можно единственным способом – используя набор команд управления модемом (AT commands). К примеру, если вы хотите узнать активен ли ваш GSM модуль вы передаете на него команду “AT” и модуль должен ответить на нее “OK”.
Весь список команд управления модемом (AT commands) можно найти в соответствующих справочниках (он весьма обширен), здесь же в нижеприведенной таблице вы можете увидеть наиболее часто используемые (востребованные) из этих команд.
AT | В ответ на эту команду передается OK для подтверждения того что модуль готов к работе |
AT+CPIN? | Проверить качество сигнала |
AT+COPS? | Найти имя провайдера услуг |
ATD96XXXXXXXX; | Звонок на определенный номер |
ATA | Ответить на входящий звонок |
ATH | Завершить текущий входящий звонок |
AT+COLP | Показать номер входящего звонка |
AT+VTS=(number) | Передать DTMF код. Вы можете использовать любое число на вашей мобильной клавиатуре (кейпаде) |
AT+CMGR AT+CMGR=1 | Прочесть сообщение на первой позиции |
AT+CMGD=1 | Удалить сообщение на первой позиции |
AT+CMGDA=”DEL ALL” | Удалить все сообщения с SIM карты |
AT+CMGL=”ALL” | Прочесть все сообщения с SIM карты |
AT+CMGF=1 | Установить SMS конфигурацию. “1” для установки текстового режима. |
AT+CMGS = “+91 968837XXXX” >Any Text<Ctrl+z> |
Передает SMS на определенный номер - 968837XXXX. Когда увидите “>” начинайте набирать текст. Нажмите Ctrl+Z чтобы передать текст |
AT+CGATT? | Проверить интернет соединение на SIM карте |
AT+CIPSHUT | Закрыть TCP соединение, то есть отключиться от интернета |
AT+CSTT = “APN”,”username”,”Pass” | Соединиться по GPRS используя ваш APN и пароль (Pass key). Их можно получить от вашего сотового оператора. |
AT+CIICR | Проверить имеется ли на вашей SIM карте пакет данных |
AT+CIFSR | Получить IP адрес сети вашей SIM карты |
AT+CIPSTART = “TCP”,”SERVER IP”,”PORT” | Установить соединение TCP IP |
AT+CIPSEND | Эта команда используется чтобы передать данные на сервер |
Для нашей схемы мы будем использовать команды AT+CMGF и AT+CMGS чтобы передавать сообщения.
Работа схемы
Схема соединений устройства на макетной плате приведена на следующем рисунке.
В схеме необходимо сделать следующие соединения:
1. Tx и Rx GSM модуля to Rx (Pin14) и Tx (Pin15) микроконтроллера Atmega16 соответственно.
2. Кнопки to PD5 (Pin19) and PD6 (Pin20).
3. Соединения с ЖК дисплеем:
• RS - PA 0
• R/W - PA1
• EN - PA2
• D4 - PA4
• D5 - PA5
• D6 - PA6
• D7 - PA7
Создание проекта для Atmega16 в программной среде CodeVision
Необходимо выполнить следующую последовательность действий.
Шаг 1. Откройте CodeVision, выберите в ней пункт меню File -> New -> Project. В появившемся диалоговом окне нажмите Yes.
Шаг 2. Откроется CodeWizard. Кликните в ней на первой опции, то есть AT90, затем нажмите OK.
Шаг 3. Выберите свой микроконтроллер, в нашем случае им будет Atmega16L.
Шаг 4. Кликните на USART. Выберите передатчик и приемник кликнув по ним как показано на рисунке.
Шаг 5: Кликните на "Alphanumeric LCD" и выберите "Enable Alphanumeric LCD support" как показано на рисунке.
Шаг 6: Выберите пункт меню Program -> Generate, Save and Exit. На этом этапе можно сказать, что половина работы уже выполнена. Но если кто не хочет использовать CodeVision то, разумеется, всю эту часть кода можно запрограммировать и вручную.
Шаг 7. Создайте новую папку на рабочем столе чтобы записывать туда наши файлы.
У нас будет 3 диалоговых окна (будут появляться последовательно одно за другим) для сохранения наших файлов.
Сделайте то же самое (что и на представленном рисунке) с двумя другими диалоговыми окнами – то есть сохраните предлагаемые ими файлы.
После этого рабочая область программы будет выглядеть следующим образом:
Теперь мы должны написать только часть кода, отвечающую за взаимодействие с модулем GSM.
Исходный код программы на языке С (Си) с пояснениями
В рассматриваемом нами способе создания программы все заголовочные файлы должны автоматически прикрепиться к проекту за исключением того что необходимо будет вручную подключить заголовочный файл delay.h и объявить все переменные. Полный текст программы будет приведен в конце статьи, здесь же будет дано пояснение лишь отдельных фрагментов программы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <io.h> // Alphanumeric LCD functions #include <alcd.h> #include <delay.h> // стандартные функции ввода/вывода #include <stdio.h> unsigned char received_value(void); unsigned char received_data,a,b,c; unsigned int z; unsigned char msg[15]; unsigned char cmd_1[]={"AT"}; unsigned char cmd_2[]={"AT+CMGF=1"}; unsigned char cmd_3[]={"AT+CMGS="}; unsigned char cmd_4[]={"Call me"}; unsigned char cmd_5[]={"Receiver mobile number"}; |
Запрограммируем функцию, которая будет принимать данные из регистра UDR. Эта функция будет возвращать принятые данные.
1 2 3 4 5 6 7 8 |
unsigned char received_value(void) { while(!(UCSRA&(1<<RXC))); { received_data=UDR; return received_data; } } |
Используем цикл while в котором создадим два условных выражения, используя оператор if, одно для передачи сообщения, а другое – для приема. Кнопка передачи подсоединена к контакту PIND6 микроконтроллера, а кнопка приема – к контакту PIND5.
Когда кнопка передачи нажата (PIND6) будет выполняться первый оператор if и все команды, необходимые для передачи сообщения, будут выполняться последовательно.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
while(1){ // lcd_clear(); lcd_putsf("Send->bttn 1"); lcd_gotoxy(0,1); lcd_putsf("Receive->buttn 2"); if(PIND.6 == 1){ lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Sending Msg..."); for(z=0;cmd_1[z]!='';z++) { UDR = cmd_1[z]; delay_ms(100); } UDR = ('\r'); delay_ms(500); for(z=0;cmd_2[z]!='';z++) { UDR = cmd_2[z]; delay_ms(100); } |
Если кнопка приема нажата, в цикле while (b!='+') будет осуществляться проверка присутствует ли команда CMT или нет. Если присутствует, то будет выполняться последовательность команд начинающаяся со второй строчки цикла while, в результате выполнения этой серии команд на ЖК дисплее будет напечатано принятое сообщение.
1 2 3 4 5 6 7 8 9 10 11 12 |
while(PIND.5 == 1){ lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Receiving Msg..."); b= received_value (); while (b!='+') { b= received_value (); } b= received_value (); if(b=='C') { b= received_value (); |
Следующий цикл предназначен для сохранения сообщения в массиве.
1 2 3 4 5 6 7 8 |
while (b!=0x0a) { b= received_value (); } for(b=0;b<3;b++) { c=received_value(); msg[b]=c; } |
Следующий цикл for служит для отображения сообщения на ЖК дисплее.
1 2 3 4 5 6 |
for(z=0;z<3;z++) { a=msg[z]; lcd_putchar(a); // PRINT IN lcd delay_ms(10); } |
Компоновка проекта
Наш код закончен. Теперь нам необходимо скомпоновать (Build) наш проект. Для этого нажмите на кнопке Build как показано на рисунке.
После компоновки проекта соответствующий HEX файл будет помещен в папку Debug-> Exe, которую можно найти в папке, которую вы создавали ранее для хранения проекта. Мы будем загружать этот HEX файл в микроконтроллер Atmega16 используя программу Sinaprog (можно использовать любую другую аналогичную программу, с которой вы привыкли работать).
Загрузка программы в Atmega16 с использованием Sinaprog
Подсоедините один конец FRC кабеля к программатору USBASP, а другой конец к контактам SPI микроконтроллера.
Необходимо сделать следующие соединения:
1. Pin1 of FRC female connector -> Pin 6, MOSI of Atmega16
2. Pin 2 connected to Vcc of atmega16 i.e. Pin 10
3. Pin 5 connected to Reset of atmega16 i.e. Pin 9
4. Pin 7 connected to SCK of atmega16 i.e. Pin 8
5. Pin 9 connected to MISO of atmega16 i.e. Pin 7
6. Pin 8 connected to GND of atmega16 i.e. Pin 11
Мы будем загружать в микроконтроллер ранее сгенерированный Hex файл используя программу Sinaprog, поэтому мы должны открыть ее и выбрать в ней Atmega16 в выпадающем меню устройства (Device). Выберите HEX файл из папки Debug->Exe как показано на рисунке.
Теперь кликните на Program и ваш код будет загружен в микроконтроллер ATmega16.
Ваш микроконтроллер запрограммирован. Теперь можете попробовать нажимать кнопки для передачи и приема сообщений от микроконтроллера к GSM модулю.
Полный код программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
#include <io.h> // Alphanumeric LCD functions #include <alcd.h> #include <delay.h> // стандартные функции ввода/вывода #include <stdio.h> unsigned char received_value(void); unsigned char received_data,a,b,c; unsigned int z; unsigned char msg[15]; unsigned char cmd_1[]={"AT"}; unsigned char cmd_2[]={"AT+CMGF=1"}; unsigned char cmd_3[]={"AT+CMGS="}; unsigned char cmd_4[]={"Call me"}; unsigned char cmd_5[]={"Receiver mobile number"}; void main(void) { // инициализация Port A // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); // инициализация Port B // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // инициализация Port C // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0); // инициализация Port D // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); // инициализация USART (универсальный синхронно-асинхронный приемопередатчик) // параметры связи: 8 бит данных, 1 стоповый бит, нет бита четности // USART Receiver (приемник): On // USART Transmitter (передатчик): On // USART Mode (режим): Asynchronous // USART Baud Rate (бодовая скорость): 9600 UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL); UBRRH=0x00; UBRRL=0x33; lcd_init(16); lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Welcome..."); delay_ms(2000); lcd_clear(); lcd_putsf("Initialising GSM"); delay_ms(4000); lcd_clear(); while(1){ lcd_putsf("Send->bttn 1"); lcd_gotoxy(0,1); lcd_putsf("Receive->buttn 2"); if(PIND.6 == 1){ lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Sending Msg..."); for(z=0;cmd_1[z]!='';z++) { UDR = cmd_1[z]; delay_ms(100); } UDR = ('\r'); delay_ms(500); for(z=0;cmd_2[z]!='';z++) { UDR = cmd_2[z]; delay_ms(100); } UDR = ('\r'); delay_ms(500); for(z=0;cmd_3[z]!='';z++) { UDR = cmd_3[z]; delay_ms(100); } UDR = ('"'); delay_ms(100); for(z=0;cmd_5[z]!='';z++) { UDR = cmd_5[z]; delay_ms(100); } UDR = ('"'); delay_ms(100); UDR = ('\r'); delay_ms(500); for(z=0;cmd_4[z]!='';z++) { UDR = cmd_4[z]; delay_ms(100); } UDR = (26); // ctrlZ-> передать сообщение delay_ms(500); lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Message Sent."); delay_ms(1000); lcd_clear(); } while(PIND.5 == 1){ lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Receiving Msg..."); b= received_value (); while (b!='+') // infinite loop when + equal to +. otherwise until the loop infinite { b= received_value (); } b= received_value (); if(b=='C') { b= received_value (); if(b=='M') { b= received_value (); if(b=='T') { b= received_value (); if(b==':') { b= received_value (); while (b!=0x0a) // waiting upto next line if no means till loop infinte { b= received_value (); } for(b=0;b<3;b++) { c= received_value (); msg[b]=c; } lcd_clear(); for(z=0;z<3;z++) { a=msg[z]; lcd_putchar(a); // PRINT IN lcd delay_ms(10); } } } } } delay_ms(3000); lcd_clear(); } } } unsigned char received_value(void) { while(!(UCSRA&(1<<RXC))); { received_data=UDR; return received_data; } } |
В описании к статье указаны инициализация кнопок "2. Кнопки to PD5 (Pin19) and PD6 (Pin20)." Однако ни в кодевизарде ни в самом коде инициализации данных кнопок не видно ...Понятно что автор настроил кнопки на вход и подтянул их внешними резисторами но желательно чтобы этот момент был отображен в статье .
Да, спасибо за замечание. Эта статья по стилю изложения немного отличается от других статей на нашем сайте по микроконтроллерам AVR. Здесь в коде программы отдельно не инициализировались контакты для этих кнопок, здесь просто сразу значения контактов почти всех портов микроконтроллера сконфигурированы для работы на ввод данных - посмотрите строки программы с 20 по 37. Насколько я понимаю, эта часть программы была автоматически сформирована средой CodeVision
Было бы очень неплохо если бы в код была добавлена функция получения команд от модема в ответ на присланные микроконтроллером... Модемы есть разные инициализации а под час и команды различаются - А так непонятно обработал ли модем команду прислал ОК или ERROR.
Спасибо за полезный совет, но, к сожалению, я пока не могу этого сделать - переключился на статьи по другим технологиям. Может быть позже, когда я буду снова возвращаться к AVR