GSM模块之TC35I发送pdu短信--stc51单片机

这几天研究了一下pdu信息收发,今天花了大半天写出了不完善的pdu信息发送程序并调试成功了,由于竞赛时间有限,暂时不对这个发短信模块进行优化了,等有时间再重新整理好这个,完善其功能

由于此程序用于初步的测试,并且本人没有多少写程序的经验,下面的东西有点儿乱。

 

发送的pdu串格式:信息服务中心地址+pdutype+mr+接收方手机地址+pid+dsc+vp+udl+ud

 

一下是一个发送的pdu串

+8613010670500
13211147412

AT+CMGF=0
AT+CMGS=28

0891683110600705F011000B813112117414F20008A70E6A215757521D59CB53166210529F

 

分析一下:0891             683110600705F0              1100     0B81  3112117414F2  0008A7  0E         6A215757521D59CB53166210529F

长度类型          奇偶兑换加F的信息中心地址

 

下面是完整的c语言实现,只能发送信息到11位号码的手机,16位编码no class,发送Unicode文字代码

 

/*
 * GSM模块收发短信打电话,pdu模式
 * 德国西门子TC35I GSM  模块
 * 基于GSM的单片机无线通讯模块程序
 *
 *  实现发送pdu短信,只需设置信息中心与收信人电话号码,发送Unitcode码。
 *  接收短信,只分辨是否为预置号码的短信,提取信息内容(Unicode码)
 *	16bit no class编码
 *
 *	gsm.h
 *
 *	使用说明:	须设置主人电话与信息中心号码:
 *					uchar code phone[] = "13211145418";		//主人电话号码
 *					uchar code sms_center[] = "+8613010200500";//广州联通
 *
 * 				GSM开关机控制线:
 *					sbit gsm_igt = P0^3;// 点火线
 *					sbit gsm_emergoff = P0^4;//关机线
 *
 *				波特率设置:
 *					uchar code AT_IPR[] = "AT+IPR=2400";	//设置波特率
 *					void gsm_uart_init(void);函数中定时器(定时器1)
 *			
 *				拨打主人电话:
 *					gsm_call();
 *
 *				处理主人来信,内容已经存在gsm_sms_ud[]中:
 *					gsm_sms_host();
 *
 *				处理非主人信息,内容已经存在gsm_sms_ud[]中:
 *					gsm_sms_unknow();
 *	
 *				主函数调用模块如下:
 *				#include <reg52.h>
 *				#include "gsm.h"
 *				#define uchar unsigned char
 *
 *				void main(void)
 *				{
 *					gsm_init();//初始化gsm(包括串口通信设置)	
 *					while(1){
 *						gsm_scan();	//处理gsm消息
 *					}
 *				}		
 *
 *	CopyRight(C) 2010 CrazyLeen <[email protected]>
 *  注意:		使用外部函数delay_s(); delay_ms();
 *				使用了定时器1
 */

#ifndef __GSM_H__
#define __GSM_H__

#include <reg52.h>
#include <string.h>
#include "delays.h"
#define uchar unsigned char

//===========================================GSM模块=====================================================
//引脚定义
sbit gsm_igt = P0^4;// 点火线
sbit gsm_emergoff = P0^3;//关机线

uchar code phone[] = "13211145418";		//主人电话号码
uchar code sms_center[] = "+8613010200500";//广州联通

//SMU
uchar code gsm_password[] = "0053004D0055";

//============================================内置短信=================================================
//Unicode字符代码for sms
//您好,GSM远程控制系统初始化成功。欢迎使用GSM远程控制系统^_^...
uchar code ud_init_ok[] = "60A8597DFF0C00470053004D8FDC7A0B63A752367CFB7EDF521D59CB53166210529F30026B228FCE4F7F752800470053004D8FDC7A0B63A752367CFB7EDF005E005F005E002E002E002E";
//您好,防盗系统已开启,请放心外出,enjoy your time...
uchar code ud_alarm_on[] = "60A8597DFF0C963276D77CFB7EDF5DF25F00542FFF0C8BF7653E5FC3591651FAFF0C0065006E006A006F007900200079006F00750072002000740069006D0065002E002E002E";
//您好,防盗系统已成功关闭,出门记得及时开启防盗系统(⊙o⊙)哦
uchar code ud_alarm_off[] = "60A8597DFF0C963276D77CFB7EDF5DF26210529F517395EDFF0C51FA95E88BB05F9753CA65F65F00542F963276D77CFB7EDF00282299006F2299002954E6";
//您好,有客人按响您家的门铃...您可以打我电话与客人进行通话。
uchar code ud_guest_ring[] = "60A8597DFF0C67095BA24EBA630954CD60A85BB6768495E894C3002E002E002E60A853EF4EE56253621175358BDD4E0E5BA24EBA8FDB884C901A8BDD3002";
//您好,操作已完成啦~~~
uchar code ud_operation_s[] = "60A8597DFF0C64CD4F5C5DF25B8C62105566007E007E007E";

