📄 main.c
字号:
/* IO 口模拟232通讯程序
使用两种方式的C程序 占用定时器0
**********************************************/
#include <ctype.h>
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define DEBUG_SMS
#define byte unsigned char
extern void sector_erase(unsigned short int dataAddr);
extern void byte_program(unsigned short int dataAddr, unsigned char dataByte);
extern unsigned char byte_verify(unsigned short int dataAddr);
extern bit sendSMS(byte *telnum, byte *STRING);
extern bit getAck(byte Len,byte *getData);
extern void deleSMS(byte *POINT);
byte gsmDecode7bit(unsigned char* pSrc, char* pDst, byte nSrcLength);
pdata byte pData[256];
sbit BT_SND =P1^7;
sbit BT_REC =P1^6;
//sbit BT_SND =P3^1;
//sbit BT_REC =P3^0;
//sbit LED_RED =P1^1;
typedef struct{
byte Index[4]; //短消息索引
byte TelNum[16];
byte Ref[20];
byte SMS_text[100];
}SMS_INFO;
byte RxFlag=0;
byte RecTimeOut=0;
byte RecStatus=0;
byte RxCount=0;
bit SMS_TYPE;
// 设置接收短信的手机号
//6
//code byte Owner[]="Owner";
// 更改密码
//code byte Password[]="Password";
//取信息
//code byte GetMessage[]="Get Message";
code byte ACK_OK[]={'O','K',0X0D,0X0A,0X00};
//code byte CharZ[]={'>',0X00};
//code byte CMG[]={'+','C','M','G',0};
bit LongDataFlag;
#ifdef DEBUG_SMS
extern void putch(byte ch);
#endif
#define F_TM F0
#define TIMER0_ENABLE TL0=TH0; TR0=1;
#define TIMER0_DISABLE TR0=0;
sbit ACC0= ACC^0;
sbit ACC1= ACC^1;
sbit ACC2= ACC^2;
sbit ACC3= ACC^3;
sbit ACC4= ACC^4;
sbit ACC5= ACC^5;
sbit ACC6= ACC^6;
sbit ACC7= ACC^7;
// 在 S 串中找 串 T ,算法如下。 从第一个数开始比较之前,先求出各串的长度。
// 当比较的字符数都小于各自的串长度时,进行比较 当取出的数据比较相等时,设量i,j 都加 1.
// 不相等时, i=i-j+2,j=1;
// 退出比较,当j> t 串的长度时,比较成功。即在 i- t 长处发现相待。
unsigned char cmp(unsigned char *array1,unsigned char *array2)
{
unsigned char i;
unsigned char m=strlen (array2);
for(i=0;i<256-m;i++)
{
if(memcmp(&array1[i],array2,m)==0)
return(i);
}
return(0xff);
}
//用IO模拟串口收,发数据占用定时器0
void IntTimer0() interrupt 1
{
F_TM=1;
}
//模拟串口,发送一个字符
void PSendChar(unsigned char inch)
{
ACC=inch;
F_TM=0;
BT_SND=0; //start bit
TIMER0_ENABLE; //启动
while(!F_TM);
BT_SND=ACC0; //先送出低位
F_TM=0;
while(!F_TM);
BT_SND=ACC1;
F_TM=0;
while(!F_TM);
BT_SND=ACC2;
F_TM=0;
while(!F_TM);
BT_SND=ACC3;
F_TM=0;
while(!F_TM);
BT_SND=ACC4;
F_TM=0;
while(!F_TM);
BT_SND=ACC5;
F_TM=0;
while(!F_TM);
BT_SND=ACC6;
F_TM=0;
while(!F_TM);
BT_SND=ACC7;
F_TM=0;
while(!F_TM);
BT_SND=1;
F_TM=0;
while(!F_TM);
F_TM=0;
TIMER0_DISABLE; //停止timer
}
//模拟串口,接收一个字符
unsigned char PGetChar()
{
TIMER0_ENABLE;
F_TM=0;
while(!F_TM); //等过起始位
ACC0=BT_REC;
TL0=TH0;
F_TM=0;
while(!F_TM);
ACC1=BT_REC;
F_TM=0;
while(!F_TM);
ACC2=BT_REC;
F_TM=0;
while(!F_TM);
ACC3=BT_REC;
F_TM=0;
while(!F_TM);
ACC4=BT_REC;
F_TM=0;
while(!F_TM);
ACC5=BT_REC;
F_TM=0;
while(!F_TM);
ACC6=BT_REC;
F_TM=0;
while(!F_TM);
ACC7=BT_REC;
F_TM=0;
while(!F_TM)
{
if(BT_REC)
{
break;
}
}
TIMER0_DISABLE; //停止timer
return ACC;
}
//发送字符串
unsigned char send_str(unsigned char *str)
{
unsigned char i;
i=0;
while( str[i] != 0 ){
PSendChar(str[i]);
i++;
}
return(0);
}
unsigned char SendAT(unsigned char *command,unsigned char * Cmp_Data,unsigned char *ACK)
{
unsigned char i=0;
unsigned char ACK_LEN;
unsigned long m;
if(strlen(command) > 0)
{
while(1)
{
if(command[i] == 0 || command[i] == '\n' || command[i] == '\r' )
{
PSendChar(0x0D);
break;
}
else
{
PSendChar(command[i]);
}
i++;
}
}
ACK_LEN = strlen(Cmp_Data);
/*
三秒钟内无回复,认为超时退出.
*/
m = 500000L;
i = 0;
while(m--)
{
if(BT_REC==0)
{
ACK[i] =PGetChar();
m = 200000L;
if(i<0xff)
i+=1;
if(i>=ACK_LEN)
{
if(memcmp(&ACK[i-ACK_LEN],Cmp_Data,ACK_LEN)==0)
{
if(i>=0x80) LongDataFlag = 1; //收到的数据确实很长
return(i+0x80);
}
}
}
}
return(i); //回复收到的数据长度.
}
unsigned long delay;
void Delay100mS(byte Cnt)
{
unsigned int m_100MS;
m_100MS = 0;
while(--Cnt)
{
for(m_100MS=0;m_100MS<60000;m_100MS++);
}
}
bit CPL;
void main()
{
byte i,j,cc,Len;
byte Pt; //分析信息指针
SMS_INFO pdata *Info = &pData[0];
SCON= 0X50; //定议串口
TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */
PCON=0X80; //波特率加倍
TR0=0;
TF0=0;
TH0 =256-80; //用IO模拟的串口速率为 19200.
TL0=TH0;
ET0=1; //允许定时器0中断
TH1 = 0XF6; //单片机的串口速度为9600,用于接收GPS数据.
TL1 = 0XF6;
TR1 = 1; //启动定时器1
ES = 1; //允许串口中断
EA=1; //开总中断
delay = 0;
sector_erase(0x2800);
while(1)
{
#ifdef DEBUG_SMS
putch('A');
#endif
memset(pData,0,256);
Len =SendAT("ATE0",ACK_OK,pData+150);
if(Len>=0X80) break; //开机是如果未接上SMS模块,则一直等待
}
// EEPROM用4扇区可用.
/*
0--14 为密码
15--39 为手机号.
40--59为 管理者名字
60为 BCC
61,62为 55,66
*/
cc = 0;
for(i=0;i<60;i++)
cc +=byte_verify(0x2E00+i);
if(byte_verify(0x2E00+60)!=cc ||byte_verify(0x2E00+61)!=0x55 || byte_verify(0x2E00+62)!=0x66)
{
putch('B');
sector_erase(0x2E00); //把旧数据擦除
memset(&pData[0],0xff,100);
for(i=0;i<6;i++)
pData[i]='8'; //默认密码为 888888
pData[6]=0;
memcpy(pData+15,"0D91683156909013F4",19);
memcpy(pData+40,"Hello",6);
Len = 0;
for(i=0;i<60;i++)
Len +=pData[i];
pData[60] =Len;
pData[61] =0x55;
pData[62] =0x66;
for(i=0;i<63;i++)
byte_program((0x2E00+i),pData[i]);
}
else
{
for(i=0;i<63;i++)
{
pData[i] =byte_verify(0x2E00 +i);
putch(pData[i]);
}
}
sendSMS(pData+15,"How Are You Owner !"); //开机时发一条短信报告.
REN = 1;
while(1)
{
REN = 1;
delay++;
if(delay>=600000L) //读短信
{
REN = 0;
Len=0;
LongDataFlag = 0;
memset(pData,0,256);
Len =SendAT("ATE0",ACK_OK,pData);
if(cmp(pData,"OK")==0XFF)
goto NoMobil;
putch('O');
putch('K');
putch(0x0d);
putch(0x0a);
LongDataFlag =0;
memset(pData,0,256);
SendAT("AT+CMGL=0",ACK_OK,pData);
/*
if(CPL)
{
CPL=0;
SendAT("AT+CMGR=6",ACK_OK,pData); //密码 888888 设置手机为 13650909314
}
else
{
CPL =1;
SendAT("AT+CMGR=7",ACK_OK,pData); //旧密码 888888 更改密码为456ABCJIE
}
*/
Pt =cmp(pData,"+CMG");
if(Pt==0xff) goto NoMobil;
{
for(i=0;i<256;i++)
{
if(pData[i]==0) break;
putch(pData[i]);
}
putch('N');
putch('e');
putch('w');
putch('S');
putch('M');
putch('S');
putch(0x0d);
putch(0x0a);
//短消息的第9个字节开始为 消息索引
Info->Index[0] = 0;
Info->Index[1] = 0;
Info->Index[2] = 0;
Info->Index[3] = 0;
if(pData[Pt+7]!=0x2C)
{
Info->Index[0] = pData[Pt+7];
if(pData[Pt+8]!=0x2C)
{
Info->Index[1] = pData[Pt+8];
if(pData[Pt+9]!=0x2C)
{
Info->Index[2] = pData[Pt+9];
}
}
}
putch('I');
putch('n');
putch('d');
putch('e');
putch('x');
putch(0x0d);
putch(0x0a);
for(i=0;i<4;i++)
{
if(Info->Index[i]!=0)
putch(Info->Index[i]);
}
for(Pt=9;Pt<25;Pt++)
{
if(pData[Pt]==0x0A) //换行,信息开始.
break;
}
if(Pt==25)
{
putch('S');
putch('M');
putch('S');
putch('e');
putch('r');
putch('r');
putch('o');
putch('r');
putch(0x0d);
putch(0x0a);
goto NoMobil;
}
//
//判断短信中心的数据长度.
Pt +=1;
Len =pData[Pt]<=0x39 ? pData[Pt]-0x30:pData[Pt]-0x41+10;
Len =(Len<<4) + (pData[Pt+1]<=0x39 ? pData[Pt+1]-0x30:pData[Pt+1]-0x41+10);
Len +=2;
Len =Len <<1; //乘以2,为字节总数.
Pt +=Len; //Pt指向目的手机的开始地址.
//判断目的手机的号码数
Len =pData[Pt]<=0x39 ? pData[Pt]-0x30:pData[Pt]-0x41+10;
Len =(Len<<4) + (pData[Pt+1]<=0x39 ? pData[Pt+1]-0x30:pData[Pt+1]-0x41+10);
//如果码号数为奇数,要加1成为偶数.
i = Len;
if(i&0x01) Len +=1;
putch('t');
putch('e');
putch('l');
putch(0x0d);
putch(0x0a);
//把目的手机号保存下来.
for(i=Pt;i<Pt+Len+4;i++)
{
Info->TelNum[i-Pt] =pData[i];
}
Info->TelNum[i-Pt] =0; //手机号结束符
//指针指向手机号码后的第一个字节.
Pt = i;
for(i=0;i<Len+4;i++)
putch(Info->TelNum[i]);
if(pData[Pt+2]=='0' && pData[Pt+3]=='0') //是ASC码短信.7-bit编码
{
SMS_TYPE=0;
}
else if(pData[Pt+2]=='0' && pData[Pt+3]=='8')
{
SMS_TYPE=1;
}
else //只处理PDU格式和ASC码格式.其它不处理
goto InfoEnd;
Pt +=18; //短信息数据长度字节.
// putch(pData[Pt]); //转换成ASC码后的字符.
// putch(pData[Pt+1]); //短信字符数
Len =pData[Pt]<=0x39 ? pData[Pt]-0x30:pData[Pt]-0x41+10;
Len =(Len<<4) + (pData[Pt+1]<=0x39 ? pData[Pt+1]-0x30:pData[Pt+1]-0x41+10);
Len = Len<<1; //乘以2,为信息字节总数.
Pt+=2; //指向信息开始地址.
putch('I');
putch('n');
putch('f');
putch('o');
if(SMS_TYPE==0) //ASC码,要用7-BIT解码解出内容
{
i = Pt;
j = Pt;
while(1)
{
if(pData[i]==0x0D || pData[i]==0x0A) break;
cc =pData[i]<=0x39 ? pData[i]-0x30:pData[i]-0x41+10;
cc =(cc<<4) + (pData[i+1]<=0x39 ? pData[i+1]-0x30:pData[i+1]-0x41+10);
pData[j]=cc;
i +=2;
j +=1;
}
Len =gsmDecode7bit(&pData[Pt],&Info->SMS_text[0],j-Pt);
Info->SMS_text[Len] = 0;
putch('A');
}
else //PDU码,解出内容
{
j = 0;
for(i=0;i<Len;)
{
i+=2;
cc =pData[Pt+i]<=0x39 ? pData[Pt+i]-0x30:pData[Pt+i]-0x41+10;
i+=1;
cc =(cc<<4) + (pData[Pt+i]<=0x39 ? pData[Pt+i]-0x30:pData[Pt+i]-0x41+10);
Info->SMS_text[j] = cc;
i+=1;
j+=1;
}
Info->SMS_text[j] =0;
Len = j;
putch('P');
}
putch(0x0d);
putch(0x0a);
putch('T');
putch('E');
putch('X');
putch('T');
putch(':');
putch(' ');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -