您的位置:首页 > 其它

用VC实现发送和接受短信

2005-04-14 01:48 288 查看
前些日子感觉得练习一下VC了,所以就有想,平时发短信那么累,手机键盘又不好用,而我又有数据线,为什么不可以用电脑直接发送短信呢?想法一出来,就开始找资料开始行动吧!
由于程序涉及的方面很多,因此只讲关键的主要的部分。
首先,得了解手机和电脑之间是通过什么通讯的,我的手机是有红外接口,电脑上接一个红外适配器,就可以与手机连接了,而Windows是把红外设备当作一个串口来看待的,所以关键就是在于如何用程序来控制COM端口来发送和接收数据。在网上找了很多资料然后就开始编写代码:
列举出系统中的所有的串口:这个需要操作注册表来实现,代码如下:
void CSendMsgDlg::GetAllCom()
{
HKEY hKey;
LONG ret;
OSVERSIONINFO osvi;
BOOL bOsVersionInfoEx;
char keyinfo[100],comm_name[200],ValueName[200];
int i;
DWORD sType,Reserved,cbData,cbValueName;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

memset(keyinfo,0,100);
strcpy(keyinfo,"HARDWARE//DEVICEMAP//SERIALCOMM");
i=0; sType=REG_SZ;Reserved=0;
bOsVersionInfoEx =GetVersionEx(&osvi);
ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyinfo,0,KEY_ALL_ACCESS,&hKey);
if (ret==ERROR_SUCCESS){
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
do
{
cbData=200;cbValueName=200;
memset(comm_name,0,200);
memset(ValueName,0,200);
ret=RegEnumValue(hKey,i,ValueName,&cbValueName,NULL,&sType,(LPBYTE)comm_name,&cbData);
if (ret==ERROR_SUCCESS)
{
//m_list.Add(comm_name);
m_comm.AddString(comm_name);
i++;
}
}while (ret==ERROR_SUCCESS);
}
}
RegCloseKey(hKey);
}
得到所有的串口了,现在就应该打开串口了,一般来说计算机自己有两个串口,而红外线的标志一般是COM3。
打开串口的代码:
void CSendMsgDlg::OnButton1()
{
char str[100];
DWORD dwThreadID;
memset(str,0,100);
int sel = m_comm.GetCurSel();
if(sel == -1)
{
AfxMessageBox("对不起,请选择一个接口!");
return;
}
m_comm.GetLBText(sel,str);
m_hCom = CreateFile(str,
GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if(m_hCom == INVALID_HANDLE_VALUE)
{
AfxMessageBox("对不起,连接失败!");
return;
}
ASSERT(m_hCom!=INVALID_HANDLE_VALUE);

SetCommMask(m_hCom, EV_RXCHAR|EV_TXEMPTY );//设置事件驱动的类型

SetupComm( m_hCom, 1024,512) ; //设置输入、输出缓冲区的大小

PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清干净输入、输出缓冲区

COMMTIMEOUTS CommTimeOuts ; //定义超时结构,并填写该结构
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;

SetCommTimeouts( m_hCom, &CommTimeOuts ) ;//设置读写操作所允许的超时

DCB dcb;

GetCommState(m_hCom, &dcb ) ; //读串口原来的参数设置

dcb.BaudRate =9600;

dcb.ByteSize =8;

dcb.Parity = NOPARITY;

dcb.StopBits = ONESTOPBIT ;

dcb.fBinary = TRUE ;

dcb.fParity = FALSE;

SetCommState(m_hCom, &dcb ) ; //串口参数配置
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_OverlappedRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_OverlappedWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hExit = CreateEvent(NULL,NULL,FALSE,NULL);
hCommWatchThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,0,(LPTHREAD_START_ROUTINE)CommWatchProc,this,0, &dwThreadID );
if(hCommWatchThread == NULL)
{
AfxMessageBox("对不起,连接失败!");
return;
}

ASSERT(hCommWatchThread!=NULL);
m_bConnected = true;
m_type = 0;
SendData("AT/r/n",strlen("AT/r/n"));
PurgeComm(m_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
m_conn.EnableWindow(false);
m_view.EnableWindow(true);
m_send.EnableWindow(true);

}
由于在CreateFile里面设置了一个参数“FILE_FLAG_OVERLAPPED”,所以与串口要按照异步的方式进行通讯,所以启动一个线程专门作为接收数据的线程:
UINT CSendMsgDlg::CommWatchProc(LPARAM parm)
{
CSendMsgDlg * dlg = (CSendMsgDlg *)parm;
HANDLE m_hComDev = dlg->m_hCom;
DWORD dwBytesRead;
char buffer[8000];

DWORD ret;
while(true)
{
memset(buffer,0,8000);
int r = dlg->ReadData(buffer,8000);
// TRACE("%s",buffer);
if(strlen(buffer) != 0)
dlg->ProcessData(buffer);
Sleep(1000);
}
return 0;
}
下面是读写COM口的函数:
int CSendMsgDlg::SendData(char *buffer, DWORD dwBytesWritten)
{
BOOL bWriteStat;
DWORD dwBytesRead;
bWriteStat = WriteFile(m_hCom, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
return ((int)dwBytesRead);
}
return(0);
}
return ((int)dwBytesRead);
}
int CSendMsgDlg::ReadData(char *buffer, DWORD dwBytesRead)
{
BOOL bReadStatus;
bReadStatus = ReadFile( m_hCom, buffer, dwBytesRead, &dwBytesRead,&m_OverlappedRead);
if(!bReadStatus)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
return ((int)dwBytesRead);
}
return(0);
}
return ((int)dwBytesRead);
}
当然了,这里的方法并不是唯一选择。
上面主要是对COM口的操作,这跟手机和短信无关,下面的部分就是与手机短信有关的部分了:
首先,得知道如何利用手机的AT指令集,我们现在需要的指令不多,只有读短信和发短信。
关于AT指令的其他命令网上有很多资料这里也不再提及了
命令:AT+CMGL
命令说明:获取短信列表
格式举例:
AT+CMGL
+CMGL: 1, 1, ,38
0891683108200205f0240D91683128500474F7000850403191611200126211572856FE4E6699865B
664E6054620021
+CMGL: 2, 1, ,70
0891683108200205f0240D91683128500474F70008504031919113003262114E0076F45C31662F4E
09597D5B66751F0020563F563F51765B9E6211662F57287BEE74039986770B4EBA5BB68DF3821E
+CMGL: 3, 1, ,64
0891683108200205f0240D91683128500474F70008504031913272002C5F53713667094E864E0D8F
C790FD662F59274E005C0F59B959B94E864F608001725B8FD860F354035AE98349
+CMGL: 4, 1, ,82
0891683108200205f0240D91683128500474F70008504031918284003E4F608D767D27542C4F6076
848BFE542700206B6A5FC3773C8FD84E0D5C1100204E004F1A80015E0863D095EE4F604F6053EF52
2B556590FD4E0D4F1A0020
+CMGL: 5, 1, ,154
0891683108200205f0240D91683128500474F70008504031916344008690A34F60600E4E484E0D4E
CE59345F0059CB542C002080AF5B9A662F5FEB80038BD54E864F60624D77406025002056F0559D54
96556189814E0D5C3157507B2C4E006392572880015E08773C76AE5E954E0B5C314E0D56F04E8600
20621173B05728592959294E5F662F4EE5549655617EF46301751F547D554A89814E0D65E9776177
404E86
+CMGL: 6, 1, ,88
0891683108200205f0240D91683128500474F70008504031914422004490A34F605C3153BB4E7090
1A51FA9898768480015E08002089814E0D5C31627E4EBA66FF4F6080030020603B776189C95BB966
1380D662404EE56211767D59294E0D7761
+CMGL: 7, 1, ,63
0891683108701305f0240BA13178855898F10008503013011285202C4F60684C4E0A7684004C0049
004E005500584E2D5348501F621162FF5BBF820D88C54E004E0B884C4E0DFF1F
+CMGL: 8, 1, ,62
0891683108200205f0240D91683128500474F70008504031913523002A54CE54404F6090A34E4880
6A660E597D597D770B4E66591A505A70B9989880AF5B9A5C3180FD8FC77684
+CMGL: 9, 1, ,32
0891683108301105f0040D91683139116779F30008503013120565000C53EF4EE563A752364E8654
17
+CMGL: 10, 1, ,36
0891683108301105f0040D91683139116779F300085030131285230010662F4E0D662F7F51901F5F
886162554A
+CMGL: 11, 1, ,38
0891683108301105f0040D91683139116779F30008503013220031001259295440002090A3662F4E
0D662F4E2D6BD2
+CMGL: 12, 1, ,38
0891683108301105f0040D91683139116779F30008503013221055001290A36211548B529E554A91
CD542F884C5417
+CMGL: 16, 1, ,151
0891683108705305f0040BA13178536816F3000850402090311220848FD979CD65F650194F605728
4E0A73ED4E865427FF0C621160F395EE95EE4F604E004E9B4E8B60C530024F6053EF4EE5544A8BC9
621153BB5E74672C79D1658779D159276982662F591A5C114E0A7EBF541730029EBB70E64F604E86
30024F604E5F628A5F2068A6534E768475358BDD544A8BC962115427FF0C514D5F97621165E0804A
+CMGL: 17, 1, ,102
0891683108301105f0040D91683139116779F300085040306112230052636E8BF46C5F6D9B768400
28003400305929653B514B59275B6682F18BED56DB7EA700290020633A597D7684002E002053EF4E
E55E2E4F608BA1521260278FC77EA7002E00204F604E708BD598984E865417
+CMGL: 18, 1, ,85
0891683108705305f0040BA13178536816F3000850404022206220424ECA59298BB25230534A8DEF
5C316CA175354E86FF0C611F89C9602A602A768430024F604EE5540E8FD8662F53EB621155E654AA
5427611F89C96BD48F834EB25207
+CMGL: 20, 1, ,56
0891683108705505f0040D91683175804276F800085040508182950024534E4E3A76847EB34E9B9E
1F4EBA5E26774088AB5B504E0A73ED3000771F768460506016
+CMGL: 21, 1, ,41
0891683108701305f0040BA13178858581F80008504080905461201666534F1F300067094E8B76F8
6C42300056DE75358BDD
+CMGL: 22, 1, ,90
0891683108705505f0040D91683175804276F8000850408011033000464F60660E59297ED9623F4E
1C62534E2A75358BDD300053F778016211665A4E0A544A8BC94F603000621190A353EF4EE54E0A7F
514E8630004ECA592998864E867B148BB0672C
+CMGL: 23, 1, ,66
0891683108705505f0040D91683175804276F80008504080223543002E0031003300350030003700
330031003400320036003253EB52185E086BCD30004F605E2E6211628A94B153E07740
+CMGL: 24, 1, ,52
0891683108705505f0040D91683175804276F8000850408022757100200031003600350030002062
1173B057286CA194B1300089817B4953D15DE58D44
+CMGL: 25, 1, ,38
0891683108705505f0040D91683175804276F8000850408022950400124F6073B057284E0D4F1A99
7F6B7B54273000
+CMGL: 26, 1, ,48
0891683108705505f0040D91683175804276F80008504080322082001C534E4E3A898162DB4E2A51
99006A00610076006176844F6067654E0D
+CMGL: 27, 1, ,44
0891683108200205f0240D91683128500474F7000850409000416200184F60771F5F3A4EE5540E53
EF4E0D65629A9A62704F604E86
+CMGL: 28, 1, ,74
0891683108200205f0240D91683128500474F700085040900081500036621165394E864EE5540E4E
0D4F1A6B3A8D1F60A880014EBA5BB64E86002C4F606B3A8D1F621162114E5F4E0D4F1A62A5602876
84002E
+CMGL: 29, 1, ,82
0891683108200205f0240D91683128500474F70008504090002273003E62116DF14FE15584670955
8462A560766709607662A5002C5BF94E864F607ED9621163024E86591A5C115C0F65F64E864EC04E
4865F650195230592A9633
+CMGL: 30, 1, ,82
0891683108200205f0240D91683128500474F70008504090009222003E62118FD85F975929592963
D091924F60002054CE4F608FD94E2A783481115B5000204F608D767D277ED9621163024E0A8FC751
E05929621168C067E553BB
+CMGL: 31, 1, ,58
0891683108200205f0240D91683128500474F7000850409000535400266211521A6D825B8C630775
326CB97B495E725B8C4E8662115C31776100204F60572873A95565
+CMGL: 32, 1, ,108
0891683108200205f0240D91683128500474F700085040900014410058776189C94E4B524D6D8263
0775326CB95C314F1A505A4E2A597D68A6800C4E1468A690FD4F1A5B9E73B04E0D4FE14F608BD58B
D5002C62114E0D8DDF4F6073A94E86660E59298FD85F9765E98D7751FA53BB73A900380038
+CMGL: 33, 1, ,76
0891683108200205f0240D91683128500474F7000850409000542200385FD84E864F60662F753776
844E864E0D8FC76CA14E8B73B057286D41884C75374EBA6D82630775326CB90020621177414E0D5F
00773C4E86
+CMGL: 34, 1, ,154
0891683108200205f0240D91683128500474F7000850401190207100864E00592954B14FE9676552
304E0053E38BB8613F4E9565C1002C62115F2F4E0B81708BB84E864E2A613F8FD85F804E9591CC62
544E2A786C5E01002E4F604E5F60F38BB8613F4F464F605F2F817065F64E0D5C0F5FC37FFB51654E
9591CC002E621188AB60CA54464E86002C5583558381EA8BED9053003A00208FD8771F7075563F00
200021
+CMGL: 35, 1, ,66
0891683108705505f0040D91683175804276F80008504031418592002E653E4E2A00760073007376
845B8988C565874EF65230670D52A156684E0A97623000628A57305740544A8BC96211
+CMGL: 36, 1, ,42
0891683108200205f0240D91683128500474F70008504031815581001680017CCA6D82795E522B5F
D87ED96211630200510051
+CMGL: 37, 1, ,72
0891683108200205f0240D91683128500474F70008504031819571003454CE54DF4F608FD84E0A8B
FE002C626B76F273ED5427003F770B676562116BCF592965E94E0A90FD5F9763D091924F604E006B
21
+CMGL: 38, 1, ,158
0891683108705505f0040D91683157011065F00008504001227091008A84288FBE59C66D3E624B4E
0B53BB89C25BDF654C60C5002C4E0D4E004F1A513F624B4E0B53065FD956DE6765002C752898DF63
07548C4E2D63074F5C51FA0056578B624B52BF002C84288FBE59C69AD8517476848BF4201C62114E
EC80DC52294E86003F201D624B4E0B8BF4201C522B4ED65988626F4E86002C5C31526954B14EEC4F
E94E863002201D
+CMGL: 40, 1, ,34
0891683108200205f0240D91683128500474F70008504001226243000E84288FBE6BCD662F621190
E84E0B
呵呵有点长了,这是刚刚我从我手机中读取出来的数据,是经过编码以后的,有兴趣的话可以“翻译”出来看看是什么内容:)
关于SMS PDU格式的说明,推荐一个地址:
http://shuixin13.mblogger.cn/posts/10087.aspx
这里的资料已经够全了,基本可以包括所有的操作。
OK,读取手机短信不是我们的主要目的,在这里就不罗索了,只要仔细研究一下SMS PDU格式的那个文档,基本就不会有什么问题,我们的主要目的是发短信,现在就着重讲讲这一部分好了:
发短信的指令格式和编码格式也可以参考上面的地址,里面讲的也很详细了,我也不在这里罗嗦了,现在的关键问题是,如何根据格式来编码和解码。
首先,我们先建立一个Class来保存要发送的数据,每个字段用相应的类型表示,还要有一个“打包”的函数,就是把每一部分的数据组合起来。
class CMsgSend
{
public:
CString GetMsgData();
void Pack(CString c_number,CString s_number,CString msg);
CMsgSend();
virtual ~CMsgSend();
CString m_strData;
CString SCA;
CString PDUType;
CString MR;
CString DA;
CString PID;
CString DCS;
CString VP;
CString UDL;
CString UD;
};
其中m_strData保存“打包”以后的数据,其他各个成员变量的含义请参照文档。
Pack是打包函数,需要三个参数:短信服务中心号码、接收短信手机号码和信息内容。
另外,我们还需要一个工具类来实现编码和解码:
class CMyTools
{
public:
static void HexToChar(CString sHex,char *p);//将十六进制转换为字符数组
static CString DeCodeChinese(CString strSrc);//中文解码
static CString EnCodeChinese(CString strSrc);//中文编码
static CString SwapConvert(CString str);//交换,例如1234567890变换为2143658709,具体什么用看文档
static BYTE HexToChar(CString str);//十六进制转换为字符类型
static CString DeCodeEnglish(CString srcStr);//英文解码
static CString EnCodeEnglish(CString srcStr);//英文编码
};
CString CMyTools::EnCodeEnglish(CString srcStr)
{
CString result;
BYTE cur,c1,c2;
CString tmp;
int len,i=0,j=0;
len = srcStr.GetLength() - 1;
result = "";
while(i <= len)
{
c1 = srcStr.GetAt(i);
if(i < len)
{
c2 = srcStr.GetAt(i+1);
cur = (c1 >> j) | (c2 << (7-j) & 0xff);
}
else
cur = (c1 >> j) & 0x7f;
tmp.Format("%2.2X",cur);
result = result + tmp;
i++;
j = (j+1) % 7;
if(j == 0)
i++;
}
return result;
}
CString CMyTools::DeCodeEnglish(CString srcStr)
{
CString strDest,strData;
int n = 0,i,flag = 0,j = 0;
strData = "";
int len = srcStr.GetLength();
for(i=0;i<len-1;i+=2)
{
CString strTmp;
char tmp;
strTmp.Format("0x%1c%1c",srcStr.GetAt(i),srcStr.GetAt(i+1));
tmp = HexToChar((LPSTR)(LPCTSTR)strTmp);
strData = strData + tmp;
}
len = len/2 + len/2/8;
for(i = 0;i<len;i++)
{
strDest = strDest + " ";
}
for(i=0;i<len;i++)
{
BYTE c1,c2;
if(i == 0)
{
c1 = strData.GetAt(i);
strDest.SetAt(i,c1 & 0x7f);
}
else
{
c1 = strData.GetAt(j);
c2 = strData.GetAt(j+1);
strDest.SetAt(i,(c2 << n) | (c1 >> (8 - n)));
strDest.SetAt(i,strDest.GetAt(i) & 0x7f);
if(i%8 != 0)
j++;
}
n = (i % 8) + 1;
}
return strDest;
}
BYTE CMyTools::HexToChar(CString hex)
{
int base = 1;
int ret = 0;
for(int i=hex.GetLength()-1;i>=0;i--)
{
char chex = hex.GetAt(i);
int ihex;
if(chex >= 'A' && chex <='F')
{
ihex = 15 - ('F' - chex);
}
else
if(chex >= 'a' && chex <='f')
{
ihex = 15 - ('f' - chex);
}
else
ihex = chex - '0';
ret += ihex * base;
base*=16;
}
return ret;
}
CString CMyTools::SwapConvert(CString str)
{
CString result;
result = str;
for(int i=0;i<strlen(str);i+=2)
{
result.SetAt(i,str.GetAt(i+1));
result.SetAt(i+1,str.GetAt(i));
}
return result;
}
CString CMyTools::EnCodeChinese(CString strSrc)
{
CString strResult = "",strTmp,str;
char lpBuff;
int len = strSrc.GetLength();
int i;
WCHAR * wc;
wc = new WCHAR[len];
for(i=0;i<strSrc.GetLength();i++)
{
if((strSrc.GetAt(i) & 0x80) >> 7 == 0)
len++;
}
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,(LPSTR)(LPCTSTR)strSrc,len,wc,len/2);
for(i=0;i<len/2;i++)
{
strTmp.Format("%4.4X",wc[i]);
strResult += strTmp;
}
return strResult;
}
CString CMyTools::DeCodeChinese(CString strSrc)
{
char *pBuf;
CString strMsg = strSrc;
int nLength = strMsg.GetLength();
if (nLength%2 == 1)
{
strMsg = strMsg.Left(nLength-1);
int nNewLen = strMsg.GetLength();
pBuf = new char[nNewLen/2];
}
else
{
pBuf = new char[nLength/2];
}
HexToChar(strMsg,pBuf);
int i = 0,nZero = 0;
while ((i = strMsg.Find("00",i))>=0)
{
i += 2;
nZero++;
}
char u_ret[255];
memset(u_ret,0,255);
int nResult=WideCharToMultiByte(
CP_ACP, // code page
WC_COMPOSITECHECK, // character-type options
(LPCWSTR)pBuf, // string to map
nLength/4, //str.GetLength(), // number of bytes in string
(LPSTR)u_ret, // wide-character buffer
sizeof(u_ret), // size of buffer
NULL,
NULL
);

CString sMessage;
sMessage.Format("%s",u_ret);
return sMessage;
}
void CMyTools::HexToChar(CString sHex, char *p)
{
unsigned char byteToHex[] =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
int nLen = sHex.GetLength();
char *chBuf = p,//记录内存块的首地址
*pch;
CString sTemp,sLeft,sRight;
for (int i=0; i<nLen/4; i++)
{
sTemp = sHex.Left(4);
sHex.Delete(0,4);
sLeft = sTemp.Left(2);
sRight = sTemp.Right(2);
*chBuf = (char)strtoul(sRight.GetBuffer(2),&pch,16);
chBuf++;
sRight.ReleaseBuffer();
*chBuf = (char)strtoul(sLeft.GetBuffer(2),&pch,16);
chBuf++;
sLeft.ReleaseBuffer();
}
*chBuf='/0';
}
编码解码的工具都全了,现在来看“打包”函数:
void CMsgSend::Pack(CString c_number,CString s_number,CString msg)
{
int len;

SCA= "00";
//PDUTtpe
PDUType = "31";
//MR
MR = "00";
//DA
s_number = s_number + "F";
len = s_number.GetLength();
DA.Format("%2.2X81",len-1);
DA = DA + CMyTools::SwapConvert(s_number);
//PID
PID = "00";
//DCS
DCS = "08";
//VP
VP = "A7";
//UD
UD = CMyTools::EnCodeChinese(msg);
//UDL
UDL.Format("%2.2X",UD.GetLength()/2);

m_strData = SCA + PDUType + MR + DA + PID + DCS + VP + UDL + UD;
}
例如我想给13875998800发送一条内容是hello的信息,短信中心号码为8613800731500,我们可以这样调用:
msg.Pack("8613800731500","13875998800","hello");
sendMsg = msg.GetMsgData();
m.Format("AT+CMGS=%d/r/n",(sendMsg.GetLength()-msg.SCA.GetLength())/2);
SendData((LPSTR)(LPCTSTR)m,m.GetLength());
m.Format("%s%c",sendMsg,26);
SendData((LPSTR)(LPCTSTR)m,m.GetLength());
具体的编码过程上面文档里面说的已经够详细了,也不在这里多说。
这里由于篇幅原因省略了很多东西,反正原理就是这些,核心代码也就是上面的一些编码解码的东西了,有些代码我也是从网上找到然后修改了一下来用的。
其实用AT指令还可以干很多事情,甚至拨打电话之类的都没问题,拨打电话的AT指令很简单:
ATD13875998800,只要发送这个指令过去,手机就会拨打13875998800这个号码。不过经过实践,发现被叫的手机无法正常的接听,提示要与电脑设备连接才可以接听,具体如何实现就没研究过了.....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: