找回密码
 注册

QQ登录

只需一步,快速开始

搜索

使用51单片机和GSM模块向手机发送短信源程序

[复制链接]
eng 发表于 2021-6-14 03:03:59 | 显示全部楼层 |阅读模式
调试时,通过串口助手向GSM模块发送相应的AT指令,就可以设置其工作模式。
比如“向指定的手机号码发送英文短信”。
PS:功能有很多,本贴以发送英文短信为例。
与单片机结合的基本原理就是:把AT指令以字符串形式写入程序,程序烧入单片机之后,调用串口中断进行通信。依次向GSM模块发送指令,GSM模块接收指令成功则返回“ok”,失败则返回“error”放在单片机的subf上,通过检测subf上是否有“ok”来判断GSM是否接收指令成功。每成功一次就发送下一条指令。以此实现设置GSM的工作模式。
代码如下:
/*头文件*/
#include <REG52.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef        unsigned char        u8;
typedef unsigned int        u16;
typedef unsigned long        u32;
/*宏定义*/
#define Success 1U
#define Failure 0U
#define Uart1_Buf_Max 100  //串口数据缓存长度
/*定义一些变量*/
unsigned long  Time_Cont = 0;  //定时器计数器
char phoneNumber[] = "15605156539";//替换成需要被拨打电话的号码
char msg[] = "fire";                //短信内容      
u8 point1;
u8 xdata  Rec_Buf[Uart1_Buf_Max];  //串口数据缓存
u8 point1 = 0;             //绶存指针
/*函数原型声明*/
void Uart_Init();
void SendData(unsigned char ch);
void SendString(char *s);
bit Hand(unsigned char *a);
void CLR_Buf(void);
void delay_ms(unsigned int n);
unsigned int sendCommand(char *Command, char *Response, unsigned long Timeout, unsigned char Retry);
void errorLog();
void soft_reset(void);
void phone(char *number);
void sendMessage(char *number,char *msg);

/*************************************************************/
/*************************************************************/
/*********------------------子函数-------------------*********/
/*************************************************************/
/*************************************************************/
//MS延时函数(12M晶振下测试)
void delay_ms(unsigned int n)
{
        unsigned int  i,j;
                for(i=0;i<n;i++)
                        for(j=0;j<123;j++);
}

/****串口中断触发函数****/
void Uart_Init()                                                                    
{      
        SCON = 0X50;  //UART方式1;8位UART 0101 0000
        REN  = 1;     //不允许串行口接收数据
        PCON = 0x00;  //SMOD=0;波特率9600不加倍
        TMOD = 0x20;  //T1计数器工作方式方式2自动重装,0010 0000用于产生波特率
        TH1  = 0xFD;  //装初值
        TL1  = 0xFD;
        TR1  = 1;     //启动定时器1
        EA   = 1;     //打开全局中断控制
        ES   = 1;     //串行口中断      
}


/*****串口中断服务函数******/
void RECEIVE_DATA(void) interrupt 4 using 1         //串口中断服务函数                        
{   
        ES = 0;
        if (RI)
    {
              RI = 0;   //接收完数据,RI由硬件置1,需要用软件使RI置0,等待下一次接收数据,所以清除RI位
                Rec_Buf[point1] = SBUF; //出去接收到的数据
                point1++;   //在数组中依次存放数据            
                if(point1>=Uart1_Buf_Max)      //接收的数据最大为100   
                {
                        point1 = 0;
                }           
    }
        ES =  1;

}

/*****单片机向GSM模块发送串口数据******/
void SendData(unsigned char ch)
{
        SBUF = ch;                 //写数据到UART数据寄存器,SBUF把信息传递出去,完成后TI由硬件置1
        while(TI == 0);         //等待发送数据完成
        TI = 0;         //清除发送完成标志位
}


/*****发送字符串******/
void SendString(char *s)
{
    while (*s)                  //检测字符串结束标志
    {
        SendData(*s++);         //发送当前字符
    }
}


/*****串口命令识别函数******/
bit Hand(unsigned char *a)                   // 串口命令识别函数
{
    if(strstr(Rec_Buf,a)!=NULL)//strstr判断字符串a是否为字符串Rec_Buf的字串,如果是,则返回1
            return 1;
        else
                return 0;
}