//您好,当前报警状态停止了,恢复正常防盗状态。
uchar code ud_alarm_cancel[] = "60A8597DFF0C5F53524D62A58B6672B66001505C6B624E86FF0C6062590D6B635E38963276D772B660013002";
//注意:防盗系统触发了
uchar code ud_alarm_started[] = "6CE8610FFF1A963276D77CFB7EDF89E653D14E86";


//===============================================短信指令===========================================================
//开防盗
uchar code ud_alarm_start[] = "5F00963276D7";
//关防盗
uchar code ud_alarm_stop[] = "5173963276D7";

//开继电器一
uchar code ud_relay_1_on[] = "5F007EE7753556684E00";
//开继电器二
uchar code ud_relay_2_on[] = "5F007EE7753556684E8C";
//开继电器三
uchar code ud_relay_3_on[] = "5F007EE7753556684E09";
//开继电器四
uchar code ud_relay_4_on[] = "5F007EE77535566856DB";
//开继电器五
uchar code ud_relay_5_on[] = "5F007EE7753556684E94";
//开继电器六
uchar code ud_relay_6_on[] = "5F007EE775355668516D";
//开继电器七
uchar code ud_relay_7_on[] = "5F007EE7753556684E03";
//开继电器八
uchar code ud_relay_8_on[] = "5F007EE775355668516B";
//开全部继电器
uchar code ud_relay_all_on[] = "5F00516890E87EE775355668";


//关继电器一
uchar code ud_relay_1_off[] = "51737EE7753556684E00";
//关继电器二
uchar code ud_relay_2_off[] = "51737EE7753556684E8C";
//关继电器三
uchar code ud_relay_3_off[] = "51737EE7753556684E09";
//关继电器四
uchar code ud_relay_4_off[] = "51737EE77535566856DB";
//关继电器五
uchar code ud_relay_5_off[] = "51737EE7753556684E94";
//关继电器六
uchar code ud_relay_6_off[] = "51737EE775355668516D";
//关继电器七
uchar code ud_relay_7_off[] = "51737EE7753556684E03";
//关继电器八
uchar code ud_relay_8_off[] = "51737EE775355668516B";
//关全部继电器
uchar code ud_relay_all_off[] = "5173516890E87EE775355668";

//?
uchar code ud_inquiry[] = "FF1F";//查询继电器状态
//?
uchar code ud_inquiry2[] = "003F";

//=======================AT指令===================================
uchar code ATD[] = "ATD";  
uchar code AT[] = "AT";
uchar code ATE[] = "ATE";				//关回显指令
uchar code AT_IPR[] = "AT+IPR=2400";	//设置波特率	
uchar code ATH[] = "ATH";				//挂断 
uchar code ATA[] = "ATA";  				//接听
uchar code AT_CLIP[] = "AT+CLIP=1";		//设置来电显示
uchar code AT_CPMS[] = "AT+CPMS=sm,sm,sm";			//短信存储在sim卡中
uchar code AT_CNMI[] = "AT+CNMI=2,2";	//设置信息提示,新信息到达直接打到串口上
uchar code AT_CMGF[] = "AT+CMGF=0";	//设置短信的格式为pdu格式
uchar code AT_CMGS[] = "AT+CMGS=";	//发送短信指令
uchar code AT_CSCA[] = "AT+CSCA=";	//设置短信中心号码


//======================SMS PDU MODE=================================================
uchar idata	pdu_cmgs_length[3];	//at+cmgs=*的长度,计算得到,去掉信息中心后的字符长度

