Gilbert在串口通信中使用CSerialPort时,发现连续发送有问题,比如,发送一个10字节长的数据,每次发送一个字节:
char OnebyteSend[10]={1,2,3,4,5,6,7,8,9,a};
for(int i=0;i<10;i++)
{
CString sendBuff;
sendBuff.Format("%s",OnebyteSend[i]);
m_SerialPort.WriteToPort((LPCTSTR)sendBuff,1); //通过串口发送验证码
memset(OnebyteSend,0,sizeof(OnebyteSend));
}
发送的结果显示1和a,开始以为这个类不能连续发送数据,但是后来发现如果写成这个样子:
for(int i=0;i<10;i++)
{
CString sendBuff;
AfxMessageBox("");
sendBuff.Format("%s",OnebyteSend[i]);
m_SerialPort.WriteToPort((LPCTSTR)sendBuff,1); //通过串口发送验证码
memset(OnebyteSend,0,sizeof(OnebyteSend));
}这样数据就都能发出去,这是为什么呢?
如果说用Sleep函数没有用,做过测试了的!一下是从网上找到了问题,但是还没有解决。希望哪位高手帮忙解答下。兄弟我不胜感激!=========================================
这个要看CSerialPort是怎么做出来的,也就是从Windows的串口编程说起。在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但是控件只能在对话框中使用。其二是调用Windows的API函数,这种方法可以清楚地掌握串口通信的机制,并且自由灵活。CSerialPort类就是对串口的API函数封装。与以往DOS下串行通信程序不同的是,Windows不提倡应用程序直接控制硬件,而是通过Windows操作系统提供的设备驱动程序来进行数据传递。串行口在Win 32中是作为文件来进行处理的,而不是直接对端口进行操作,对于串行通信,Win 32 提供了相应的文件I/O函数与通信函数,通过了解这些函数的使用,可以编制出符合不同需要的通信程序。由于是作为文件来处理,我们看看windows API中打开串口的函数:
HANDLE CreateFile( LPCTSTR lpFileName, //将要打开的串口逻辑名,如“COM1”;
DWORD dwDesiredAccess, //指定串口访问的类型,可以是读取、写入或二者并列;
DWORD dwShareMode, //指定共享属性,由于串口不能共享,该参数必须置为0;
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //引用安全性属性结构,缺省值为NULL;
DWORD dwCreationDistribution, //创建标志,对串口操作该参数必须置为OPEN_EXISTING;
DWORD dwFlagsAndAttributes, //属性描述,用于指定该串口进行异步或同步操作;
HANDLE hTemplateFile); //对串口而言该参数必须置为NULL;=========================================
请务必注意倒数第二个参数dwFlagsAndAttributes,它指示了串口进行异步或同步操作。还请注意这里的同步和异步不是指的数据通信里时钟的同步和异步。这里的同步和异步指的是:同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而异步(重叠)操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。dwFlagsAndAttributes该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作。既然CSerialPort类是对API函数的封装,我们有理由相信在它的实现里面必定有CreateFile函数,打开它的cpp来看,果然可以搜索的到,再看看它是怎么设置的:m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到倒数第二个参数设为FILE_FLAG_OVERLAPPED,即异步发送。=========================================
其实问题就在这里,异步发送的话就造成文章一开始说的两个现象。先说第一个现象:为什么三个数组中只发送了最后一个数组?
因为采用了异步操作,在执行到m_serial.WriteToPort(chSend1); 时,并不马上发送串口数据,而是要等进入CSerialPort的线程之后再发送(如果是同步操作,则程序停在那里等发送完成)。
你可以跟踪一下程序,看是什么时候进入它的线程的,三句WriteToPort都会进入这一个线程,而不是三个线程,在这个线程中只发送一次数据,数据的来源就是形参最后的更新,所以就是第三个数组了。第二个现象:为什么加了AfxMessageBox(""); 就都可以发送?
因为AfxMessageBox(""); 使程序的进程被挂起,这样CSerialPort的线程就得以运行,所以就发送了。=========================================
看到这里你可能会想:那能不能将dwFlagsAndAttributes改成0设为同步发送?
答案是好像不可以,可能还需要改其他地方,光这里改成同步的话,串口什么数据也发不了。
如果你发现能简易的将这个类改成同步的方法,欢迎联系我[email protected]
char OnebyteSend[10]={1,2,3,4,5,6,7,8,9,a};
for(int i=0;i<10;i++)
{
CString sendBuff;
sendBuff.Format("%s",OnebyteSend[i]);
m_SerialPort.WriteToPort((LPCTSTR)sendBuff,1); //通过串口发送验证码
memset(OnebyteSend,0,sizeof(OnebyteSend));
}
发送的结果显示1和a,开始以为这个类不能连续发送数据,但是后来发现如果写成这个样子:
for(int i=0;i<10;i++)
{
CString sendBuff;
AfxMessageBox("");
sendBuff.Format("%s",OnebyteSend[i]);
m_SerialPort.WriteToPort((LPCTSTR)sendBuff,1); //通过串口发送验证码
memset(OnebyteSend,0,sizeof(OnebyteSend));
}这样数据就都能发出去,这是为什么呢?
如果说用Sleep函数没有用,做过测试了的!一下是从网上找到了问题,但是还没有解决。希望哪位高手帮忙解答下。兄弟我不胜感激!=========================================
这个要看CSerialPort是怎么做出来的,也就是从Windows的串口编程说起。在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但是控件只能在对话框中使用。其二是调用Windows的API函数,这种方法可以清楚地掌握串口通信的机制,并且自由灵活。CSerialPort类就是对串口的API函数封装。与以往DOS下串行通信程序不同的是,Windows不提倡应用程序直接控制硬件,而是通过Windows操作系统提供的设备驱动程序来进行数据传递。串行口在Win 32中是作为文件来进行处理的,而不是直接对端口进行操作,对于串行通信,Win 32 提供了相应的文件I/O函数与通信函数,通过了解这些函数的使用,可以编制出符合不同需要的通信程序。由于是作为文件来处理,我们看看windows API中打开串口的函数:
HANDLE CreateFile( LPCTSTR lpFileName, //将要打开的串口逻辑名,如“COM1”;
DWORD dwDesiredAccess, //指定串口访问的类型,可以是读取、写入或二者并列;
DWORD dwShareMode, //指定共享属性,由于串口不能共享,该参数必须置为0;
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //引用安全性属性结构,缺省值为NULL;
DWORD dwCreationDistribution, //创建标志,对串口操作该参数必须置为OPEN_EXISTING;
DWORD dwFlagsAndAttributes, //属性描述,用于指定该串口进行异步或同步操作;
HANDLE hTemplateFile); //对串口而言该参数必须置为NULL;=========================================
请务必注意倒数第二个参数dwFlagsAndAttributes,它指示了串口进行异步或同步操作。还请注意这里的同步和异步不是指的数据通信里时钟的同步和异步。这里的同步和异步指的是:同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而异步(重叠)操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。dwFlagsAndAttributes该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作。既然CSerialPort类是对API函数的封装,我们有理由相信在它的实现里面必定有CreateFile函数,打开它的cpp来看,果然可以搜索的到,再看看它是怎么设置的:m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到倒数第二个参数设为FILE_FLAG_OVERLAPPED,即异步发送。=========================================
其实问题就在这里,异步发送的话就造成文章一开始说的两个现象。先说第一个现象:为什么三个数组中只发送了最后一个数组?
因为采用了异步操作,在执行到m_serial.WriteToPort(chSend1); 时,并不马上发送串口数据,而是要等进入CSerialPort的线程之后再发送(如果是同步操作,则程序停在那里等发送完成)。
你可以跟踪一下程序,看是什么时候进入它的线程的,三句WriteToPort都会进入这一个线程,而不是三个线程,在这个线程中只发送一次数据,数据的来源就是形参最后的更新,所以就是第三个数组了。第二个现象:为什么加了AfxMessageBox(""); 就都可以发送?
因为AfxMessageBox(""); 使程序的进程被挂起,这样CSerialPort的线程就得以运行,所以就发送了。=========================================
看到这里你可能会想:那能不能将dwFlagsAndAttributes改成0设为同步发送?
答案是好像不可以,可能还需要改其他地方,光这里改成同步的话,串口什么数据也发不了。
如果你发现能简易的将这个类改成同步的方法,欢迎联系我[email protected]
解决方案 »
- HOOK 模拟魔兽争霸3 虚拟局域网的问题(修改HOOK到的函数)高手求救啊
- vs2008程序打包,提示“存储空间不足”,急!!!
- InstallShield问题,如何在Uninstall时卸载之前安装的DLL?解决马上给分!!
- 请问 Visual C++ 6.0 界面 本身的窗口分割以及视图分配大体上是怎么一回事啊.
- 如何通过AT命令来操作MODEM;
- 为何打印出来的是乱码?
- 急!----视图类的构造函数的调用问题
- 请问: 谁有SDK 的最简单的服务程序代码, 给我一个. 立马 200 分送上
- 谁用过Code Jockey扩展类库,怎么创建docking windows?
- CTime类,怎么用?
- 窗口过程函数内部使用switch/case语句
- 线程非返回暂停或摧毁。结果卡死机了
相当于你延时了,所以发送没有问题
// 懒得去下CSerialPort看
{
assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
strcpy(m_szWriteBuffer, string);
m_nWriteSize=strlen(string); // set event for write
SetEvent(m_hWriteEvent);
}
SetEvent(m_hWriteEvent);// 每发送一次需要等待串口缓冲区空的消息
// 可以把这个去掉,然后在发送10次后,SetEvent()一次。
// 或者你一次发送10个。