//制造重启命令
void soft_reset(void)      
{
   ((void (code *) (void)) 0x0000) ();
}


void errorLog()
{
        while (1)
        {
                  if (sendCommand("AT\r\n", "OK\r\n", 100, 10) == Success)
                {
                        soft_reset();
                }
                delay_ms(200);
        }
}

/*****串口缓存清理******/
void CLR_Buf(void)                           // 串口缓存清理
{
        memset(Rec_Buf, 0, Uart1_Buf_Max);      //清空  100个字节大小的Rec_Buf全部置0  ,清空SBUF出去接收到的数据
    point1 = 0;                    
}

/*****函数名:sendCommand*******/
/*****函数功能:*******/
/************/
unsigned int sendCommand(char *Command, char *Response, unsigned long Timeout, unsigned char Retry)
{
        unsigned char n;
        CLR_Buf();//串口缓存清理
        for (n = 0; n < Retry; n++)
        {
                SendString(Command);                 //发送GPRS指令

                Time_Cont = 0;
                while (Time_Cont < Timeout)
                {
                        delay_ms(100);
                        Time_Cont += 100;
                        if (strstr(Rec_Buf, Response) != NULL)
                        {

                                CLR_Buf();
                                return Success;
                        }

                }
                Time_Cont = 0;
        }

        CLR_Buf();
        return Failure;
}


/******--------------------------******/
/***发送号码及短信内容,并判断是否成功**/
/******--------------------------******/
void sendMessage(char *number,char *msg)
{
        xdata char send_buf[20] = {0};//开辟1个20字节的空间
        memset(send_buf, 0, 20);    //清空  把send_buf初始化为20字节大小的内容全部是0的数组
        strcpy(send_buf, "AT+CMGS=\"");
        /*发送号码并判断是否发送成功*/
        strcat(send_buf, number);//连接字符串
        strcat(send_buf, "\"\r\n");
        if (sendCommand(send_buf, ">", 3000, 10) == Success);//判断手机号码是否发送成功
        else errorLog();
        /*发送短信内容并判断是否发送成功*/
        if (sendCommand(msg, msg, 3000, 10) == Success);
        else errorLog();

        memset(send_buf, 0, 40);    //清空
        send_buf[0] = 0x1a;
        send_buf[1] = '\0';
        if (sendCommand(send_buf, "OK\r\n", 10000, 5) == Success);
        else errorLog();
}


/*************************************************************/
/*************************************************************/
/*********------------------主函数-------------------*********/
/*************************************************************/
/*************************************************************/
void main()
{
    Uart_Init();//调用串口中断函数               
    /*******-----状态检测及设置-----********/
        if (sendCommand("AT\r\n", "OK\r\n", 3000, 10) == Success);
        else errorLog();
        delay_ms(100);

        if (sendCommand("AT+CSQ\r\n", "OK\r\n", 3000, 10) == Success);//信号质量
        else errorLog();
        delay_ms(100);

        if (sendCommand("AT+CPIN?\r\n", "READY", 3000, 10) == Success);//SIM卡状态
        else errorLog();
        delay_ms(100);

        if (sendCommand("AT+COPS?\r\n", "OK\r\n", 3000, 10) == Success);//运营商
        else errorLog();
        delay_ms(100);

        if (sendCommand("AT+CREG?\r\n", ",1", 3000, 10) == Success);        //本地SIM卡
        else if(sendCommand("AT+CREG?\r\n", ",5", 3000, 10) == Success        );//漫游SIM卡
        else        errorLog();
        delay_ms(100);


        if (sendCommand("AT+CMGF=1\r\n", "OK\r\n", 1000, 10) == Success);//短消息为文本模式
        else errorLog();
        delay_ms(10);

        if (sendCommand("AT+CSMP=17,167,0,8\r\n", "OK\r\n", 3000, 10) == Success);
        else errorLog();
        delay_ms(10);

        if (sendCommand("AT+CSCS=\"GSM\"\r\n", "OK\r\n", 1000, 10) == Success);
        else errorLog();
        delay_ms(10);

        sendMessage(phoneNumber,msg);                //发送短信

        while(1)
        {      

        }
}


您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|ELEOK |网站地图

GMT+8, 2024-12-4 01:30

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表