uchar code 	pdu_sca_len_type[] = "0891"; //服务中心地址的长度与类型
uchar idata	pdu_sms_center[15];	//转换后的信息中心号码//////////////////////////需要更改
uchar code 	pdu_type_mr[] = "1100";//pdu类型与信息参考
uchar code 	pdu_phone_length_type[] = "0B81";//发送目标手机号码的长度与类型
uchar 		pdu_phone[13];		//转换后的电话///////////////、//////////////////需要更改
uchar code 	pdu_pid[] = "00";	//协议标识
uchar code 	pdu_dcs[] = "08";	//数据编码方式,这里是16bit方式编码(汉字)
uchar code	pdu_vp[] = "A7";	//信息有效期
uchar idata	pdu_udl[3];	//用户数据长        
uchar 	   *pdu_ud;			//用户数据  



//========================================GSM状态标志=============================================
uchar code OK[] = "OK";	//回显的OK
uchar code sms_new[] = "089168";//新信息关键字

bit gsm_send_ready = 1;//串口发送标志位
bit at_ok = 0;	//TC35I回显了OK的标志位
bit gsm_ring = 0;//响铃标志位
bit gsm_sms_new = 0;//新信息标志
uchar gsm_sms_state = 0;//新信息状态,1为有信息,而且是主人信息,2为信息非主人信息

#define GSM_SMS_UD (4*13)	//接收信息的用户数据长度,四的倍数
uchar gsm_sms_ud[GSM_SMS_UD + 1]; //接收到的信息数据,须是内部RAM以减少运行时间


//==========================================函数声明部分============================================

//GSM基本操作部分
void gsm_power_on(void);//开机
void gsm_power_off(void);//关机
void gsm_uart_init(void);//串口设置
void gsm_init(void);
void gsm_send_byte(uchar c);//向GSM发送一个字节
void gsm_send_str(uchar *p);//发送一串字符
void gsm_at(uchar *p);//发送一个at指令
void gsm_receive(uchar sbuf);//中断接收一字节的处理
void gsm_call(void);//拨打电话主人

void gsm_poweroff(void);//关机
void gsm_start(void);//开机
void gsm_reboot(void);//重启

//发pdu信息相关函数
void gsm_sms_init(void);//初始化pdu短信发送相关数据
void gsm_conver_pdu(uchar *p, uchar *pdu);	//地址或电话号码转换,偶+F
void gsm_work_out_data(uchar *p_data);	//算出pdu_udl和cmgs的长度
void gsm_send_sms(uchar *p_data);//发送一条 短信 (Unitcode码)

//GSM消息处理函数
void gsm_error(void);//GSM错误处理
//void gsm_scan(void);//这个是处理gsm模块消息的,须经常扫描
//void gsm_sms_unknow();//处理非主人信息
//void gsm_sms_host();//处理主人来信



//=================================函数定义部分=====================================================
//点火线开机
void gsm_power_on(void)
{
 	gsm_igt = 0;
	delay_s(1);
	gsm_igt = 1;
}

//强制关机
void gsm_power_off(void)
{
	gsm_emergoff = 0;
	delay_s(3);
	gsm_emergoff = 1;
}
//初始化串口,300
void gsm_uart_init(void)
{
    TMOD = 0x20;
    SCON = 0x50;
    TH1 = 0xF4;
    TL1 = TH1;
    PCON = 0x00;
    EA = 1;
    ES = 1;
    TR1 = 1;
}

//中断
//接受一字节
void gsm_interrupt(void) interrupt 4 
{ 	
	uchar sbuf;
    if(RI){	
		sbuf = SBUF;
		RI = 0;		
		gsm_receive(sbuf);//接收一个字节
     }
    else {
        TI = 0;
		gsm_send_ready = 1;//允许发送了
	}
}

//发送一字节
void gsm_send_byte(uchar c)
{
	while(!gsm_send_ready);	//允许发送后在发送

    SBUF = c;
    gsm_send_ready = 0;
}

//向gsm发送字符串
void gsm_send_str(uchar *p)
{
	at_ok = 0;	//清除OK标志	  	
 	for(; *p != '\0'; p++)//发送字符串
		gsm_send_byte(*p);
}

