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文章
7536浏览量
151293 -
PIC
+关注
关注
8文章
507浏览量
87530 -
GSM模块
+关注
关注
6文章
48浏览量
23137
发布评论请先 登录
相关推荐
评论