1 、Windows API通信函数方法 。与通信有关的Windows API函数共有26个,但主要有关的有: CreateFile() 用 “comn”(n为串口号)作为文件名就可以打开串口。 ReadFile() 读串口。
2、WriteFile() 写串口。 CloseHandle() 关闭串口句柄。初始化时应注意CreateFile()函数中串口共享方式应设为0,串口为不可共享设备,其它与一般文件读写类似。以下给出API实现的源代码。
3、利用端口函数直接 *** 作 。这种方式主要是采用两个端口函数_inp(), _outp()实现对串口的读写,其中读端口函数的原型为: int _inp(unsigned shot port) 。该族坦巧函数从端口读取一个字节,端口号为0~65535。 写端口的函数原型为: nt _outp(unsigned shot port, int databyte) 。
4、 MSComm控件 。MSComm控件是微软开发的专用通信控件,封装了串口的所有功能,使用很方便,但在实际应用中要小心对其属性进行配置。下面详细说明该类应用方法。
串行端口的本质功能是作兆键为CPU和串行设备间的编码转换器。当数据从信则 CPU经过串行端口发送出去时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。
在Windows环境(Windows NT、Win98、Windows2000)下,串口是系统资源的一部分。
应用程序要使用串口进行通信,必须在使用之前向 *** 作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。
通过你的问题,我感觉,你想要一种安全的数据接收方式,那么你需要使用同步方式,同步方式是一种阻塞方式的数据传输,这样你可以安全的获的所有数据。1.对于问题1,你的问题2既是答案,使用ClearCommError函数,第三个参族陪数.cbInQue可获得缓冲区中未读的数量。
2.从物理上,每次字节到来都会触发EV_RXCHAR,但是毕竟标志位只有1个,当多个字节快速到来时,标志位被重复写入,这种情况下,EV_RXCHAR的触发次数与接收到的字节数是不同的。如果对方的传输速度慢(频度),可以通过ClearCommError这个函数获得缓冲区中有多少个数据没有读出,按照这个数将其一次读出。如果频度比较高,只能使用一个监控线程不断的从缓冲区中读出,直到没有数据为止。
3.这个就是同步和异步的问题了,如果用同步方式,对方传1个,你不接收他是不会传第二个的,但异步方式,不同,不论对方是否接收,数据都会被传输,使用何种方式,看你项目的应用而定。
4.起始位、停止位、校验位,是根据你设定的通信格式,协议芯片帮你加入的,如果你使用标准的串口协议接收的,在你接收到数据时,这些标志都会被清除掉的,即数据在接受方,软件方面是透明的,但这些标志在线上是存在,使用示波器,可以明显的看到。
5.一般地,使用软件协议,即在开始处加上同步头、传输量等,接收方在检测到同步头后开始接收有用数据。
6.补充一下,如果你需要握手,还需要设定EV_CTS、EV_CTS等,这些标志是专门用来控制数据传输是否开始的标志,当然,这也将是硬线增加,这得视你的接口情况来决定是否能使用。
----不知道回兆塌蠢答明白没,如需要更详细的,请QQ me[19226004],注明串口问题,我做过很多串口方面的项目,可衫芦以交流一下。
1、新建MFC对话框工程如下
2、给编辑框控件添加变量,其中Edit Box添加Value变量,Button添加Control变量,ID和变量分别为:
IDC_BTNOPEN() 数橘源 伍链 CButton m_cBtnOpen
IDC_BTNSEND() CButton m_cBtnSend
IDC_EDIT_RXDATA() CString m_sRXDATA
IDC_EDIT_TXDATA() CString m_sTXDATA
3、右击插入Active X控件:
右击电话图标选择“Class Wirzard”,添加变量m_comm1,添加Function:
双击两个薯态Button按钮;
代码中显示如下:
[cpp] view plain copy print?
void CMSCommTestDlg::OnBnClickedBtnopen()
{
// TODO: Add your control notification handler code here
}
void CMSCommTestDlg::OnBnClickedBtnsend()
{
// TODO: Add your control notification handler code here
}
void CMSCommTestDlg::OnOncommMscomm1()
{
// TODO: Add your message handler code here
}
void CMSCommTestDlg::OnBnClickedBtnopen(){
// TODO: Add your control notification handler code here
}
void CMSCommTestDlg::OnBnClickedBtnsend()
{
// TODO: Add your control notification handler code here
}
void CMSCommTestDlg::OnOncommMscomm1()
{
// TODO: Add your message handler code here
}
5、将上面代码补全如下:
[cpp] view plain copy print?
void CMSCommTestDlg::OnClickedBtnopen()
{
// TODO: Add your control notification handler code here
//如果端口已经开启,那么先关闭
if (m_comm1.get_PortOpen())
{
m_comm1.put_PortOpen(FALSE)
}
m_comm1.put_CommPort(3) //选择com3,可以根据具体情况更改
m_comm1.put_InBufferSize(1024) //设置输入缓冲区的大小,Bytes
m_comm1.put_OutBufferSize(1024) //设置输出缓冲区的大小,Bytes
m_comm1.put_Settings(_T("9600,n,8,1")) //波特率9600,无校验,8个数据位,停止位1
m_comm1.put_InputMode(1) //1:表示以二进制方式检索数据
m_comm1.put_RThreshold(1) //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
m_comm1.put_InputLen(0) //设置当前接收区长度是0
if (!m_comm1.get_PortOpen())
{
m_comm1.put_PortOpen(TRUE)
}
else
{
AfxMessageBox(_T("Can not open serial port!"))
}
m_comm1.get_Input() //先预读缓冲区以清除残留数据
UpdateData(FALSE)
}
void CMSCommTestDlg::OnClickedBtnsend()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE)
m_comm1.put_Output(COleVariant(m_sTXDATA))//发送数据
}
void CMSCommTestDlg::OnOncommMscomm1()
{
// TODO: Add your message handler code here
VARIANT variant_inp
COleSafeArray safearray_inp
LONG len, k
BYTE rxdata[2048]
CString strtemp
if (m_comm1.get_CommEvent() == 2) //事件值为2表示缓冲区内有字符
{
variant_inp = m_comm1.get_Input() //读缓冲区
safearray_inp = variant_inp //VARIANT型变量转换为ColeSafeArray型变量
len = safearray_inp.GetDim() //得到有效数据长度
for (k = 0 k < len k++)
{
safearray_inp.GetElement(&k, rxdata + k)//转换为BYTE型数组
}
for (k = 0 k < len k++) //将数组转换为CString型变量
{
BYTE bt = *(char*)(rxdata + k) //字符型
strtemp.Format(_T("%c"), bt) //将字符送入临时变量strtemp存放
m_sRXDATA += strtemp //接收到的数据放到编辑框对应的变量中
}
}
SetDlgItemText(IDC_EDIT_RXDATA, m_sRXDATA)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)