//发送一个at指令
void gsm_at(uchar *p)
{
	gsm_send_str(p);
	gsm_send_byte('\r');//发送回车		
}


//处理接收到的字符,来电判断,OK判断,信息接收
void gsm_receive(uchar sbuf)
{
	static uchar i = 0;	//处理OK回显
	static uchar j = 0; //处理来电
	static uchar k = 0; //处理新信息
	static uchar n = 0; //接收新信息
	static bit new_sms_flag = 0; //新信息到来寄存器

	//OK查询
	if(sbuf == OK[i++]){
	 	if(i == 2)
			at_ok = 1;//接收到ok回显
	}
	else	i = 0;
	

	//处理来电部分(只接听主人电话)
	if(sbuf == phone[j++]){
		if(j == 11) 	 
		    gsm_ring = 1;//写来电标志
	}
	else	j = 0;
	
	//检测处理新信息
	if(sbuf == sms_new[k++]){
	 	if(k == 6){
			new_sms_flag = 1;//新信息到
		}
	}
	else k = 0;

	if(new_sms_flag == 1){ //接收新信息
		++n;
		if(n < 20)	return;

		//检测手机号码		n=31为手机末尾号码,n = 20为手机第一个字码
		if(n < 32){	
			if(n == 20)
				gsm_sms_state = 100;	
			if(pdu_phone[n - 20] == sbuf)	
				gsm_sms_state++;//这个累加到112则信息为主人发送的

			pdu_phone[n - 20] = sbuf;//存放来信号码
		}

									 	
		else if(n >= 52){	//存放信息数据部
				if(n - 51 <= GSM_SMS_UD && sbuf != '\r')
					gsm_sms_ud[n - 52] = sbuf;
				else {//接收完毕
					gsm_sms_ud[n - 52] = '\0';
					new_sms_flag = 0;//清除信息接收标志
					n = 0;
				 	if(gsm_sms_state == 112)	
						gsm_sms_state = 1;//主人信息
					else	
						gsm_sms_state = 2;//非主人信息	
				}  	
			}		
				 
		}			
}

void gsm_init(void)
{
	gsm_uart_init();//初始化串口
	gsm_power_on();
	delay_s(3);
	gsm_at(AT);
	delay_ms(200);		
	gsm_at(ATE);	//关指令回显
	delay_ms(200);
	gsm_at(AT_IPR);//设置波特率
	delay_ms(200);
	gsm_send_str(AT_CSCA); //设置中心号码
	gsm_at(sms_center);
	delay_ms(200);
	gsm_at(AT_CLIP);//设置来电显示
	delay_ms(200);
	gsm_at("AT^SNFS=2");//audio mode 2, using ep2,mic2,handset free, adjustable
	delay_ms(200);
	gsm_at(AT_CPMS);//设置短信存储在sim卡中
	delay_ms(200);
	gsm_at(AT_CNMI);//设置新信息提示方式	
	delay_ms(200);
	gsm_sms_init();//初始化sms发送  
	delay_ms(200);
	gsm_send_sms(ud_init_ok);//发送成功开机短信
	//gsm_call();
}


void gsm_send_sms(uchar *p_data)
{	 
	gsm_at(AT);
	pdu_ud = p_data;//用户数据Unicode代码
	gsm_work_out_data(pdu_ud);//计算出cmgs发送的长度与udl
	delay_ms(200);
	gsm_at(AT);
	delay_s(1);
	gsm_at(AT_CMGF);//设置pdu模式
	delay_s(1);
	gsm_send_str(AT_CMGS);
	gsm_at(pdu_cmgs_length); //开始发送短信 
	delay_s(1);	
	gsm_send_str(pdu_sca_len_type);//服务中心地址的长度与类型
	gsm_send_str(pdu_sms_center);//转换后的信息中心号码
	gsm_send_str(pdu_type_mr);//pdu类型与信息参考
	gsm_send_str(pdu_phone_length_type);//发送目标手机号码的长度与类型
	gsm_send_str(pdu_phone);//转换后的电话
	gsm_send_str(pdu_pid);//协议标识
	gsm_send_str(pdu_dcs);//数据编码方式
	gsm_send_str(pdu_vp);//信息有效期
	gsm_send_str(pdu_udl);//用户数据长度
	gsm_send_str(pdu_ud);//用户数据
	gsm_send_byte(0x1A);
	gsm_send_byte('\t');
	delay_s(5);	//等待模块发送信息完毕
}

