串口接手机编程,单步正常,直接运行读不出东西。 串口接手机,用CreateFile打开串口,WriteFile写数据,ReadFile读数据。打开串口后,用WriteFile写入“AT”,然后用ReadFile读数据。结果如果单步执行,ReadFile可以读出数据,如果直接运行,则读不出数据。请问是什么原因造成这种现象?在网上好像也见别人说过这个问题,但没找到产生这种现象的原因。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 问题原因有以下几种可能:1.你的串口程序可能不是全双工、半双工的、是单工的,双向对流同步写会有一方数据阻塞,单步调试时人的操作时间长,通信不会出现阻塞现象的2.CreatFile打开串口后,你初始化的串口缓冲是多少?nWriteBuffer?一般AT命令都很短的,你可以开512字节缓冲就够了3.串口通信最好不要让手机开机状态,因为AT命令容易打断你做好的消息封装,当手机开机初始化的时候,会发一些bind:+7等AT命令,理论上不会和你的协议产生冲突的,但是实际当中总是会打断你的通信的4.你可以抓TRACE监控手机端具体接受到什么消息 另外,忘了说一点,接GPRS猫是正常的,接手机就不正常了。 如何确认程序是是全双工、半双工的、或单工?我是以读写方式打开COM口的。 打开串口后,用WriteFile写入“AT”,然后用ReadFile读数据。结果如果单步执行,ReadFile可以读出数据,如果直接运行,则读不出数据。--你的写法有问题,直接写两个字节的"AT"是不行的,得加上回车:"at\r";至于单步执行可以,估计你打开了Modem的字符回显功能,用这个命令可以打开会关闭回显:关闭:ate0\r打开:ate1\r TO: zhangnanonnet(鱼欢)我也考虑过这个问题,但我在读写中间加上Sleep,从100ms到数数秒,都没有效果。 我没有清空缓冲区呀,我的相关代码如下,大家帮我看看,另外,要说明的是,接GPRS MODEM时没有问题,接西门子3508就不行,它们的波特率分别为115200和19200。打开端口:BOOL OpenComm(HANDLE& hComm,const char* pPort , int nBaudRate , int nParity , int nByteSize , int nStopBits){ if(hComm != INVALID_HANDLE_VALUE) return FALSE; DCB dcb; // 串口控制块 COMMTIMEOUTS timeouts = { // 串口超时控制参数 100, // 读字符间隔超时时间: 100 ms 1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms) 500, // 基本的(额外的)读超时时间: 500 ms 1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms) 100}; // 基本的(额外的)写超时时间: 100 ms hComm = CreateFile(pPort, // 串口名称或设备路径 GENERIC_READ | GENERIC_WRITE, // 读写方式 0, // 共享方式:独占 NULL, // 默认的安全描述符 OPEN_EXISTING, // 创建方式 0, // 不需设置文件属性 NULL); // 不需参照模板文件 if(hComm == INVALID_HANDLE_VALUE) return FALSE; // 打开串口失败 GetCommState(hComm, &dcb); // 取DCB dcb.BaudRate = nBaudRate; dcb.ByteSize = nByteSize; dcb.Parity = nParity; dcb.StopBits = nStopBits; SetCommState(hComm, &dcb); // 设置DCB SetupComm(hComm, 4096, 1024); // 设置输入输出缓冲区大小 SetCommTimeouts(hComm, &timeouts); // 设置超时 return CheckCom(hComm);}写:void WriteComm(HANDLE hComm,void* pData , int nLength){ DWORD dwNumWrite; // 串口发出的数据长度 WriteFile(hComm, pData, (DWORD)nLength, &dwNumWrite, NULL);}读:int ReadComm(HANDLE hComm, void* pData, int nLength){ DWORD dwNumRead; // 串口收到的数据长度 ReadFile(hComm, pData, (DWORD)nLength, &dwNumRead, NULL); return (int)dwNumRead;}产生问题的地方:BOOL CheckCom(HANDLE hComm){ int nLength; // 串口收到的数据长度 char cmd[16]; // 命令串 char ans[4096]; // 应答串 char ansTmp[128]; //应答临时串 memset(cmd, 0, sizeof(cmd)); sprintf(cmd, "AT\r"); // 生成命令 /* 此行之前设定断点,开始单步执行就不会有问题 */ WriteComm(hComm, cmd, strlen(cmd)); // 先输出命令串 memset(ans, 0, sizeof(ans)); do { memset(ansTmp, 0, sizeof(ansTmp)); nLength = ReadComm(hComm, ansTmp, sizeof(ansTmp) - 1); if(nLength > 0) { strcat(ans, ansTmp); } }while(nLength > 0); if(strlen(ans) > 0 && strstr(ans, "OK") != NULL) { return TRUE; } else { return FALSE; }} 在读数据之前,最好先判断是否有数据可读。下面给出我的代码供参考:int TagBaseComm::recTest(void){ ClearCommError(hCom, &lComStat, &comStat); return((int)comStat.cbInQue);}... int num = pCom->recTest(); if( num>0 ){ // 如果有数据 pCom->Read(); ... 也可以下载我的DLL试试:http://www.bluespace.com.cn/koodoo/examples_sms.htm 谢谢楼上,你的DLL的头文件好像不是VC的吧? 波特率19200的时候出了问题,那说明你需要调整DCB的设计,我建议你调整一下SetCommTimeouts(hComm, &timeouts);中timeouts的设置,有这么一种可能,因为通讯输率比较慢,你READ等待超时已经过去,数据还没有写入BUF,你把READ超时设大一些,还有就是你为什么不把不特率调上去呢?手机的AT指令都有一条是调整波特率的,你把波特率调上去,然后shut down掉串口从新用新的波特率打开就可以了 肯定可以设定的,一般初始BUADRATE是19200,然后能网上调一直调到115200,这个波特率是通过master->slaver协商解决的,也就是我说的用修改波特率的指令完成。你最好查查你用的那款MODULE的AT指令集 19200波特率时我接的是西门子M35i,在超级终端上测试指令AT+IPR?或AT+IPR=?返回ERROR。 那说明M35I并不支持AT+IPR的指令,你应该找找M35I的指令集。看看它协商波特率是什么命令 Xpath问题,求助 CPtrArray类排序问题? 为什么我的程序脱离了VC开发环境就不能正常运行??? 给定路径名,如何判断该路径存不存在? 从MP3文件格式到WAV文件格式 Help!Help! 我想学习vc,原来没用过,没有基础,请大家帮我指条路!谢谢了,up有分 寻找失去的风格菜单的图标! 鼠标靠近ListControl中的随便那一项,鼠标形状发生改变! 在数据库中,设置了主键是不是表示已经是索引了? 在vc里,一个对话框中弹出新的对话框时,如何让原先的对话框保持“可用状态”? 怎么用C语言读写一张图片?
2.CreatFile打开串口后,你初始化的串口缓冲是多少?nWriteBuffer?一般AT命令都很短的,你可以开512字节缓冲就够了
3.串口通信最好不要让手机开机状态,因为AT命令容易打断你做好的消息封装,当手机开机初始化的时候,会发一些bind:+7等AT命令,理论上不会和你的协议产生冲突的,但是实际当中总是会打断你的通信的
4.你可以抓TRACE监控手机端具体接受到什么消息
至于单步执行可以,估计你打开了Modem的字符回显功能,用这个命令可以打开会关闭回显:
关闭:ate0\r
打开:ate1\r
BOOL OpenComm(HANDLE& hComm,const char* pPort , int nBaudRate , int nParity , int nByteSize , int nStopBits)
{
if(hComm != INVALID_HANDLE_VALUE)
return FALSE; DCB dcb; // 串口控制块
COMMTIMEOUTS timeouts = { // 串口超时控制参数
100, // 读字符间隔超时时间: 100 ms
1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
500, // 基本的(额外的)读超时时间: 500 ms
1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
100}; // 基本的(额外的)写超时时间: 100 ms
hComm = CreateFile(pPort, // 串口名称或设备路径
GENERIC_READ | GENERIC_WRITE, // 读写方式
0, // 共享方式:独占
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if(hComm == INVALID_HANDLE_VALUE) return FALSE; // 打开串口失败
GetCommState(hComm, &dcb); // 取DCB
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nByteSize;
dcb.Parity = nParity;
dcb.StopBits = nStopBits;
SetCommState(hComm, &dcb); // 设置DCB
SetupComm(hComm, 4096, 1024); // 设置输入输出缓冲区大小
SetCommTimeouts(hComm, &timeouts); // 设置超时
return CheckCom(hComm);}写:
void WriteComm(HANDLE hComm,void* pData , int nLength)
{
DWORD dwNumWrite; // 串口发出的数据长度
WriteFile(hComm, pData, (DWORD)nLength, &dwNumWrite, NULL);
}读:
int ReadComm(HANDLE hComm, void* pData, int nLength)
{
DWORD dwNumRead; // 串口收到的数据长度
ReadFile(hComm, pData, (DWORD)nLength, &dwNumRead, NULL);
return (int)dwNumRead;}产生问题的地方:
BOOL CheckCom(HANDLE hComm)
{
int nLength; // 串口收到的数据长度
char cmd[16]; // 命令串
char ans[4096]; // 应答串
char ansTmp[128]; //应答临时串 memset(cmd, 0, sizeof(cmd));
sprintf(cmd, "AT\r"); // 生成命令
/* 此行之前设定断点,开始单步执行就不会有问题 */
WriteComm(hComm, cmd, strlen(cmd)); // 先输出命令串 memset(ans, 0, sizeof(ans));
do
{
memset(ansTmp, 0, sizeof(ansTmp));
nLength = ReadComm(hComm, ansTmp, sizeof(ansTmp) - 1); if(nLength > 0)
{
strcat(ans, ansTmp);
}
}while(nLength > 0);
if(strlen(ans) > 0 && strstr(ans, "OK") != NULL)
{
return TRUE;
}
else
{
return FALSE;
}
}
int TagBaseComm::recTest(void)
{
ClearCommError(hCom, &lComStat, &comStat);
return((int)comStat.cbInQue);
}...
int num = pCom->recTest();
if( num>0 ){ // 如果有数据
pCom->Read();
...
http://www.bluespace.com.cn/koodoo/examples_sms.htm