天津网站建设制作品牌公司,网站源码下载网站,举重运动员 做网站,宁波seo外包平台1、串口通信的概述#xff1a;
串口是一种重要的通信资源#xff0c;例如鼠标口、USB接口都是串口。串行端口是CPU和串行设备间的编码转换器。当数据从CPU经过端口发送出去的时候#xff0c;字节数据会被转为串行的位#xff0c;在接收数据时#xff0c;串行的位被转换为…1、串口通信的概述
串口是一种重要的通信资源例如鼠标口、USB接口都是串口。串行端口是CPU和串行设备间的编码转换器。当数据从CPU经过端口发送出去的时候字节数据会被转为串行的位在接收数据时串行的位被转换为字节数据。
1、串口通信的特点
数据通信多采用串口技术主要因为串口可以在现有的电话网络上进行数据传输。串口通信是按照数据一位一位的依次传输所以一根传输线就可以完成数据交换降低了通信成本。
2、串口通信的传输方式
串口通信按照数据流可以分为三种传输方式单工通信、半双工通信、全双工通信。
单工通信使用一根导线数据只能从A发送到B
半双工通信是用一根导线数据可以从A发送到B也可以从B发送到A。但是不能同时进行
全双工通信俩根导线。允许通信双方在俩个方向同时进行数据传输。
3、通信方式
同步通信接收方不必对每个字节进行起始和停止的操作传输效率高。传输设备复杂双方时钟允许误差小。可用于点对点之间的数据传输。
异步通信以字符为单位进行数据传输并且每个字符都有起始位和停止位的标记。允许各个字符之间有间隙俩个字符之间的间隔不固定。异步通信的传输效率低传输设备简单并且只适用于点对点的数据传输。
2、利用Mscomm进行串口通信
1、字符格式收发
1、初始化框架的ICON和发送EDIT的文本 初始化框架上的内容应该位于框架类的构造函数中 CComDlg::CComDlg(CWnd* pParent /*NULL*/) 初始化ICONm_hIcon AfxGetApp()-LoadIcon(IDI_ICON_EARTH); // 图标改成地球 初始化发送EIDT的文本 m_strSend My first SerialPortTool!; 2、初始化下拉列表
初始化下拉列表位于入口函数中
入口函数 CComDlg::OnInitDialog 初始化串口号波特率校验位数据位停止位 m_cboPort.SetCurSel(0); m_cboBaudRate.SetCurSel(4); m_cboCheck.SetCurSel(0); m_cboDataBit.SetCurSel(3); m_cboStopBit.SetCurSel(0); 3、获取我们界面中的设置到CMscomm类中的对象中
UI的串口设置中的打开按钮添加打开按钮事件。 UpdateData(TRUE); //将控件中的内容同步到变量中我们操作控件就相当于操作变量。 CString strOpen;//strOpen来获得按钮上面的文字内容。 GetDlgItemText(IDC_BUTTON_OPEN, strOpen); if(strOpen 打开) { //1、执行打开串口操作 m_mscomm.put_InBufferSize(1024); //接收缓冲区 m_mscomm.put_OutBufferSize(1024);//发送缓冲区 m_mscomm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取 m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//以二进制方式读写数据 m_mscomm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时将引发接收数据的OnComm事件 //2、获取我们界面中的设置到CMscomm类中的对象中 //校验位,犹豫我们拼接字符串但是校验位比较特殊很多设备没有校验位所以我们不能直接使用value类型变量 CString strCheck getCheck(); CString strSettings m_strBaudRate strCheck m_strDataBit m_strStopBit; //MessageBox(strSettings); //9600,n,8,1 和 9600n81 均对 //m_mscomm.put_Settings(_T(9600,n,8,1));//波特率9600无检验位8个数据位1个停止位 m_mscomm.put_Settings(strSettings); //端口号 //put_CommPort参数直接代表串口号为1m_cboPort.GetCurSel() 1目的增加了复用性。 m_mscomm.put_CommPort(m_cboPort.GetCurSel() 1);//索引从0开始 getCheck()获取当前的校验位
//步骤2、获取校验位
CString CComDlg::getCheck(void)
{CString strCheck;switch(m_cboCheck.GetCurSel()){case 0: strCheck n; break;//无校验case 1: strCheck o; break;//基校验case 2: strCheck e; break;//偶校验case 3: strCheck m; break;case 4:strCheck s; break;default:break;}return strCheck;
} 4、真正打开串口的操作
我们点击打开串口的时候调用put_PortOpen打开串口并且要做一个异常捕获。
打击打开串口的操作我们的打开按钮得更换文本内容为关闭
同时有一个bmp的资源图片也会随着串口的打开和关闭改变图片 try { m_mscomm.put_PortOpen(TRUE);//put_PortOpen(TRUE)参数为TRUE则打开串口为FALSE则关闭串口 } catch (CException* e) { MessageBox(端口不存在, 打开串口, MB_ICONERROR); return; } SetDlgItemText(IDC_BUTTON_OPEN, _T(关闭)); //串口打开之后设置按钮为“关闭” CBitmap bitmap; // CBitmap对象用于加载位图 HBITMAP hBmp; // 保存CBitmap加载的位图的句柄 bitmap.LoadBitmap(IDB_BITMAP_GREEN); // 将位图IDB_BITMAP1加载到bitmap hBmp (HBITMAP)bitmap.GetSafeHandle(); // 获取bitmap加载位图的句柄 m_picIndicator.SetBitmap(hBmp); // 设置图片控件m_picIndicator的位图图片为IDB_BITMAP_RED } else // 4、此时串口已经处于打开状态 执行关闭串口 { m_mscomm.put_PortOpen(FALSE);//put_PortOpen(TRUE)参数为TRUE则打开串口为FALSE则关闭串口 SetDlgItemText(IDC_BUTTON_OPEN, _T(打开)); //串口打开之后设置按钮为“关闭” CBitmap bitmap; // CBitmap对象用于加载位图 HBITMAP hBmp; // 保存CBitmap加载的位图的句柄 bitmap.LoadBitmap(IDB_BITMAP_RED); // 将位图IDB_BITMAP1加载到bitmap hBmp (HBITMAP)bitmap.GetSafeHandle(); // 获取bitmap加载位图的句柄 m_picIndicator.SetBitmap(hBmp); // 设置图片控件m_picIndicator的位图图片为IDB_BITMAP_RED } 5、发送2进制或者16进制数据
首先当我们点击发送按钮的时候进行一个异常捕获如果串口没有打开之间弹出对话框串口未打开然后我们进行一个勾选框的判断判断发送的是2进制还是十六进制数据最后进行数据处理和发送 UpdateData(TRUE); //1、读取编辑框内容 内容写到控件中然后同步到变量中//2、什么时候发送发送的条件就是文本内容是“发送”CString strSend;GetDlgItemText(IDC_BUTTON_SEND, strSend);if(strSend 发送){ //3、执行串口发送操作try{CString strOrdered ;if(1 m_chkHexSend.GetCheck())//当勾选框被选中的时候{ //以十六进制发送hexToSend.RemoveAll();//清空数组//十六进制 41 42 43 41空格为一组42空格为一组....。strOrdered GetOrderedStr();//MessageBox(strOrdered);for(int i 0; i strOrdered.GetLength(); i 2){CString strTemp strOrdered.Mid(i, 2);char *p strTemp.GetBuffer(2);hexToSend.Add(strtol(p, NULL, 16));}m_mscomm.put_Output(COleVariant(hexToSend));//发送的二进制转换成16进制//4、这里如果串口没有打开直接写数据程序会崩溃可能有异常直接try catch}else{//没有选中以字符格式发送strToSend m_strSend;m_mscomm.put_Output(COleVariant(strToSend));//发送数据}
这里我们如果发送的是十六进制数据进行一个消息处理 CString CComDlg::GetOrderedStr() { CString str; int i 0; int length m_strSend.GetLength(); for(i 0; i length - 1; i)//31 32 33 回车 34 34 31 327 34 31 32 7 32 33 3 34 { if(m_strSend.Mid(i, 1) ! m_strSend.Mid(i, 1) ! \r) { if(m_strSend.Mid(i1, 1) ! m_strSend.Mid(i1, 1) ! \r) { CString strTemp; strTemp m_strSend.Mid(i, 2); str str strTemp; i; } else { str str 0 m_strSend.Mid(i, 1); } } if(m_strSend.Mid(i, 1) \r m_strSend.Mid(i1, 1) \n) //碰到回车,也就是\n\r,则直接跳过\n\r这两个字符! i; } if(i m_strSend.GetLength()-1 m_strSend.Mid(i, 1) ! ) str str 0 m_strSend.Mid(i, 1); //该行防止34 31 32 7中7丢失 //至此, 31323334 34313207 34313207 32330334 //MessageBox(str); return str; } 6、接收十六进制或者二进制数据
void CComDlg::OnCommMscomm()
{// TODO: 在此处添加消息处理程序代码UpdateData(TRUE); static unsigned int cnt0; VARIANT variant_inp; COleSafeArray safearray_inp; long len,k; byte rxdata[1024]; //设置 BYTE 数组 CString strtemp; //通过声明这样一个字节数组您可以在后续的代码中使用rxdata来存储从串口读取的二进制数据switch(m_mscomm.get_CommEvent()) //1、如果我们读取到事件{case CMscomm::comEvReceive: //值为 2 表示接收缓冲区内有字符 //2、从串口缓冲区读取数据m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//规定二进制方式读取数据cnt; variant_inp m_mscomm.get_Input(); // variant_inp m_mscomm.get_Input()这行代码用于从串口读取数据并将读取的数据存储在variant_inp变量中safearray_inp variant_inp; //variant_inp中的数据转换为SAFEARRAY类型并存储在safearray_inp变量中。len safearray_inp.GetOneDimSize(); //得到有效的数据长度 //状态栏显示接收到的字符个数CString strReceiveNum;m_ulReceiveNum len;strReceiveNum.Format(%d, m_ulReceiveNum);strReceiveNum 接收 strReceiveNum;m_StatusBar.SetText(strReceiveNum, 2, 0);//SBT_POPOUT, SBT_NOBORDERS//3、接收数据for(k 0; k len; k) { safearray_inp.GetElement(k, rxdata k);if(1 m_chkHexReceive.GetCheck()) //接收到的数据以十六进制显示{//safearray_inp.GetElement(k, rxdata k); CString strtemp ;strtemp.Format(_T(%02X),rxdata[k]);//rxdata[k] 的值以十六进制格式添加到 strtemp 字符串中m_strReceive m_strReceive strtemp ; }else //接收到的数据以字符格式显示{CString strtemp ;//safearray_inp.GetElement(k, rxdata k); strtemp.Format(%c,rxdata[k]); //将字符送入临时变量strtemp存放m_strReceive m_strReceive strtemp;//m_strReceive接收EDIT的变量} }if (1 m_chkHexReceive.GetCheck()) // 如果以十六进制显示最后再加上一个换行{m_strReceive \r\n;}else{m_strReceive \n;}break;}UpdateData(FALSE); //更新编辑框内容//注意在更新完编辑框的内容之后还要设置接收编辑框定位到最后一行int nLineCount m_editReceive.GetLineCount();int nLineLength m_editReceive.LineLength(nLineCount);m_editReceive.LineScroll(nLineCount, nLineLength);//TRACE(%d, nLineCount);
}
7、点击十六进制发送的时候EDIT的内容变成十六进制
//将发送的文本内容直接从二进制编程变成16进制
void CComDlg::OnBnClickedCheckSendHex()
{ // TODO: 在此添加控件通知处理程序代码UpdateData(TRUE);if (1 m_chkHexSend.GetCheck()) //此时要把字符格式转换成十六进制{char *p m_strSend.GetBuffer(m_strSend.GetLength());m_strSend.ReleaseBuffer();CString str ;int length m_strSend.GetLength();for(int i 0; i length; i){CString strTemp;strTemp.Format(%02X, p[i]);str str strTemp ;}m_strSend str.TrimRight( );}else //此时要把十六进制转换成字符格式{int length m_strSend.GetLength();CString str;for(int i 0; i length; i 3){CString strTemp m_strSend.Mid(i, 2);char *p strTemp.GetBuffer(2);int num strtol(p, NULL, 16);strTemp.Format(%c, num);str str strTemp;}m_strSend str;}UpdateData(FALSE);
}