GSM模塊使用起來非常吸引人,尤其是當我們的項目需要遠程訪問時。這些模塊可以執行我們普通手機可以執行的所有操作,例如撥打/接聽電話,發送/接收短信,使用GPRS連接到互聯網等。您還可以將普通麥克風和揚聲器連接到此模塊,并在移動通話中交談。如果它可以與微控制器連接,這將為許多創意項目打開大門。因此,在本教程中,我們將學習如何將GSM模塊(SIM900A)與我們的PIC微控制器連接,并通過使用GSM模塊撥打和接聽電話來演示它。
所需材料:
- PIC 微控制器 (PIC16F877A)
- GSM 模塊(SIM900 或任何其他)
- 連接線
- 12V 適配器
- 圖片套件 3
GSM模塊:
即使沒有任何微控制器,也可以通過使用AT命令模式使用GSM模塊。如上所示,GSM模塊帶有USART適配器,可以使用MAX232模塊直接連接到計算機,或者Tx和Rx引腳可用于將其連接到微控制器。您還可以注意到可以連接麥克風或揚聲器的其他引腳,如MIC +,MIC-,SP+,SP-等。該模塊可以通過普通的直流桶形插孔由 12V 適配器供電。
將SIM卡插入模塊插槽并打開電源,您應該注意到電源指示燈亮起。現在等待一分鐘左右,您應該會看到紅色(或任何其他顏色)LED 每 3 秒閃爍一次。這意味著您的模塊能夠與您的SIM卡建立連接。現在,您可以繼續將模塊與手機或任何微控制器連接。
使用 AT 命令與 GSM 模塊通信:
正如您可能已經猜到的那樣,GSM模塊可以通過串行通信進行通信,并且只能理解一種語言,即“ AT命令 ”。無論您想告訴或詢問GSM模塊什么,都只能通過AT命令進行。例如,如果您想知道模塊是否處于活動狀態。您應該詢問(發送)像“AT”這樣的命令,您的模塊將回答“確定”。
這些AT命令在其數據手冊中有很好的解釋,可以在其官方數據手冊中找到。好!好!這是一份 271 頁的數據表,您可能需要幾天時間才能通讀它們。因此,我在下面給出了一些最重要的AT命令,以便您盡快啟動并運行它。
在 | 回復“確定”進行確認 |
---|---|
AT+CPIN? | 檢查信號質量 |
AT+COPS? | 查找服務提供商名稱 |
ATD96XXXXXXXX; | 撥打特定號碼,以分號結尾 |
AT+CNUM | 查找SIM卡的數量(可能不適用于某些SIM卡) |
ATA | 接聽來電 |
阿特 | 掛斷當前來電 |
AT+COLP | 顯示來電號碼 |
AT+VTS=(數字) | 發送 DTMF 編號。您可以使用移動鍵盤上的任意數字(數字) |
AT+CMGR | AT+CMGR=1 在第一個位置讀取消息 |
AT+CMGD=1 | 刪除第一個位置的消息 |
AT+CMGDA=“DEL ALL” | 從SIM卡中刪除所有郵件 |
AT+CMGL=“ALL” | 讀取來自 SIM 卡的所有消息 |
AT+CMGF=1 | 設置短信配置。“1”表示純文本模式 |
AT+CMGS = “+91 968837XXXX”>電路摘要文本 | 在此處向特定號碼發送短信 968837XXXX。當您看到“>”時,請開始輸入文本。按 Ctrl+Z 發送文本。 |
AT+CGATT? | 檢查SIM卡上的互聯網連接 |
AT+CIPSHUT | 關閉TCP連接,意味著斷開互聯網 |
AT+CSTT = “APN”,“用戶名”,“通行證” | 使用您的 APN 和通行密鑰連接到 GPRS。可以從網絡提供商處獲得。 |
AT+CIICR | 檢查SIM卡是否有數據包 |
AT+CIFSR | 獲取 SIM 卡網絡的 IP |
AT+CIPSTART = “TCP”,“服務器 IP”,“端口” | 用于設置 TCP IP 連接 |
AT+CIPSEND | 此命令用于將數據發送到服務器 |
電路圖:
我們只是簡單地將GSM模塊的Tx和Rx引腳分別與PIC MCU PIC16F877A的Rx和Tx引腳連接。這將在兩者之間建立串行連接。另外,不要忘記將GSM和PIC模塊共同接地。我們還使用LCD顯示屏來了解GSM模塊的狀態。連接完成后,您的硬件將如下所示。
PIC微控制器編程:
可以在本教程的底部找到此項目的完整程序。在這里,我將解釋一些重要的函數和代碼片段。該程序還具有LCD代碼,該代碼來自與PIC微控制器的接口LCD,如果您想知道如何將LCD與PIC微控制器一起使用,可以訪問該教程。
如前所述,我們將通過串行通信模式使用 AT 命令在 PIC 和 GSM 之間進行通信。因此,首先我們必須使用 Initialize***_SIM900()* **初始化 PIC 微控制器中的 USART 通信模塊;功能。在此函數中,我們聲明 Tx 和 RX 引腳,并以 9600 波特率和 8 位模式初始化異步接收和傳輸。
//***Initialize UART for SIM900**//
void Initialize_SIM900(void)
{
//****Setting I/O pins for UART****//
TRISC6 = 0; // TX Pin set as output
TRISC7 = 1; // RX Pin set as input
//________I/O pins set __________//
/**Initialize SPBRG register for required
baud rate and set BRGH for fast baud_rate**/
SPBRG = 129; //SIM900 operates at 9600 Baud rate so 129
BRGH = 1; // for high baud_rate
//_________End of baud_rate setting_________//
//****Enable Asynchronous serial port*******//
SYNC = 0; // Asynchronous
SPEN = 1; // Enable serial port pins
//_____Asynchronous serial port enabled_______//
//**Lets prepare for transmission & reception**//
TXEN = 1; // enable transmission
CREN = 1; // enable reception
//__UART module up and ready for transmission and reception__//
//**Select 8-bit mode**//
TX9 = 0; // 8-bit reception selected
RX9 = 0; // 8-bit reception mode selected
//__8-bit mode selected__//
}
//________UART module Initialized__________//
現在我們需要從/向我們的 GSM 模塊讀取和寫入信息。為此,我們使用函數 **_SIM900_putch)、_SIM900_getch()、_SIM900_send_string()、_SIM900_print()。 **這些函數使用發送和接收緩沖區寄存器(如 TXREG 和 RCREG)串行讀取或寫入數據。
//**Function to send one byte of date to UART**//
void _SIM900_putch(char bt)
{
while(!TXIF); // hold the program till TX buffer is free
TXREG = bt; //Load the transmitter buffer with the received value
}
//_____________End of function________________//
//**Function to get one byte of date from UART**//
char _SIM900_getch()
{
if(OERR) // check for Error
{
CREN = 0; //If error -> Reset
CREN = 1; //If error -> Reset
}
while(!RCIF); // hold the program till RX buffer is free
return RCREG; //receive the value and send it to main function
}
//_____________End of function________________//
//**Function to convert string to byte**//
void SIM900_send_string(char* st_pt)
{
while(*st_pt) //if there is a char
_SIM900_putch(*st_pt++); //process it as a byte data
}
//___________End of function______________//
//**End of modified Codes**//
void _SIM900_print(unsigned const char *ptr) {
while (*ptr != 0) {
_SIM900_putch(*ptr++);
}
上述功能是通用的,無需為任何應用程序進行更改。對它們的解釋只是為了給出一個粗略的介紹。如果你愿意,你可以通過理解深入了解它們。
現在在我們的主函數中,我們初始化 USART 連接,并使用以下代碼行檢查我們在發送“AT”時是否能夠收到“OK”
do
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Module not found");
}while (!SIM900_isStarted()); //wait till the GSM to send back "OK"
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Module Detected ");
__delay_ms(1500);
函數 SIM900_isStarted(); 將向 GSM 發送“AT”并等待其響應“OK”。如果是,它將返回 1 其他 0;
如果未檢測到模塊或存在任何連接問題,則LCD將顯示“未找到模塊”,否則將顯示“檢測到模塊”并繼續下一步,我們檢查是否可以通過以下代碼行檢測到SIM卡。
/*Check if the SIM card is detected*/
do
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("SIM not found ");
}while (!SIM900_isReady()); //wait till the GSM to send back "+CPIN: READY"
Lcd_Set_Cursor(2,1);
Lcd_Print_String("SIM Detected ");
__delay_ms(1500);
函數 SIM900_isReady() 將向 GSM 發送“AT+CPIN?”,并等待來自它的響應“+CPIN:READY”。如果是,它將返回 1 其他 0;
如果找到SIM卡,我們將在LCD上顯示檢測到SIM卡。然后,我們可以嘗試使用命令“ ATD手機號碼 ;”撥打電話。作為一個例子,我使用我的號碼作為ATD93643159XX;。您必須在那里替換各自的手機號碼。
/*Place a Phone Call*/
do
{
_SIM900_print("ATD93643XXXXX;\\r\\n"); //Here we are placing a call to number 93643XXXXX
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Placing Call....");
}while (_SIM900_waitResponse() != SIM900_OK); //wait till the ESP send back "OK"
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Call Placed....");
__delay_ms(1500);
發出呼叫后,液晶屏將顯示“呼叫已發出”,您應該會收到該指定號碼的來電。
您還可以撥打連接到GSM模塊的手機號碼,并使用以下代碼在LCD屏幕上獲得通知
while(1)
{
if (_SIM900_waitResponse() == SIM900_RING) //Check if there is an incoming call
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Incoming Call!!.");
}
}
當GSM模塊檢測到來電時,它將在LCD模塊的第二行上顯示來電。函數 *_SIM900_waitResponse() *將檢查來自 GSM 模塊的傳入數據。當它收到SIM900_RING時,由于 waitResponce() 而相當于“RING”,我們將顯示狀態“來電”。
您可以像這樣創建自己的函數,以使用 GSM 模塊執行幾乎所有類型的激活。如果你想對東西進行硬編碼,你可以簡單地使用 __SIM900_print() 函數發送任何 AT 命令,如下所示。
_SIM900_print("AT+CPIN?\\r\\n");
請記住,所有命令后面都應跟有“\\r\\n”,以指示命令正在終止。
模擬:
了解程序的工作原理后,您可以嘗試模擬并進行更改以滿足您的需求。模擬將為您節省大量時間。模擬是使用 Proteus 完成的,如下所示。
如您所見,我們在Proteus中使用了虛擬終端選項來檢查程序是否按預期響應。我們可以通過彈出對話框輸入值。例如,一旦我們點擊運行,就會出現一個像上面這樣的黑色對話框并顯示 AT,這意味著它已將 GSM 模塊發送到 AT,現在我們可以通過在框中輸入“確定”并按回車鍵來回復 PIC,PIC 將響應它。同樣,我們可以嘗試所有 AT 命令。
使用 GSM 和 PIC 撥打和接聽電話:
了解代碼和硬件的工作原理后,只需將以下程序上傳到 PIC 并打開模塊電源即可。如果一切正常,您的液晶屏應顯示“檢測到模塊”,“檢測到SIM卡”和“呼叫已放置”。一旦您看到“已撥打電話”,您將接到程序中指定的號碼的來電。
您也可以嘗試撥打GSM模塊中的號碼,LCD將顯示“來電”以指示正在呼叫SIM卡。
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//End of CONFIG registers
#define _XTAL_FREQ 20000000
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#define SIM900_OK 1
#define SIM900_READY 2
#define SIM900_FAIL 3
#define SIM900_RING 4
#define SIM900_NC 5
#define SIM900_UNLINK 6
#include
// Wait for any response on the input
inline unsigned char _SIM900_waitResponse(void);
int recv;
char p =1;
//LCD Functions Developed by Circuit Digest.
void Lcd_SetBit(char data_bit) //Based on the Hex value Set the Bits of the Data Lines
{
if(data_bit& 1)
D4 = 1;
else
D4 = 0;
if(data_bit& 2)
D5 = 1;
else
D5 = 0;
if(data_bit& 4)
D6 = 1;
else
D6 = 0;
if(data_bit& 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0;
Lcd_SetBit(a); //Incoming Hex value
EN = 1;
__delay_ms(4);
EN = 0;
}
void Lcd_Clear()
{
Lcd_Cmd(0); //Clear the LCD
Lcd_Cmd(1); //Move the curser to first position
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a== 1)
{
temp = 0x80 + b - 1; //80H is used to move the curser
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
else if(a== 2)
{
temp = 0xC0 + b - 1;
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
}
void Lcd_Start()
{
Lcd_SetBit(0x00);
for(int i=1065244; i<=0; i--) NOP();
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x08); //Select Row 1
Lcd_Cmd(0x00); //Clear Row 1 Display
Lcd_Cmd(0x0C); //Select Row 2
Lcd_Cmd(0x00); //Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Print_Char(char data) //Send 8-bits through 4-bit mode
{
char Lower_Nibble,Upper_Nibble;
Lower_Nibble = data&0x0F;
Upper_Nibble = data&0xF0;
RS = 1; // => RS = 1
Lcd_SetBit(Upper_Nibble>>4); //Send upper half by shifting by 4
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
Lcd_SetBit(Lower_Nibble); //Send Lower half
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
}
void Lcd_Print_String(char *a)
{
int i;
for(i=0;a[i]!='\\0';i++)
Lcd_Print_Char(a[i]); //Split the string using pointers and call the Char function
}
/*****End of LCD Functions*****/
//***Initialize UART for SIM900**//
void Initialize_SIM900(void)
{
//****Setting I/O pins for UART****//
TRISC6 = 0; // TX Pin set as output
TRISC7 = 1; // RX Pin set as input
//________I/O pins set __________//
/**Initialize SPBRG register for required
baud rate and set BRGH for fast baud_rate**/
SPBRG = 129; //SIM900 operates at 9600 Baud rate so 129
BRGH = 1; // for high baud_rate
//_________End of baud_rate setting_________//
//****Enable Asynchronous serial port*******//
SYNC = 0; // Asynchronous
SPEN = 1; // Enable serial port pins
//_____Asynchronous serial port enabled_______//
//**Lets prepare for transmission & reception**//
TXEN = 1; // enable transmission
CREN = 1; // enable reception
//__UART module up and ready for transmission and reception__//
//**Select 8-bit mode**//
TX9 = 0; // 8-bit reception selected
RX9 = 0; // 8-bit reception mode selected
//__8-bit mode selected__//
}
//________UART module Initialized__________//
//**Function to send one byte of date to UART**//
void _SIM900_putch(char bt)
{
while(!TXIF); // hold the program till TX buffer is free
TXREG = bt; //Load the transmitter buffer with the received value
}
//_____________End of function________________//
//**Function to get one byte of date from UART**//
char _SIM900_getch()
{
if(OERR) // check for Error
{
CREN = 0; //If error -> Reset
CREN = 1; //If error -> Reset
}
while(!RCIF); // hold the program till RX buffer is free
return RCREG; //receive the value and send it to main function
}
//_____________End of function________________//
//**Function to convert string to byte**//
void SIM900_send_string(char* st_pt)
{
while(*st_pt) //if there is a char
_SIM900_putch(*st_pt++); //process it as a byte data
}
//___________End of function______________//
//**End of modified Codes**//
void _SIM900_print(unsigned const char *ptr) {
while (*ptr != 0) {
_SIM900_putch(*ptr++);
}
}
bit SIM900_isStarted(void) {
_SIM900_print("AT\\r\\n");
return (_SIM900_waitResponse() == SIM900_OK);
}
bit SIM900_isReady(void) {
_SIM900_print("AT+CPIN?\\r\\n");
return (_SIM900_waitResponse() == SIM900_READY);
}
inline unsigned char _SIM900_waitResponse(void) {
unsigned char so_far[6] = {0,0,0,0,0,0};
unsigned const char lengths[6] = {2,12,5,4,6,6};
unsigned const char* strings[6] = {"OK", "+CPIN: READY", "ERROR", "RING", "NO CARRIER", "Unlink"};
unsigned const char responses[6] = {SIM900_OK, SIM900_READY, SIM900_FAIL, SIM900_RING, SIM900_NC, SIM900_UNLINK};
unsigned char received;
unsigned char response;
char continue_loop = 1;
while (continue_loop) {
received = _SIM900_getch();
for (unsigned char i = 0; i < 6; i++) {
if (strings[i][so_far[i]] == received) {
so_far[i]++;
if (so_far[i] == lengths[i]) {
response = responses[i];
continue_loop = 0;
}
} else {
so_far[i] = 0;
}
}
}
return response;
}
void main(void)
{
//I/O Declarations//
TRISD = 0x00; //LCD pins on port D as output
//End of I/O declaration//
Lcd_Start(); //Initialize LCD
Initialize_SIM900();//lets get our Serial ready for action
Lcd_Set_Cursor(1,1);
Lcd_Print_String("SIM900 & PIC");
/*Check if the SIM900 communication is successful*/
do
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Module not found");
}while (!SIM900_isStarted()); //wait till the GSM to send back "OK"
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Module Detected ");
__delay_ms(1500);
/*Check if the SIM card is detected*/
do
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("SIM not found ");
}while (!SIM900_isReady()); //wait till the GSM to send back "+CPIN: READY"
Lcd_Set_Cursor(2,1);
Lcd_Print_String("SIM Detected ");
__delay_ms(1500);
Lcd_Clear();
/*Place a Phone Call*/
do
{
_SIM900_print("ATD93643XXXXX;\\r\\n"); //Here we are placing a call to number 93643XXXXX
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Placing Call....");
}while (_SIM900_waitResponse() != SIM900_OK); //wait till the ESP send back "OK"
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Call Placed....");
__delay_ms(1500);
while(1)
{
if (_SIM900_waitResponse() == SIM900_RING) //Check if there is an incoming call
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Incoming Call!!.");
}
}
}
-
微控制器
+關注
關注
48文章
7562瀏覽量
151503 -
PIC
+關注
關注
8文章
507瀏覽量
87599 -
GSM模塊
+關注
關注
6文章
48瀏覽量
23145
發布評論請先 登錄
相關推薦
評論