//计算pdu短信中的未知数
void gsm_work_out_data(uchar *p_data)
{
	uchar i;
	uchar word;//用户数据长度
	
	for(i = 0; *p_data != '\0'; i++, p_data++);//计算用户数据的长度
	word = i;//用户数据长度

	i /= 2;
	
	//完成pdu_udl的字符串
	if(i / 16 >= 10)	pdu_udl[0] = i / 16 - 10 + 'A';
	else	pdu_udl[0] = i / 16 + '0';
	if(i % 16 >= 10)	pdu_udl[1] = i % 16 - 10 + 'A';
	else	pdu_udl[1] = i % 16 + '0';
	pdu_udl[2] = '\0'; 
	
	word += 28;//去掉信息中心后(PDU 数据包字符数-2)/2
	word /= 2;	
	pdu_cmgs_length[0] = word / 10 + '0';//cmgs的长度,用字符表示
	pdu_cmgs_length[1] = word % 10 + '0';
	pdu_cmgs_length[2] = '\0';
}

//把p号码奇偶对换,非偶加'F',转换后存放在pdu中
void gsm_conver_pdu(uchar *p, uchar *pdu)
{
	uchar i = 0;
	while(p[i++] != '\0');//算出长度
	i-=2;

	if(i % 2 == 0){//基数添加F
		pdu[i] = 'F';
		pdu[i + 1] = p[i];
		pdu[i + 2] = '\0';
		i--;	
	}
	else	pdu[i+1] = '\0';
	
	for(; i < 30; i -= 2){
		pdu[i] = p[i - 1];
		pdu[i - 1] = p[i];
	}
}

//发送pdu短信的前提工作
void gsm_sms_init(void)
{
	gsm_conver_pdu(&sms_center[1], pdu_sms_center);//转换信息中心号码
	gsm_conver_pdu(phone, pdu_phone);//转换电话号码
}

//拨打电话主人
void gsm_call(void)
{
 	gsm_at(AT);
	delay_s(1);
	gsm_send_str(ATD);
	gsm_send_str(phone);
	gsm_at(";");
	delay_s(20);
}



//GSM错误处理
void gsm_error(void)
{
	gsm_at("AT^SMSO");// 关机指令
	delay_s(1);
	gsm_power_off();  //强制关机
	gsm_init();	  	//开机初始化
}


/*
//这个是处理gsm模块消息的,须经常扫描
void gsm_scan(void)
{
	uchar i;

	if(gsm_ring){//主人来电
		
	// 	gsm_at(ATA);//接听来电
		gsm_at(ATH);//测试用------------------------------------------------
		delay_s(2);
		gsm_ring = 0;
	}

   	for(i = 0; i < 200; i++){ //检测GSM
		gsm_at(AT);
		delay_ms(200);
		if(at_ok == 1)
			i = 250; //GSM正常
    }
	if(i != 251)
		gsm_error();//GSM错误处理

	if(gsm_sms_state == 1){
		gsm_sms_host();//处理主人来信
	 	gsm_sms_state = 0;
	}

	else if(gsm_sms_state == 2){
		gsm_sms_unknow();//处理非主人信息
		gsm_sms_state = 0;
	}
}

*/

/*
//处理主人来信,内容已经存在gsm_sms_ud[]中
void gsm_sms_host(void)
{
	gsm_send_sms(gsm_sms_ud);////测试用--------------------------------------
	if(strcmp(gsm_sms_ud, ud_help) == 0)//帮助指令
		gsm_sms_help(); 
	
}

//处理非主人信息
void gsm_sms_unknow(void)
{
	gsm_send_sms(gsm_sms_ud);////测试用--------------------------------------
	delay_s(3);
	gsm_call();//测试用--------------------------------------
}
*/
//=============================================================================================================
#endif

//附加说明:
//	通过gsm_init();初始化GSM模块,包括设置串口通信,波特率设置为2400,关指令回显,开来电显示号码,新信息直接
//	输出到mcu不作存储,初始化完毕后,须经常执行gsm_scan();以处理GSM的消息


 

你可能感兴趣的:(测试,手机,byte,sms,电话,delay)