串口调试助手代码分析42
C语言串口通信助手代码
该程序全部由C写成没有C++ 更没用MFC完全是自娱自乐给需要的人一个参考#include "stdafx.h"#include <windowsx.h>#include "resource.h"#include "MainDlg.h"#include <windows.h>#include <stdio.h>#include <stdlib.h>HANDLE hComm;//用于获取串口打开函数的返回值(句柄或错误值)OVERLAPPED m_ov;COMSTAT comstat;DWORD m_dwCommEvents;TCHAR cRecs[200],cSends[100]; //接收字符串发送字符串char j=0,*cCom; //接收用统计数据大小变量端口选择BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){switch(uMsg){HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose);}return FALSE;}/*系统初始化函数*/BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1);ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM3"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM4"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM5"));ComboBox_SetCurSel(hwndCombo1,0);void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime);SetTimer(hwnd,1,1000,TimerProc);return TRUE;}/*监视串口错误时使用的函数*/boolProcessErrorMessage(char* ErrorText){char *Temp = new char[200];LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language(LPTSTR) &lpMsgBuf,NULL);sprintf(Temp, "WARNING: %s Failed with the following error:\n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, "com2"); MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP); LocalFree(lpMsgBuf);delete[] Temp;return true;}boolopenport(char *portname)//打开串口{hComm = CreateFile(portname, //串口号“com1”“com2” 调用方法:bool open; open=openport("com2");GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE) //如果被占用或是没有打开时返回的是这个错误代码CloseHandle(hComm);return FALSE;}elsereturn true;}boolsetupdcb(intrate_arg)//设置port的属性{DCB dcb;int rate= rate_arg;memset(&dcb,0,sizeof(dcb));if(!GetCommState(hComm,&dcb))//获取当前DCB配置return FALSE;// set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);dcb.BaudRate = rate;dcb.Parity = NOPARITY; //奇偶校验值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零dcb.fParity = 0; //为1的话激活奇偶校验检查dcb.StopBits = ONESTOPBIT;//停止位个数,0~2分别对应1位、1.5位、2位停止位dcb.ByteSize = 8; //数据位数dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutX = 0;dcb.fInX = 0;dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLim = 2;dcb.XoffLim = 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;// set DCBif(!SetCommState(hComm,&dcb))return false;elsereturn true;}/*串口读取相关时间设置*/boolsetuptimeout(DWORDReadInterval,DWORDReadTotalMultiplier,DWORDReadTotalconstant,DW ORDWriteTotalMultiplier,DWORDWriteTotalconstant){COMMTIMEOUTS timeouts;timeouts.ReadIntervalTimeout=ReadInterval; //读取两个字节间隔最大值mS如超过立即返回不再读取timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //如果同下面一个都为0 则无论是否读到数据都返回// 可以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; // 以毫秒为单位指定一个常数,用于计算读操作的总限时时间0表示不限时timeouts.WriteTotalTimeoutConstant=WriteTotalconstant;// 写操作延时同上timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier;if(!SetCommTimeouts(hComm, &timeouts))return false;elsereturn true;}intClearn() //清除buff中的内容并返回buff中现有数据量的大小并读取错误原因{DWORD dwError = 0;DWORD BytesRead = 0;ClearCommError(hComm, &dwError, &comstat);return comstat.cbInQue; //返回buff中数据量}/*串口数据接收读取函数*/void ReceiveChar(){BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char i=0,n;char RXBuff;j=0;while (i-n){n=i;Sleep(10);bResult = ClearCommError(hComm, &dwError, &comstat); i=(char)comstat.cbInQue;for (;i>0;i--){if (bRead)bResult = ReadFile(hComm, // Handle to COMM port &RXBuff, // RX Buffer Pointer1, // Read one byte&BytesRead, // Stores number of bytes read&m_ov); // pointer to the m_ov structure// printf("%c",RXBuff);cRecs[j++]=(char)RXBuff;if (!bResult){switch (dwError = GetLastError()){case ERROR_IO_PENDING:{bRead = FALSE;break;}default: break;}elsebRead = TRUE; // close if (bRead)if (!bRead){bRead = TRUE;bResult = GetOverlappedResult(hComm, // Handle to COMM port&m_ov, // Overlapped structure&BytesRead, // Stores number of bytes readTRUE); // Wait flag}}}boolWriteChar(char* m_szWriteBuffer,DWORDm_nToSend) //写字符的函数{BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;HANDLE m_hWriteEvent;ResetEvent(m_hWriteEvent);if (bWrite){m_ov.Offset = 0;m_ov.OffsetHigh = 0;// Clear bufferbResult = WriteFile(hComm, // Handle to COMM Portm_szWriteBuffer, // Pointer to message buffer in calling finction m_nToSend, // Length of message to send&BytesSent, // Where to store the number of bytes sent&m_ov ); // Overlapped structureif (!bResult){DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:// all other error codesbreak;}}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = GetOverlappedResult(hComm, // Handle to COMM port &m_ov, // Overlapped structure&BytesSent, // Stores number of bytes sentTRUE); // Wait flag// deal with the error codeif (!bResult){printf("GetOverlappedResults() in WriteFile()");}} // end if (!bWrite)// Verify that the data size send equals what we tried to send if (BytesSent != m_nToSend){printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)m_szWriteBuffer));}return true;}/*window时间函数回调*/void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime){SYSTEMTIME time; //定义机构体变量timeGetLocalTime(&time); //取系统时间以指针方式TCHAR strTime[256]; //程序只有一个作用wsprintf(strTime,"%04d-%02d-%02d %02d:%02d:%02d",time.wYear, //就是读取系统时间time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond);//然后写进strTimeSetDlgItemText(hwnd,IDC_TIME,strTime); //这个字符串}void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){switch(id){case IDC_SEND:{GetDlgItemText (hwnd,IDC_EDIT2,cSends,sizeof(cSends)); unsigned n=sizeof(cSends); //n是通知串口将发送字节的长度char send[100];wsprintf (send,"%s",cSends);WriteChar(send,n-1);SetCommMask(hComm, EV_RXCHAR); //监视串口是否接收有数据ReceiveChar(); //读取串口sbuff中数据cRecs[j]='\0'; //将cRecs转为字符串SetDlgItemText(hwnd,IDC_EDIT1,cRecs);} break;/*case IDC_RECEIVE: //暂时未用采用直接显示的方式{}break;*/case IDC_CHECK:{intctr;HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1);ctr = ComboBox_GetCurSel(hwndCombo1);switch (ctr){case 0:cCom="com1";break;case 1:cCom="com2";break;case 2:cCom="com3";break;case 3:cCom="com4";break;case 4:cCom="com5";break;default: cCom="com1";break;}if (openport(cCom)){ SetDlgItemText(hwnd,IDC_EDIT3,"OK !");MessageBox(hwnd,"串口打开成功!","",0); }elseSetDlgItemText(hwnd,IDC_EDIT3,"FAIL");if(setupdcb(9600)&&setuptimeout(1024,0,0,20,1000)) //初始化串口属性波特率9600SetDlgItemText(hwnd,IDC_EDIT4,"串口属性设置成功");elseSetDlgItemText(hwnd,IDC_EDIT4,"串口初始化失败!"); PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR |PURGE_RXABORT | PURGE_TXABORT);}default:break;}}void Main_OnClose(HWND hwnd) {EndDialog(hwnd, 0);}。
VB串口调试助手源代码
VB串口调试助手源代码Dim OutputAscii As BooleanDim InputString As StringDim OutputString As String'============================================================================== =======' 变量定义'============================================================================== =======Option Explicit ’强制显式声明Dim ComSwitch As Boolean ’串口开关状态判断Dim FileData As String ’要发送的文件暂存Dim SendCount As Long ’发送数据字节计数器Dim ReceiveCount As Long ’接收数据字节计数器Dim InputSignal As String ’接收缓冲暂存Dim OutputSignal As String ’发送数据暂存Dim DisplaySwitch As Boolean ’显示开关Dim ModeSend As Boolean ’发送方式判断Dim Savetime As Single ’时间数据暂存延时用Dim SaveTextPath As String ’保存文本路径' 网页超链接申明Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPrivate Sub CloseCom() '关闭串口On Error GoTo ErrIf MSComm.PortOpen = True ThenMSComm.PortOpen = False’先判断串口是否打开,如果打开则先关闭txtstatus.Text = "STATUS:COM Port Cloced" ’串口状态显示mnuconnect.Caption = "断开串口"cmdswitch.Caption = "打开串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\guan.jpg") ' 显示串口已经关闭的图标ImgSwitchoff.Visible = TrueImgSwitchon.Visible = FalseErr:End SubPrivate Sub UpdateStatus()If MSComm.PortOpen ThenStatusBar1.Panels(1).Text = "Connected"mnuautosend.Caption = "自动发送"mnuconnect.Caption = "断开串口"ElseStatusBar1.Panels(1).Text = "断开串口"mnuautosend.Caption = "disautosend"mnuconnect.Caption = "打开串口"End IfStatusBar1.Panels(2).Text = "COM" & mPortStatusBar1.Panels(3).Text = MSComm.SettingsIf (OutputAscii) ThenStatusBar1.Panels(4) = "ASCII"ElseStatusBar1.Panels(4) = "HEX"End If'On Error GoTo ErrIf ChkAutoSend.Value = 1 Then ’如果有效则,自动发送If MSComm.PortOpen = True Then ’串口状态判断mnuautosend.Caption = "Dis&autosend"TmrAutoSend.Interval = Val(TxtAutoSendTime) ’设置自动发送时间TmrAutoSend.Enabled = True ’打开自动发送定时器Elsemnuautosend.Caption = "autosend"ChkAutoSend.Value = 0 ’串口没有打开去掉自动发送MsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfElseIf ChkAutoSend.Value = 0 Then ’如果无效,不发送mnuautosend.Caption = "autosend"TmrAutoSend.Enabled = False ’关闭自动发送定时器End IfErr:End SubPrivate Sub CmdSendFile_Click() '发送文件On Error GoTo ErrIf MSComm.PortOpen = True Then ’如果串口打开了,则可以发送数据If FileData = "" Then ’判断发送数据是否为空MsgBox "发送的文件为空", 16, "串口调试助手" ’发送数据为空则提示ElseIf ChkHexReceive.Value = 1 Then ’如果按十六进制接收时,按二进制发送,否则按文本发送MSComm.InputMode = comInputModeBinary ’二进制发送ElseMSComm.InputMode = comInputModeText ’文本发送End IfMSComm.Output = Trim(FileData) ’发送数据ModeSend = True ’设置文本发送方式End IfElseMsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfErr:End SubPrivate Sub Comm_initial(Port As Byte, BaudRate As String, ParityBit As String, DataBit As Integer, StopBit As Integer)On Error GoTo ErrorTrap ' 错误则跳往错误处理If MSComm.PortOpen = True Then MSComm.PortOpen = False’先判断串口是否打开,如果打开则先关闭mPort = Port ’设定端口MSComm.Settings = BaudRate & "," & ParityBit & "," & DataBit & "," & StopBit ' 设置波特率,无校验,8位数据位,1位停止位MSComm.InBufferSize = 1024 ’设置接收缓冲区为1024字节MSComm.OutBufferSize = 4096 ’设置发送缓冲区为4096字节MSComm.InBufferCount = 0 ’清空输入缓冲区MSComm.OutBufferCount = 0 ’清空输出缓冲区MSComm.SThreshold = 1 ’发送缓冲区空触发发送事件MSComm.RThreshold = 1 ’每X个字符到接收缓冲区引起触发接收事件MSComm.OutBufferCount = 0 ’清空发送缓冲区MSComm.InBufferCount = 0 ’滑空接收缓冲MSComm.PortOpen = True ’打开串口If MSComm.PortOpen = True Thentxtstatus.Text = "STATUS:" & cbocom.Text & " OPEND," & cbobaudrate.Text & "," &Left(cboparitybit.Text, 1) & "," & cbodatabit.Text & "," & cbostopbit.TextElsetxtstatus.Text = "STATUS:COM Port Cloced" ’串口没打开时,提示串口关闭状态End IfExit SubErrorTrap: ’错误处理Select Case Err.NumberCase comPortAlreadyOpen ’如果串口已经打开,则提示MsgBox "没有发现此串口或被占用", 49, "串口调试助手"CloseComCase ElseMsgBox "没有发现此串口或被占用", 49, "串口调试助手"CloseComEnd SelectErr.ClearEnd SubPrivate Sub Comm_reSet(Port As Byte, BaudRate As String, ParityBit As String, DataBit As Integer, StopBit As Integer)On Error GoTo ErrorHint ’错误则跳往错误处理If MSComm.PortOpen = True Then MSComm.PortOpen = False’先判断串口是否打开,如果打开则先关闭mPort = Port ’设定端口MSComm.Settings = BaudRate & "," & ParityBit & "," & DataBit & "," & StopBit ' 设置波特率,无校验,8位数据位,1位停止位MSComm.PortOpen = True ’打开串口If MSComm.PortOpen = True Thencmdswitch.Caption = "关闭串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\kai.jpg") ' 显示串口已经打开的图标ImgSwitchoff.Visible = Falsemnuconnect.Caption = "disconnect"ImgSwitchon.Visible = Truetxtstatus.Text = "STATUS:" & cbocom.Text & " OPEND," & cbobaudrate.Text & "," &Left(cboparitybit.Text, 1) & "," & cbodatabit.Text & "," & cbostopbit.TextElsecmdswitch.Caption = "打开串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\guan.jpg") ' 显示串口已经关闭的图标ImgSwitchon.Visible = FalseImgSwitchoff.Visible = Truetxtstatus.Text = "STATUS:COM Port Cloced"End IfExit SubErrorHint: ’错误处理Select Case Err.NumberCase comPortAlreadyOpen ’如果串口已经打开,则提示MsgBox "没有成功,请重试", vbExclamation, "串口调试助手"CloseCom ’调用关闭串口函数Case ElseMsgBox "没有成功,请重试", vbExclamation, "串口调试助手"CloseCom ’调用关闭串口函数End SelectErr.Clear ’清除Err 对象的属性End SubPrivate Sub Command1_Click()End SubPrivate Sub cbobaudrate_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbocom_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbodatabit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cboparitybit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbostopbit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub chkautosend_Click()On Error GoTo ErrIf ChkAutoSend.Value = 1 Then ’如果有效则,自动发送If MSComm.PortOpen = True Then ’串口状态判断mnuautosend.Caption = "取消自动发送"TmrAutoSend.Interval = Val(TxtAutoSendTime) ’设置自动发送时间TmrAutoSend.Enabled = True ’打开自动发送定时器ElseChkAutoSend.Value = 0 ’串口没有打开去掉自动发送MsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfElseIf ChkAutoSend.Value = 0 Then ’如果无效,不发送mnuautosend.Caption = "自动发送数据"TmrAutoSend.Enabled = False ’关闭自动发送定时器End IfErr:End SubPrivate Sub cmdamend_Click()Dim spShell As Object ’定义存放引用对象的变量Dim spFolder As Object ’定义存放引用对象的变量Dim spFolderItem As Object ’定义存放引用对象的变量Dim spPath As String ’定义存放的变量On Error GoTo Err ’错误处理,防止取消打开文件夹时报错Const WINDOW_HANDLE = 0Const NO_OPTIONS = 0Set spShell = CreateObject("Shell.Application")Set spFolder = spShell.BrowseForFolder(WINDOW_HANDLE, "选择目录:", NO_OPTIONS,"C:\Scripts")Set spFolderItem = spFolder.SelfspPath = spFolderItem.PathspPath = Replace(spPath, "\", "\") ’ Replace函数的返回值是一个字符串txtsavepath.Text = spPath ’把文件夹路径显示在标签上SaveTextPath = txtsavepath.Text ’路径暂存Err:End SubPrivate Sub CmdClearCounter_Click()On Error GoTo ErrSendCount = 0 ’发送计数器清零ReceiveCount = 0 ’接收计数器清零txtRXcount.Text = "RX:" & 0 ’接收计数txtTXcount.Text = "TX:" & 0 ’发送计数Err:End SubPrivate Sub cmdclearrecieve_Click()TxtReceive.Text = ""End SubPrivate Sub cmdclearsend_Click()txtsend.Text = ""End SubPrivate Sub CmdHelp_Click()FrmHelp.ShowEnd SubPrivate Sub CmdQuit_Click()If MSComm.PortOpen = True Then MSComm.PortOpen = False’先判断串口是否打开,如果打开则先关闭Unload Me ’卸载窗体,并退出程序EndEnd SubPrivate Sub cmdsavedisp_Click()On Error GoTo Err ’错误处理SaveTextPath = txtsavepath ’路径暂存Open txtsavepath & "\1.txt" For Output As #1 ’打开文件’不存在的话会创建文件,如已存在会覆盖’ output 改为append 为追加’改为input 则只读Print #1, Year(Date) & "年" & Month(Date) & "月" & Day(Date) & _"日" & Hour(Time) & "时" & Minute(Time) & "分" & Second(Time) & _"秒" & vbCrLf & TxtReceive.Text + vbCrLf ’把接收区的文本保存文本前加上保存时间(0000年00月00日00时00分00秒)’ vbcrlf 为回车换行Close #1 ’关闭文件txtsavepath = "OK,1.txt Save" ’提示保存成功cmdsavedisp.Enabled = FalseSavetime = Timer ’记下开始的时间While Timer < Savetime + 5 ’循环等待5 - 要延时的时间DoEvents ’转让控制权,以便让操作系统处理其它的事件。
c#上位机串口通信助手源代码详解
c#上位机串口通信助手源代码实例详解
一、功能
1软件打开时,自动检测有效COM端口
2软件打开时,自动复原到上次关闭时的状态
3不必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位),可按更改后的信息自动将串口重新打开
4
5
6
7
8
扰
9
10
二、
三、
1
用
端口号:
数据位:
校验位:
发送(byte):tbSendCount接收(byte):tbReceivedCount
清空计数按钮:btnClearCount按16进制显示:cb16Display
接收区清空内容按钮:btnClearReceived保存数据按钮:btnSaveFile
接收数据框:tbReceivedData发送数据框:tbSendData
自动发送:cbAutomaticSend间隔时间:tbSpaceTime
按16进制发送:cb16Send发送区清空内容按钮:btnClearSend
2创建一个方法类
按Ctrl+shift+A快捷键创建一个类,名字叫Methods,代码为:
tbSendData.Text=tbSendDataStr;
}
}
//发送文本框键盘按键检测
privatevoidtbSendData_KeyPress(objectsender,KeyPressEventArgse) {
if(cb16Send.Checked)
{
//正则匹配
stringpattern="[0-9a-fA-F]|\b";//\b:退格键
if(m.Success)。
c#上位机串口通信助手源代码详解
c#上位机串口通信助手源代码实例详解一、功能1软件打开时,自动检测有效COM端口2 软件打开时,自动复原到上次关闭时的状态3 不必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位),可按更改后的信息自动将串口重新打开4 可统计接收字节和发送字节的个数5 接收数据可按16进制数据和非16进制数据进行整体转换6 可将接收到数据进行保存7 可设置自动发送,发送时间可进行实时更改8可按字符串、16进制字节、文件方式进行发送,字符串和16进制字节可分别进行存储,内容互不干扰9 按16进制发送时,可自动校验格式,不会输错10 可清空发送或接收区域的数据二、使用工具Visual Studio2015三、程序详解1 界面创建图1用winform创建如图1所示界面,控件名字分别为:端口号:cbxCOMPort 波特率:cbxBaudRate数据位:cbxDataBits 停止位:cbxStopBits校验位:label5 打开串口按钮:btnOpenCom发送(byte):tbSendCount 接收(byte):tbReceivedCount 清空计数按钮:btnClearCount 按16进制显示:cb16Display接收区清空内容按钮:btnClearReceived 保存数据按钮:btnSaveFile接收数据框:tbReceivedData 发送数据框:tbSendData自动发送:cbAutomaticSend 间隔时间:tbSpaceTime按16进制发送:cb16Send 发送区清空内容按钮:btnClearSend 读入文件按钮:btnReadFile 发送按钮:btnSend2 创建一个方法类按Ctrl+shift+A快捷键创建一个类,名字叫Methods,代码为:using System;using System.Collections;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading.Tasks;namespace串口助手sdd{class Methods{//获取有效的COM口public static string[] ActivePorts(){ArrayList activePorts = new ArrayList();foreach (string pname in SerialPort.GetPortNames()){activePorts.Add(Convert.ToInt32(pname.Substring(3)));}activePorts.Sort();string[] mystr = new string[activePorts.Count];int i = 0;foreach (int num in activePorts){mystr[i++] = "COM" + num.ToString();}return mystr;}//16进制字符串转换为byte字符数组public static Byte[] _16strToHex(string strValues){string[] hexValuesSplit = strValues.Split(' ');Byte[] hexValues = new Byte[hexValuesSplit.Length];Console.WriteLine(hexValuesSplit.Length);for (int i = 0; i < hexValuesSplit.Length; i++){hexValues[i] = Convert.ToByte(hexValuesSplit[i], 16);}return hexValues;}//byte数组以16进制形式转字符串public static string ByteTo16Str(byte[] bytes){string recData = null;//创建接收数据的字符串foreach (byte outByte in bytes)//将字节数组以16进制形式遍历到一个字符串内 {recData += outByte.ToString("X2") + " ";}return recData;}//16进制字符串转换字符串public static string _16strToStr(string _16str){string outStr = null;byte[] streamByte = _16strToHex(_16str);outStr = Encoding.Default.GetString(streamByte);return outStr;}}}2 Form1.cs的代码为:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.IO.Ports;using System.Linq;using System.Text;using System.Text.RegularExpressions;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.Collections;namespace串口助手sdd{public partial class Form1 : Form{//声明变量SerialPort sp = new SerialPort();bool isSetProperty = false;//串口属性设置标志位private enum PortState//声明接口显示状态,枚举型{打开,关闭}string path = AppDomain.CurrentDomain.BaseDirectory + "confing.ini";//声明配置文件路径string tbSendDataStr = "";//发送窗口字符串存储string tbSendData16 = "";//发送窗口16进制存储List<byte> receivedDatas = new List<byte>();//接收数据泛型数组//接收串口数据private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) {byte[] ReceivedData = new byte[sp.BytesToRead];//创建接收字节数组sp.Read(ReceivedData, 0, ReceivedData.Length);//读取所接收到的数据receivedDatas.AddRange(ReceivedData);tbReceivedCount.Text = (Convert.ToInt32(tbReceivedCount.Text) + ReceivedData.Length).ToString();if (cb16Display.Checked)tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray());elsetbReceivedData.Text =Encoding.Default.GetString(receivedDatas.ToArray());sp.DiscardInBuffer();//丢弃接收缓冲区数据}//发送串口数据private void DataSend(){try{if (cb16Send.Checked){byte[] hexBytes = Methods._16strToHex(tbSendData16);sp.Write(hexBytes, 0, hexBytes.Length);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + hexBytes.Length).ToString();}else{sp.WriteLine(tbSendDataStr);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + tbSendDataStr.Length).ToString();}}catch (Exception ex){MessageBox.Show(ex.Message.ToString());return;}}//设置串口属性private void SetPortProperty(){sp.PortName = cbxCOMPort.Text.Trim();//设置串口名sp.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim());//设置波特率switch (cbxStopBits.Text.Trim())//设置停止位{case"1": sp.StopBits = StopBits.One; break;case"1.5": sp.StopBits = StopBits.OnePointFive; break;case"2": sp.StopBits = StopBits.Two; break;default: sp.StopBits = StopBits.None; break;}sp.DataBits = Convert.ToInt32(cbxDataBits.Text.Trim());//设置数据位switch (cbxParity.Text.Trim())//设置奇偶校验位{case"无": sp.Parity = Parity.None; break;case"奇校验": sp.Parity = Parity.Odd; break;case"偶校验": sp.Parity = Parity.Even; break;default: sp.Parity = Parity.None; break;}sp.ReadTimeout = 5000;//设置超时时间为5sControl.CheckForIllegalCrossThreadCalls = false;//这个类中我们不检查跨线程的调用是否合法(因为.net 2.0以后加强了安全机制,,不允许在winform中直接跨线程访问控件的属性)//定义DataReceived事件的委托,当串口收到数据后出发事件sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);}//设置端口显示状态private void DisplayPortState(PortState portState){toolStripStatusLabel1.Text = cbxCOMPort.Text + "端口处于" + portState + "状态 " + cbxBaudRate.Text + " " + cbxDataBits.Text + " " + cbxStopBits.Text + " " + cbxParity.Text;}//重新打开串口private void AgainOpenPort(){if (sp.IsOpen){try{sp.Close();SetPortProperty();isSetProperty = true;sp.Open();}catch (Exception){isSetProperty = false;btnOpenCom.Text = "打开串口";DisplayPortState(PortState.关闭);MessageBox.Show("串口无效或已被占用!", "错误提示");return;}DisplayPortState(PortState.打开);}else{DisplayPortState(PortState.关闭);}}public Form1(){InitializeComponent();}//软件启动时加载事件private void Form1_Load(object sender, EventArgs e){#region加载配置文件Hashtable ht = new Hashtable();if (File.Exists(path)){try{string myline = "";string[] str = new string[2];using (StreamReader sr = new StreamReader(path)) {myline = sr.ReadLine();while (myline != null){str = myline.Split('=');ht.Add(str[0], str[1]);myline = sr.ReadLine();}}}catch(Exception ex){MessageBox.Show(ex.Message.ToString());}}#endregion#region设置窗口为固定大小且不可最大化this.MaximumSize = this.Size;this.MinimumSize = this.Size;this.MaximizeBox = false;#endregion#region列出常用的波特率cbxBaudRate.Items.Add("1200");cbxBaudRate.Items.Add("2400");cbxBaudRate.Items.Add("4800");cbxBaudRate.Items.Add("9600");cbxBaudRate.Items.Add("19200");cbxBaudRate.Items.Add("38400");cbxBaudRate.Items.Add("43000");cbxBaudRate.Items.Add("56000");cbxBaudRate.Items.Add("57600");cbxBaudRate.Items.Add("115200");if (ht.ContainsKey("cbxBaudRate"))cbxBaudRate.SelectedIndex =cbxBaudRate.Items.IndexOf(ht["cbxBaudRate"].ToString());elsecbxBaudRate.SelectedIndex = 3;cbxBaudRate.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出停止位cbxStopBits.Items.Add("1");cbxStopBits.Items.Add("1.5");cbxStopBits.Items.Add("2");if (ht.ContainsKey("cbxStopBits"))cbxStopBits.SelectedIndex =cbxStopBits.Items.IndexOf(ht["cbxStopBits"].ToString());elsecbxStopBits.SelectedIndex = 0;cbxStopBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出数据位cbxDataBits.Items.Add("8");cbxDataBits.Items.Add("7");cbxDataBits.Items.Add("6");cbxDataBits.Items.Add("5");if (ht.ContainsKey("cbxDataBits"))cbxDataBits.SelectedIndex =cbxDataBits.Items.IndexOf(ht["cbxDataBits"].ToString());elsecbxDataBits.SelectedIndex = 0;cbxDataBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出奇偶校验位cbxParity.Items.Add("无");cbxParity.Items.Add("奇校验");cbxParity.Items.Add("偶校验");if (ht.ContainsKey("cbxParity"))cbxParity.SelectedIndex =cbxParity.Items.IndexOf(ht["cbxParity"].ToString());elsecbxParity.SelectedIndex = 0;cbxParity.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region COM口重新加载cbxCOMPort.Items.Clear();//清除当前串口号中的所有串口名称 cbxCOMPort.Items.AddRange(Methods.ActivePorts());if (ht.ContainsKey("cbxCOMPort") &&cbxCOMPort.Items.Contains(ht["cbxCOMPort"].ToString()))cbxCOMPort.SelectedIndex =cbxCOMPort.Items.IndexOf(ht["cbxCOMPort"].ToString());elsecbxCOMPort.SelectedIndex = 0;cbxCOMPort.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region初始化计数器tbSendCount.Text = "0";tbSendCount.ReadOnly = true;tbReceivedCount.Text = "0";tbReceivedCount.ReadOnly = true;#endregion#region初始化当前时间toolStripStatusLabel3.Text = DateTime.Now.ToString();#endregion#region初始化串口状态toolStripStatusLabel1.ForeColor = Color.Blue;if (!isSetProperty)//串口未设置则设置串口属性{SetPortProperty();isSetProperty = true;}try{sp.Open();btnOpenCom.Text = "关闭串口";DisplayPortState(PortState.打开);}catch (Exception){//串口打开失败后,串口属性设置标志位设为falseisSetProperty = false;MessageBox.Show("串口无效或已被占用!", "错误提示"); }#endregion#region初始化间隔时间if (ht.ContainsKey("tbSpaceTime"))tbSpaceTime.Text = ht["tbSpaceTime"].ToString();elsetbSpaceTime.Text = "1000";#endregion#region初始化按16进制显示状态if (ht.ContainsKey("cb16Display") && ht["cb16Display"].ToString() == "True") cb16Display.Checked = true;elsecb16Display.Checked = false;#endregion#region初始化按16进制发送状态if (ht.ContainsKey("cb16Send") && ht["cb16Send"].ToString() == "True")cb16Send.Checked = true;elsecb16Send.Checked = false;#endregion#region初始化发送区文本if(ht.ContainsKey("tbSendData16") && ht.ContainsKey("tbSendDataStr")){tbSendData16 = ht["tbSendData16"].ToString();tbSendDataStr = ht["tbSendDataStr"].ToString();if (cb16Send.Checked)tbSendData.Text = ht["tbSendData16"].ToString();elsetbSendData.Text = ht["tbSendDataStr"].ToString();}#endregiontbSendData.Focus();}//显示当前时间private void timer1_Tick(object sender, EventArgs e){toolStripStatusLabel3.Text = DateTime.Now.ToString();}//点击打开串口按钮private void btnOpenCom_Click(object sender, EventArgs e){if (!sp.IsOpen)//串口没有打开时{if (!isSetProperty)//串口未设置则设置串口属性{SetPortProperty();isSetProperty = true;}try{sp.Open();btnOpenCom.Text = "关闭串口";DisplayPortState(PortState.打开);}catch (Exception){//串口打开失败后,串口属性设置标志位设为falseisSetProperty = false;MessageBox.Show("串口无效或已被占用!", "错误提示"); }}else//串口已经打开{try{sp.Close();isSetProperty = false;btnOpenCom.Text = "打开串口";DisplayPortState(PortState.关闭);}catch (Exception){MessageBox.Show("关闭串口时发生错误", "错误提示"); }}}//发送串口数据private void btnSend_Click(object sender, EventArgs e){if (tbSendData.Text.Trim() == "")//检测发送数据是否为空{MessageBox.Show("请输入要发送的数据!", "错误提示");return;}if (sp.IsOpen){DataSend();}else{MessageBox.Show("串口未打开!", "错误提示");}}//点击端口号选择下拉框按钮private void cbxCOMPort_SelectedIndexChanged(object sender, EventArgs e){AgainOpenPort();}//点击波特率选择下拉框按钮private void cbxBaudRate_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击数据位选择下拉框按钮private void cbxDataBits_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击停止位选择下拉框按钮private void cbxStopBits_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击校验位选择下拉框按钮private void cbxParity_SelectedIndexChanged(object sender, EventArgs e){AgainOpenPort();}//点击数据接收区清空按钮private void btnClearReceived_Click(object sender, EventArgs e){receivedDatas.Clear();tbReceivedData.Text = "";}//点击是否按16进制显示接收数据private void cb16Display_CheckedChanged(object sender, EventArgs e){if (cb16Display.Checked)tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray());elsetbReceivedData.Text =Encoding.Default.GetString(receivedDatas.ToArray());//点击是否按16进制发送数据private void cb16Send_CheckedChanged(object sender, EventArgs e){if (cb16Send.Checked){tbSendData.Text = tbSendData16;}else{tbSendData.Text = tbSendDataStr;}}//发送文本框键盘按键检测private void tbSendData_KeyPress(object sender, KeyPressEventArgs e){if (cb16Send.Checked){//正则匹配string pattern = "[0-9a-fA-F]|\b";//\b:退格键Match m = Regex.Match(e.KeyChar.ToString(), pattern);if (m.Success){if(e.KeyChar != '\b'){if (tbSendData.Text.Length % 3 == 2){tbSendData.Text += " ";tbSendData.SelectionStart = tbSendData.Text.Length;}e.KeyChar = Convert.ToChar(e.KeyChar.ToString().ToUpper()); }e.Handled = false;}else{e.Handled = true;}}else{e.Handled = false;}}//点击清空发送内容private void btnClearSend_Click(object sender, EventArgs e){tbSendData.Text = "";if (cb16Send.Checked)tbSendData16 = "";elsetbSendDataStr = "";//点击清空计数器数据private void btnClearCount_Click(object sender, EventArgs e){tbReceivedCount.Text = "0";tbSendCount.Text = "0";}//点击是否设置自动发送private void cbAutomaticSend_CheckedChanged(object sender, EventArgs e) {if (cbAutomaticSend.Checked){timer2.Enabled = true;timer2.Interval = Convert.ToInt32(tbSpaceTime.Text);}else{timer2.Enabled = false;}}//自动发送时间文本框键盘按键检测private void tbSpaceTime_KeyPress(object sender, KeyPressEventArgs e) {//正则匹配string pattern = "[0-9]|\b";Match m = Regex.Match(e.KeyChar.ToString(),pattern);if (m.Success){timer2.Interval = Convert.ToInt32(tbSpaceTime.Text);e.Handled = false;}else{e.Handled = true;}}//串口显示状态private void timer2_Tick(object sender, EventArgs e){if (sp.IsOpen){DataSend();}else{timer2.Enabled = false;cbAutomaticSend.Checked = false;MessageBox.Show("串口未打开!", "错误提示");return;}if (tbSendData.Text.Trim() == "")//检测发送数据是否为空{timer2.Enabled = false;cbAutomaticSend.Checked = false;MessageBox.Show("请输入要发送的数据!", "错误提示");return;}}//关闭窗口时出发的事件private void Form1_FormClosed(object sender, FormClosedEventArgs e){try{using (StreamWriter sw = new StreamWriter(path, false)){sw.WriteLine("cbxCOMPort=" + cbxCOMPort.Text);sw.WriteLine("cbxBaudRate=" + cbxBaudRate.Text);sw.WriteLine("cbxDataBits=" + cbxDataBits.Text);sw.WriteLine("cbxStopBits=" + cbxStopBits.Text);sw.WriteLine("cbxParity=" + cbxParity.Text);sw.WriteLine("cb16Display="+ cb16Display.Checked.ToString()); sw.WriteLine("tbSpaceTime=" + tbSpaceTime.Text);sw.WriteLine("cb16Send=" + cb16Send.Checked.ToString());sw.WriteLine("tbSendDataStr=" + tbSendDataStr);sw.WriteLine("tbSendData16=" + tbSendData16);sp.Close();}}catch(Exception ex){MessageBox.Show(ex.Message.ToString());}}//发送文本框按键抬起时出发的事件private void tbSendData_KeyUp(object sender, KeyEventArgs e){if (cb16Send.Checked){tbSendData16 = tbSendData.Text.Trim();}else{tbSendDataStr = tbSendData.Text;}}//点击读入文件按钮private void btnReadFile_Click(object sender, EventArgs e){openFileDialog1.Filter = "所有文件(*.*)|*.*";//文件筛选器的设定openFileDialog1.FilterIndex = 1;openFileDialog1.Title = "选择文件";openFileDialog1.FileName = "";openFileDialog1.ShowHelp = true;if(openFileDialog1.ShowDialog() == DialogResult.OK){using (FileStream fs = newFileStream(openFileDialog1.FileName,FileMode.Open)){byte[] bufferByte = new byte[fs.Length];fs.Read(bufferByte, 0, Convert.ToInt32(fs.Length));sp.Write(bufferByte, 0, bufferByte.Length);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + bufferByte.Length).ToString();}}}//点击保存数据按钮private void btnSaveFile_Click(object sender, EventArgs e){saveFileDialog1.Filter = "所有文件(*.*)|*.*";if(saveFileDialog1.ShowDialog() == DialogResult.OK){string fName = saveFileDialog1.FileName;using(FileStream fs = File.Open(fName, FileMode.Append)){fs.Write(receivedDatas.ToArray(), 0, receivedDatas.Count);}}}}}需要源代码或有疑问的c#爱好者们,欢迎加入c#技术交流群(33647125),附加信息为”我以下载此文档”,进群后找群主索要源代码或进行技术交流。
经典的串口调试助手源代码
/article/446.html/hinzn/blog/item/4e81b4459b390a2ecffca3bb.html/modeng_2005/blog/static/265611200981142011329//mod eng_2005/blog/static/265611200981142011329/Dim OutputAscii As BooleanDim InputString As StringDim OutputString As String'============================================================================== =======' 变量定义'============================================================================== =======Option Explicit ' 强制显式声明Dim ComSwitch As Boolean ' 串口开关状态判断Dim FileData As String ' 要发送的文件暂存Dim SendCount As Long ' 发送数据字节计数器Dim ReceiveCount As Long ' 接收数据字节计数器Dim InputSignal As String ' 接收缓冲暂存Dim OutputSignal As String ' 发送数据暂存Dim DisplaySwitch As Boolean ' 显示开关Dim ModeSend As Boolean ' 发送方式判断Dim Savetime As Single ' 时间数据暂存延时用Dim SaveTextPath As String ' 保存文本路径' 网页超链接申明Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPrivate Sub CloseCom() '关闭串口On Error GoTo ErrIf MSComm.PortOpen = True Then MSComm.PortOpen = False ' 先判断串口是否打开,如果打开则先关闭txtstatus.Text = "STATUS:COM Port Cloced" ' 串口状态显示mnuconnect.Caption = "断开串口"cmdswitch.Caption = "打开串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\guan.jpg") ' 显示串口已经关闭的图标ImgSwitchoff.Visible = TrueImgSwitchon.Visible = FalseErr:End SubPrivate Sub UpdateStatus()If MSComm.PortOpen ThenStatusBar1.Panels(1).Text = "Connected"mnuautosend.Caption = "自动发送"mnuconnect.Caption = "断开串口"ElseStatusBar1.Panels(1).Text = "断开串口"mnuautosend.Caption = "disautosend"mnuconnect.Caption = "打开串口"End IfStatusBar1.Panels(2).Text = "COM" & mPortStatusBar1.Panels(3).Text = MSComm.SettingsIf (OutputAscii) ThenStatusBar1.Panels(4) = "ASCII"ElseStatusBar1.Panels(4) = "HEX"End If'On Error GoT o ErrIf ChkAutoSend.Value = 1 Then ' 如果有效则,自动发送If MSComm.PortOpen = True Then ' 串口状态判断mnuautosend.Caption = "Dis&autosend"TmrAutoSend.Interval = Val(TxtAutoSendTime) ' 设置自动发送时间TmrAutoSend.Enabled = True ' 打开自动发送定时器Elsemnuautosend.Caption = "autosend"ChkAutoSend.Value = 0 ' 串口没有打开去掉自动发送MsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfElseIf ChkAutoSend.Value = 0 Then ' 如果无效,不发送mnuautosend.Caption = "autosend"TmrAutoSend.Enabled = False ' 关闭自动发送定时器End IfErr:End SubPrivate Sub CmdSendFile_Click() '发送文件On Error GoTo ErrIf MSComm.PortOpen = True Then ' 如果串口打开了,则可以发送数据If FileData = "" Then ' 判断发送数据是否为空MsgBox "发送的文件为空", 16, "串口调试助手" ' 发送数据为空则提示ElseIf ChkHexReceive.Value = 1 Then ' 如果按十六进制接收时,按二进制发送,否则按文本发送MSComm.InputMode = comInputModeBinary ' 二进制发送ElseMSComm.InputMode = comInputModeText ' 文本发送End IfMSComm.Output = Trim(FileData) ' 发送数据ModeSend = True ' 设置文本发送方式End IfElseMsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfErr:End SubPrivate Sub Comm_initial(Port As Byte, BaudRate As String, ParityBit As String, DataBit As Integer, StopBit As Integer)On Error GoTo ErrorTrap ' 错误则跳往错误处理If MSComm.PortOpen = True Then MSComm.PortOpen = False ' 先判断串口是否打开,如果打开则先关闭mPort = Port ' 设定端口MSComm.Settings = BaudRate & "," & ParityBit & "," & DataBit & "," & StopBit ' 设置波特率,无校验,8位数据位,1位停止位MSComm.InBufferSize = 1024 ' 设置接收缓冲区为1024字节MSComm.OutBufferSize = 4096 ' 设置发送缓冲区为4096字节MSComm.InBufferCount = 0 ' 清空输入缓冲区MSComm.OutBufferCount = 0 ' 清空输出缓冲区MSComm.SThreshold = 1 ' 发送缓冲区空触发发送事件MSComm.RThreshold = 1 ' 每X个字符到接收缓冲区引起触发接收事件MSComm.OutBufferCount = 0 ' 清空发送缓冲区MSComm.InBufferCount = 0 ' 滑空接收缓冲MSComm.PortOpen = True ' 打开串口If MSComm.PortOpen = True Thentxtstatus.Text = "STATUS:" & cbocom.Text & " OPEND," & cbobaudrate.Text & "," & Left(cboparitybit.Text, 1) & "," & cbodatabit.Text & "," & cbostopbit.TextElsetxtstatus.Text = "STATUS:COM Port Cloced" ' 串口没打开时,提示串口关闭状态End IfExit SubErrorTrap: ' 错误处理Select Case Err.NumberCase comPortAlreadyOpen ' 如果串口已经打开,则提示MsgBox "没有发现此串口或被占用", 49, "串口调试助手"CloseComCase ElseMsgBox "没有发现此串口或被占用", 49, "串口调试助手"CloseComEnd SelectErr.ClearEnd SubPrivate Sub Comm_reSet(Port As Byte, BaudRate As String, ParityBit As String, DataBit As Integer,StopBit As Integer)On Error GoTo ErrorHint ' 错误则跳往错误处理If MSComm.PortOpen = True Then MSComm.PortOpen = False ' 先判断串口是否打开,如果打开则先关闭mPort = Port ' 设定端口MSComm.Settings = BaudRate & "," & ParityBit & "," & DataBit & "," & StopBit ' 设置波特率,无校验,8位数据位,1位停止位MSComm.PortOpen = True ' 打开串口If MSComm.PortOpen = True Thencmdswitch.Caption = "关闭串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\kai.jpg") ' 显示串口已经打开的图标ImgSwitchoff.Visible = Falsemnuconnect.Caption = "disconnect"ImgSwitchon.Visible = Truetxtstatus.Text = "STATUS:" & cbocom.Text & " OPEND," & cbobaudrate.Text & "," & Left(cboparitybit.Text, 1) & "," & cbodatabit.Text & "," & cbostopbit.TextElsecmdswitch.Caption = "打开串口"'ImgSwitch.Picture = LoadPicture("f:\我的VB\串口调试软件\图片\guan.jpg") ' 显示串口已经关闭的图标ImgSwitchon.Visible = FalseImgSwitchoff.Visible = Truetxtstatus.Text = "STATUS:COM Port Cloced"End IfExit SubErrorHint: ' 错误处理Select Case Err.NumberCase comPortAlreadyOpen ' 如果串口已经打开,则提示MsgBox "没有成功,请重试", vbExclamation, "串口调试助手"CloseCom ' 调用关闭串口函数Case ElseMsgBox "没有成功,请重试", vbExclamation, "串口调试助手"CloseCom ' 调用关闭串口函数End SelectErr.Clear ' 清除Err 对象的属性End SubPrivate Sub Command1_Click()End SubPrivate Sub cbobaudrate_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbocom_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbodatabit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cboparitybit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub cbostopbit_Change()Call Comm_reSet(Val(Mid(cbocom.Text, 4, 2)), cbobaudrate.Text, Left(cboparitybit.Text, 1), cbodatabit.Text, cbostopbit.Text) '串口设置End SubPrivate Sub chkautosend_Click()On Error GoTo ErrIf ChkAutoSend.Value = 1 Then ' 如果有效则,自动发送If MSComm.PortOpen = True Then ' 串口状态判断mnuautosend.Caption = "取消自动发送"TmrAutoSend.Interval = Val(TxtAutoSendTime) ' 设置自动发送时间TmrAutoSend.Enabled = True ' 打开自动发送定时器ElseChkAutoSend.Value = 0 ' 串口没有打开去掉自动发送MsgBox "串口没有打开,请打开串口", 48, "串口调试助手" ' 如果串口没有被打开,提示打开串口End IfElseIf ChkAutoSend.Value = 0 Then ' 如果无效,不发送mnuautosend.Caption = "自动发送数据"TmrAutoSend.Enabled = False ' 关闭自动发送定时器End IfErr:End SubPrivate Sub cmdamend_Click()Dim spShell As Object ' 定义存放引用对象的变量Dim spFolder As Object ' 定义存放引用对象的变量Dim spFolderItem As Object ' 定义存放引用对象的变量Dim spPath As String ' 定义存放的变量On Error GoTo Err ' 错误处理,防止取消打开文件夹时报错Const WINDOW_HANDLE = 0Const NO_OPTIONS = 0Set spShell = CreateObject("Shell.Application")Set spFolder = spShell.BrowseForFolder(WINDOW_HANDLE, "选择目录:", NO_OPTIONS, "C:\Scripts")Set spFolderItem = spFolder.SelfspPath = spFolderItem.PathspPath = Replace(spPath, "\", "\") ' Replace函数的返回值是一个字符串txtsavepath.Text = spPath ' 把文件夹路径显示在标签上SaveTextPath = txtsavepath.Text ' 路径暂存Err:End SubPrivate Sub CmdClearCounter_Click()On Error GoTo ErrSendCount = 0 ' 发送计数器清零ReceiveCount = 0 ' 接收计数器清零txtRXcount.Text = "RX:" & 0 ' 接收计数txtTXcount.Text = "TX:" & 0 ' 发送计数Err:End SubPrivate Sub cmdclearrecieve_Click()TxtReceive.Text = ""End SubPrivate Sub cmdclearsend_Click()txtsend.Text = ""End SubPrivate Sub CmdHelp_Click()FrmHelp.ShowEnd SubPrivate Sub CmdQuit_Click()If MSComm.PortOpen = True Then MSComm.PortOpen = False ' 先判断串口是否打开,如果打开则先关闭Unload Me ' 卸载窗体,并退出程序EndEnd SubPrivate Sub cmdsavedisp_Click()On Error GoTo Err ' 错误处理SaveTextPath = txtsavepath ' 路径暂存Open txtsavepath & "\1.txt" For Output As #1 ' 打开文件' 不存在的话会创建文件,如已存在会覆盖' output 改为append 为追加' 改为input 则只读Print #1, Year(Date) & "年" & Month(Date) & "月" & Day(Date) & _"日" & Hour(Time) & "时" & Minute(Time) & "分" & Second(Time) & _"秒" & vbCrLf & TxtReceive.Text + vbCrLf ' 把接收区的文本保存文本前加上保存时间(0000年00月00日00时00分00秒)' vbcrlf 为回车换行Close #1 ' 关闭文件txtsavepath = "OK,1.txt Save" ' 提示保存成功cmdsavedisp.Enabled = FalseSavetime = Timer ' 记下开始的时间While Timer < Savetime + 5 ' 循环等待5 - 要延时的时间DoEvents ' 转让控制权,以便让操作系统处理其它的事件。
串口调试助手代码分析42
第5章串口调试助手代码分析1、建立基于对话框的工程SCOMM2、绘制界面,如下图:接收区串口组合框:IDC_COMBO_COMSELECT,m_Com波特率组合框:IDC_COMBO_SPEED,m_Speed停止位组合框:IDC_COMBO_STOPBITS,m_StopBits数据位组合框:IDC_COMBO_DATABITS,m_DataBits校验位组合框:IDC_COMBO_PARITY,m_Parity十六进制显示(接收):IDC_CHECK_HEXRECIEVE,m_ctrlHexReceieve接收编辑框:IDC_EDIT_RECIVE ,m_ReceiveData m_ctrlReceiveData Style:Vertical Scroll MultiLine打开串口IDC_BUTTON_OPENPORT,m_ctrlOpenPort串口开关标志图标IDC _STATIC_OPENOFF,m_ctrlIconOpenoff数据文件保存路径IDC _EDIT_SA VEPATH,m_strCurPath保存显示数据文件路径IDC _EDIT_SA VEPATH, m_ctrlSavePath接收计数IDC_STATIC_RXCOUNT ,m_ctrlRXCOUNT发送区…。
3、添加CSeraiPort类文件将类文件SerialPort.h SerialPort.cpp 复制到工程所在文件夹中(选择改进后的类),然后单击VC 6.0菜单Projrct -> Add to Projrct ->Files… ,再在打开的文件选择对话框中选择SerialPort.h 和SerialPort.cpp ,点击OK,就把类文件加入当前工程,并在SCOMMDlg.h 中加入头文件,#include "SerialPort.h",通过上述步骤就在当前工程中加入了CSeraiPort类。
(串口通信编程)开源串口调试助手Common(ComMonitor)
(串⼝通信编程)开源串⼝调试助⼿Common(ComMonitor) 最新的⽂档见这⾥: 我写的串⼝调试助⼿程序以及源代码. 警告:请勿将本软件源代码⽤于任何商业⽤途。
其实吧, 我写的这个串⼝软件绝对⽐⽹上流传的⼀些串⼝调试软件好⽤很多, 对于软件,我本⾝并没有作 太多推⼴, ⼀些功能我由于懒也没有⽂档化; 如果您正在使⽤, 也觉得我说得没错, 还望您帮忙推⼴⼀下. 感激!本程序最近正在使⽤C++完全重构, github上⾯的源代码⽆法通过编译~~ 敬请期待最新版本!微云你就⼀坑货, 说了的链接永久有效呢?源代码: 声明:本软件为开源软件,绝对不包含任何对系统不利的代码,对于360的那种⾏为,我不想说什么. 软件界⾯:-------------------------------------------------------------------------------------------------------------------------说明: 更新信息可能不会再更新到这⾥, 请到上⾯查看. 更新:2014-07-07:①优化:接收数据时,如果最后⼀个字符是'\r'或'\n',则会在⼀定时间内等待接收所有'\r','\n'字符,避免导致读取'\r\n'可能造成的两次换⾏②更改:除已经提到的那三种情况, 还有使⽤'\r\n\r'三个字符作为换⾏符使⽤的, 已增加⽀持2014-07-07:①修复:回车换⾏字符'\r','\n','\r\n'均能达到换⾏效果②修复:⼀开始"忽略回车"等⽆法点击问题③优化:简化对数据中包含'\0'的数据的处理④增加:简洁界⾯模式时把⼯具栏放到左边⑤更改:只显⽰接收区按下的"回车"字符为"<Enter>",其它不显⽰⑥增加:接收区增加⼀个"清空数据"菜单2014-07-06 1.17:①增加:允许从接收区输⼊字符并发送(更友好的类交互模式) 会显⽰的字符包括: ' ' <Space> '\b' <Backspace> '\t' <Tab> '\r' <Enter> 感觉输⼊效果还不错:②更改:更改了字符接收区/发送区的字体为Consolas等宽字体,不再使⽤原来的Courier字体③增加:简洁模式 - 此模式下⼤部分界⾯元素会被隐藏, 有时候这样更舒服 见上图所⽰, 左下⾓为"简洁模式"开关, 开启简洁模式后就像上图, 是不是很简洁?④增加:主窗⼝的⾃动界⾯布局(允许拖动改变窗⼝⼤⼩,控件坐标⾃动调整)⑤更改:默认使⽤的模式改为:字符接收+字符发送2014-07-05 1.16 (未对外发布):①字符接收数据时,增加对控制字符Backspace的⽀持(即'\b'),效果就是向前删除⼀个字符②修复⼀处中⽂检测错误(原来是对的, 不知道什么时候改错了③删除了窗体⼤⼩调整(下个版本即将使⽤⾃动布局)2014-03-03 1.15: 更新:⽀持⼿动输⼊⾮标准波特率 改进:增加了⼏个功能快捷键,⽐如Alt+S为发送,.... 优化:修正:如果接收缓冲区有未显⽰的数据,则会在按下继续显⽰时进⾏提⽰,⽽不是原来的在接收到下⼀次的数据时进⾏提⽰; 2013-11-02 1.14: 更新:修改了原来的命令发送模式的界⾯,现在变得更加友好了 如下图, 先选择要发送的命令列表⽂件: 点击打开, 将会打开如下界⾯: 1.上⾯的代码是我测试蓝⽛芯⽚⽤到的命令列表⽂件, 点击"发送命令"就会发送对应的⼀条命令 2.16进制还是原来的要求, 2个⼀组即可; 对于字符数据:默认开启转义字符功能, ⽐如 '\n' 就代表换⾏, ⽀持字符型转义字符有6个, \n,\r,\\,\t,\a,\v,\b, 那些可见的字符不需要转义, ⽐如引号,问号... ⽀持的16进制转义字符格式:\x?? - 其中, ⼀个?代表⼀个16进制字符, 以上4个字符组成⼀个16进制值,缺⼀不可 3.⽂本框中的数据可以在发送时随时修改,回车键可看到效果, (但修改的内容⽬前不能更新到原来的本地⽂件上) 4.注意到数据类型后⾯的"双击改变"⼏个字样, 也就是说通过双击, 可以改变那条命令的解析格式 5.数据⼤⼩是指最终要被发送的数据的⼤⼩, ⽽不是转义前的⼤⼩ 命令⽂件的格式举例: C:初始化SPP库:at+init\r\n C:查询任意访问码的蓝⽛设备:at+iac=9e8b33\r\n C:查询设备类为0x1f1f的蓝⽛设备:at+class=1f1f\r\n C:设置查询模式:at+inqm=1,9,48\r\n C:过滤,查询周边蓝⽛设备:at+inq\r\n H:16进制测试:12 45 67 4f 分为3部分组成, 两者之间⽤冒号隔开: 第1部分:C或者H(⼤写), 代表数据是16进制还是字符数据 第2部分:命令的名字 第3部分:数据对应的数据 BUG修复: 上⼀个版本在发送数据前忘记检查串⼝是否已经打开了, 已修复~----------------------------------------------------------------------------------------------------------2012-12-24 1.0.0.0:发布第1个版本2012-12-26:⾃动识别当前存在,插⼊,移除的串⼝号2013-01-11 1.0.0.1:增加保存接收区数据到⽂件(16进制/⽂本形式)增加从⽂件读数据到发送区(16进制/⽂本形式)增加暂停显⽰功能增加复制发送/接收区数据到剪贴板2013-01-18 1.0.0.2:修复:⽂本⽂件,16⼆进制⽂件读取错误修复:程序内部缓冲区满后使程序进⼊死循环修复:⽂本字符⽅式显⽰接收的数据时产⽣不正确的换⾏符的错误,若要产⽣换⾏符, 请使⽤"\n"2013-02-08 1.0.0.3:内部程序作了许多的优化⼯作,包含数据的发送⽅式等修复接收数据时⿏标在接收区的⽂本选择造成的⼲扰2013-02-14 1.0.0.4:增加显⽰出0~127号ASCII对应8,10,16进制功能2013-02-24 1.0.0.5,今天元宵节:更改原来的1~64串⼝列表到⾃动检测计算机上的可⽤串⼝2013-02-27 1.0.0.6:若发送⽂本,则⾃动发送被⾃动取消(若⾃动发送选项已打开)在显⽰模式下不允许对接收区数据进⾏选择操作提供硬件⽀持的串⼝设备设置为⽤户提供串⼝超时设置提供⼿动设置DTR/RTS引脚电平2013-03-01 1.0.0.7:修改原计算器(系统)为表达式求值计算器(简单版本)2013-03-03:添加:<其它>菜单添加<设备管理器>修改:在关闭串⼝后⾃动发送前⾯的钩不再⾃动取消(如果已经选中)修改:串⼝被关闭/移除后串⼝列表回到第⼀个串⼝设备的BUG2013-03-04:修改:现在在串⼝列表中可以显⽰串⼝在设备管理器中的名字了修正:⽆法显⽰ MSP430-FETUIF Debugger 的串⼝号(现在调⽤SetupApi更新列表)2013-03-05:为了⽅便数据的统计与显⽰,16进制内容与字符内容被显⽰到不同的编辑框中2013-03-09 1.0.0.8:修正在使⽤SetupApi枚举串⼝设备时未检测并⼝设备⽽造成的内存异常访问错误减少在某些波特率(如:19200bps)下丢包严重的情况(如:MSP430串⼝),有时候还是会发⽣,等待修复.某些软件(如:SComAssistant采⽤每次只读⼀个字节的办法效果还⾏, 就是速度有点慢. 我改成了WaitCommEvent函数调⽤了(原来是Pending ReadFile),减少了CPU占⽤(有些串⼝驱动并不总是⽀持同步操作.以前只管ReadFile+输出nRead字节,这⾥错误,ReadFile并不保证读取到要求的数据量后才返回,这⾥会导致严重丢包,WriteFile亦然.速度减慢,但数据更完整2013-03-10 1.0.0.9:修正:因为在格式化字符串的最后少写了⼀句 *pb = '\0',导致接收区数据显⽰错误! 修复:对utils.hex2chs和add_text作了⼤量修改,⼤⼤减少数据丢包,貌似没有丢包?,细节处理参见源程序 1.0.0.8版本因为内部原因速度严重减慢, 1.0.0.9回到原来的快速!2013-03-18:更正:若为字符显⽰⽅式,16进制⽅式保存不被允许,因为格式基本上不满⾜!2013-03-23 1.10:添加:⼯作模式中,右键点击接收区字符⽂本框可以使能中⽂显⽰模式(不推荐),由于中⽂字符由两个字节构成,所以:⼀旦在某⼀次接收过程中只接收到了中⽂字符的⼀个字节,那么数据就会显⽰出错, 这个⽆法避免, 所以建议尽量不使能中⽂显⽰模式.修正:⽤C语⾔的⼈们都习惯使⽤'\n'作为换⾏符,我也这样使⽤,但偏偏Windows的编辑框以'\r\n'作为换⾏符,没有办法,我不得不把所有的'\n'换成'\r\n',效率必然会下降,⽽且我不得不计算出\n的个数先 --> 为了计算所需缓冲区的⼤⼩.添加:现在可以显⽰出还未被发送出去的数据计数.添加:新增计时器,打开串⼝后开始计时,关闭后停⽌计时.2013-03-25:修正:⼤⼤减少中⽂乱码的问题.细节处理见代码.增加:字符串转16进制数组功能,⼯具菜单⾥⾯.2013-04-04:修正:⽆法复制接收区字符⽂本的BUG.⼩提⽰:在选择串⼝时,如果没有任何可⽤的串⼝,则进⾏提⽰更新.2013-04-07:修改:完全修改了utils.str2hex的实现,⼤⼤增加了16进制输⼊的灵活性.现在的要求:每个16进制值由两个相邻字符组成,⽆其它限制.(以前是2个相邻字符+⼀个空格)2013-04-11:发送字符数据时,对于换⾏,只发送'\n',不再发送'\r\n',注意:结尾的'\0\'不被发送!2013-04-13:修正:更改发送与接收⽅式为异步⽅式.添加:简单波形显⽰.2013-04-23:修正:发送与接收⽅式改回同步⽅式!坑~修正:当发送操作达到100次时⽆法继续发送的BUG!修改:优化内部线程同步机制,避免程序停⽌⼯作(失去响应)!优化:优化⾃动发送数据的⽅式,提⾼精度,减⼩内存/CPU占⽤!⼩提⽰:在加载/保存⽂件时,若不清楚打开/保存⽅式,可以查看简单的帮助信息!2013-05-11:明天母亲节修正:终于找到⼀个⽐较好的办法来处理⾃动发送⽤到的重复数据了,呵呵,时间下限减少到10ms2013-07-05:临时修正:选择从⽂件加载并取消后, 串⼝号选择的ComboBox会消失不见,不知道原因,临时已解决2013-07-14:改进:程序内部改进内存分配算法,避免因程序错误造成内存泄漏2013-07-20 1.12:2013-09-10 1.13 今天教师节:增加:现在可以⼿动编写待发送的命令⽂件,并发送命令了 - 在发送⽂件时选择命令⽂件, 格式见博客后⾯的介绍增加:字符发送模式下,可以选择取消回车换⾏符的发送,可以选择插⼊转义字符 1.⽀持的字符型转义字符:\r,\n,\t,\v,\a,\b,\\2.⽀持的16进制转义字符格式:\x?? - 其中⼀个问号代表⼀个16进制字符, 不可省略其⼀,必需保证4个字符的格式3.'?',''','"', 等print-able字符不需要转义 ⼥孩不哭 @ 2012-12-27 14:47:59 @。
串口调试助手源程序及编程详细过程
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.GetLength();
senddata.SetSize(len/2);
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
for(k=0;k<len;k++) //将数组转换为Cstring型变量
3.利用ClassWizard定义CMSComm类控制对象 打开ClassWizard->Member Viariables选项卡,选择CSCommTestDlg类,为IDC_MSCOMM1添加控制变量:m_ctrlComm,这时你可以看一看,在对话框头文件中自动加入了//{{AFX_INCLUDES() #include "mscomm.h" //}}AFX_INCLUDES (这时运行程序,如果有错,那就再从头开始)。
{ ////////以下你可以根据自己的通信协议加入处理代码
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
}运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一端的串口调试助手(或别的调试工具)接收框里出现了什么。如果你真是初次涉猎串口编程,又一次成功,那该说声谢谢我了,因为我第一次做串口程序时可费劲了,那时网上的资料也不好找。开开玩笑,谢谢你的支持,有什么好东西别忘了给我寄一份。最后说明一下,由于用到VC控件,在没有安装VC的计算机上运行时要从VC中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到Windows目录下的System子目录中(win2000为System32)龚建伟 2001.6.20
串口通信(232、485、422)常见问题及解决
串⼝通信(232、485、422)常见问题及解决对于串⼝,理想的情况下,⼀般只要⼀上电,不需要太多的操作和配置,就可以通信上。
但是现实不会那么美好,总会出现各种各样的问题,这⾥并不对串⼝的编程作讲解,主要是从应⽤的⾓度去讲⼀讲碰到的⼀些问题。
ARM嵌⼊式,提供开发板、主板、核⼼板等ARM硬件产品和解决⽅案。
1、电脑使⽤USB转串⼝可以和设备通信上,换成屏与设备就通信不上了:①有可能电脑USB转串⼝接到设备上,使⽤的是标准串⼝功能,也就是除了RX,TX,GDN外,还使⽤了其它引脚。
⽐如像欧姆龙PLC,三菱PLC,在实际与屏的通信中,就需要接某些引脚短接的情况。
②电脑与控制器或PLC通信时,是扫描波特率参数,⾃适应的,屏通信可能参数没有设备好。
在三菱,基恩⼠等PLC,就存在变化波特率进⾏通信交互的过程。
③也有可能是接线⽅式不对。
因为有些DB9,还需要公头,母头。
如果不注意的话,也会存在把TX接到TX上,把RX接到RX上,这样需要注意的地⽅。
④在这⾥补充⼀下,有时候可能会使⽤⼀些串⼝助⼿发送测试数据与控制器通信,有些串⼝助⼿的奇偶校验是不起作⽤,这个要提醒⼀下。
2、在A家的屏可以和设备通信,换成B家的屏就通信不上了:①⾸先确认⼀下接线是否正确了,RX和TX是否兼容。
②地线是否没有接。
③除了RX,TX,GND,是否还有其它引脚需要短接的。
④通信协议是否⼀致或不完善,波特率是否⼀样。
3、以前不接地线可以通信,换个设备为什么需要接地线了:这个问题和上⼀个有类似的。
因为有些设备使⽤了隔离电源。
以前不接地可以通信,有可能是地线已经在另外⼀个环路已经共地了,实际地线已经接了,所以才可以通信。
可能换了个带隔离电源的,两个设备的地是隔离的,就需要在串⼝上把地线接起来。
这个我是⾃⾝经历过的,有个客户⽼说他的设备通信不上,后来拍个照我给我,他地线没有接,他说以前不接地线可以通信的。
于是我就给他科普了⼀下。
4、⼀个设备是232,另⼀个设备是422,没有转换设备,怎么办(232与422互转的简单⽅法);这个情况我遇到过,客户的设备是422通信的,但是我⼿上并没有422设备,只有232通信可以测试。
串口调试助手源码
串口调试助手程序框架(一)【截图】【源码】main.cpp#include<windows.h>#include<commctrl.h>#include<iostream>#include<stdio.h>#include"resource.h"using namespace std;HINSTANCE hInst;//窗口实例HWND hRDCLEAR, hSDCLEAR;HMENU hRDCHAR;void Init(HWND hwndDlg){SetWindowText(GetDlgItem(hwndDlg, SETXONC), "0x13");SetWindowText(GetDlgItem(hwndDlg, SETXOFFC), "0x19");SetWindowText(GetDlgItem(hwndDlg, SETTO), "0");SendDlgItemMessage(hwndDlg, RDCHAR, BM_SETCHECK, 1, 0);//把RadioBox RDCHAR设置为选中SendDlgItemMessage(hwndDlg, SDCHAR, BM_SETCHECK, 1, 0);//默认发送字符SendDlgItemMessage(hwndDlg, CTASY, BM_SETCHECK, 1, 0);//默认异步通信//在一个groupbox中必须有一个radiobox的属性:组为真//串口号SetWindowText(GetDlgItem(hwndDlg, SETCOMNO), "COM4");//默认值SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM1"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM2"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM3"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM4"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM5"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM6"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM7"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM8"));SendDlgItemMessage(hwndDlg, SETCOMNO, CB_ADDSTRING, 0, (LPARAM)("COM9"));//波特率SetWindowText(GetDlgItem(hwndDlg, SETBR), "9600");//默认值SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("1200"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("2400"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("4800"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("9600"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("14400"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("28800"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("38400"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("57600"));SendDlgItemMessage(hwndDlg, SETBR, CB_ADDSTRING, 0, (LPARAM)("115200"));//数据位SetWindowText(GetDlgItem(hwndDlg, SETBS), "8");//默认值SendDlgItemMessage(hwndDlg, SETBS, CB_ADDSTRING, 0, (LPARAM)("4"));SendDlgItemMessage(hwndDlg, SETBS, CB_ADDSTRING, 0, (LPARAM)("5"));SendDlgItemMessage(hwndDlg, SETBS, CB_ADDSTRING, 0, (LPARAM)("6"));SendDlgItemMessage(hwndDlg, SETBS, CB_ADDSTRING, 0, (LPARAM)("7"));SendDlgItemMessage(hwndDlg, SETBS, CB_ADDSTRING, 0, (LPARAM)("8"));//校验位SetWindowText(GetDlgItem(hwndDlg, SETPAR), "N");//默认值SendDlgItemMessage(hwndDlg, SETPAR, CB_ADDSTRING, 0, (LPARAM)("N"));SendDlgItemMessage(hwndDlg, SETPAR, CB_ADDSTRING, 0, (LPARAM)("odd"));SendDlgItemMessage(hwndDlg, SETPAR, CB_ADDSTRING, 0, (LPARAM)("even"));//停止位SetWindowText(GetDlgItem(hwndDlg, SETSB), "1");//默认值SendDlgItemMessage(hwndDlg, SETSB, CB_ADDSTRING, 0, (LPARAM)("1"));SendDlgItemMessage(hwndDlg, SETSB, CB_ADDSTRING, 0, (LPARAM)("2"));}BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {//窗口回调函数switch (uMsg)//消息处理{case WM_INITDIALOG://初始化{Init(hwndDlg);}return TRUE;case WM_CLOSE://关闭窗口{EndDialog(hwndDlg, 0);}return TRUE;case WM_COMMAND://菜单消息{switch (LOWORD(wParam)){case RDCLEAR://清空接收框数据{SetWindowText(hRDCLEAR, "");}return TRUE;case SDCLEAR://清空发送框数据{SetWindowText(GetDlgItem(hwndDlg, SDTEXT), "");}return TRUE;case SDSEND://发送数据{TCHAR szBuf[80];//缓存区string temp;GetWindowText(GetDlgItem(hwndDlg, SDTEXT), szBuf, 80);//获得接收框的文本temp = szBuf;//拼接字符串//cout<<temp;SetWindowText(GetDlgItem(hwndDlg, RDTEXT), temp.c_str());}return TRUE;case SETOP:{//打开串口}return TRUE;case SETCP:{//关闭串口}return TRUE;case SETSO:{}return TRUE;}}return TRUE;}return FALSE;}int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {hInst = hInstance;InitCommonControls();return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);}【源码】resource.h#ifndef IDC_STATIC#define IDC_STATIC (-1)#endif#define DLG_MAIN 100#define RDBOX 40000#define RDTEXT 40001#define RDCHAR 40002#define RDHEX 40003#define RDCLEAR 40004#define SDCHAR 40005#define SDHEX 40006#define SDCLEAR 40007#define SDSEND 40008#define SDAS 40009#define SDASTIME 40010#define SETCOMNO 40011#define CTSYN 40012#define CTASY 40013#define SETBR 40014#define SDTEXT 40015#define SETXONC 40016#define SETXOFFC 40017#define SETTO 40018#define SETPAR 40019#define SETSB 40020#define SETBS 40021#define SETOP 40022#define SETCP 40023#define SETSO 40024【源码】resource.rc#include<windows.h>#include<commctrl.h>#include<richedit.h>#include"resource.h"//// Dialog resources//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRALDLG_MAIN DIALOG 0, 0, 635, 304STYLE DS_3DLOOK| DS_CENTER| DS_MODALFRAME| DS_SHELLFONT| WS_CAPTION| WS_VISIBLE| WS_POPUP| WS_SYSMENU CAPTION "SerialPortDebug"FONT 8, "Ms Shell Dlg"{GROUPBOX "Setting", 0, 257, 7, 365, 290, 0, WS_EX_LEFTLTEXT "Select Port", 0, 284, 30, 36, 8, SS_LEFT, WS_EX_LEFTGROUPBOX "Communication Type", 0, 278, 62, 295, 35, 0, WS_EX_LEFTLTEXT "ByteSize", 0, 469, 120, 28, 8, SS_LEFT, WS_EX_LEFTLTEXT "BaudRate", 0, 297, 122, 33, 8, SS_LEFT, WS_EX_LEFTGROUPBOX "Send Data", 0, 12, 135, 240, 162, 0, WS_EX_LEFTLTEXT "StopBits", 0, 471, 161, 27, 8, SS_LEFT, WS_EX_LEFTLTEXT "Parity", 0, 299, 162, 18, 8, SS_LEFT, WS_EX_LEFTAUTOCHECKBOX "fParity", 0, 401, 162, 35, 8, 0, WS_EX_LEFTAUTOCHECKBOX "CTS", 0, 296, 202, 30, 8, 0, WS_EX_LEFTAUTOCHECKBOX "DSR", 0, 365, 202, 31, 8, 0, WS_EX_LEFTAUTOCHECKBOX "DTR", 0, 436, 202, 31, 8, 0, WS_EX_LEFTAUTOCHECKBOX "XON/XOFF", 0, 507, 202, 53, 8, 0, WS_EX_LEFTLTEXT "ms", 0, 131, 228, 10, 8, SS_LEFT, WS_EX_LEFTLTEXT "ms", 0, 562, 237, 10, 8, SS_LEFT, WS_EX_LEFTLTEXT "XonChar", 0, 293, 238, 28, 8, SS_LEFT, WS_EX_LEFTLTEXT "XoffChar", 0, 383, 238, 28, 8, SS_LEFT, WS_EX_LEFTLTEXT "Timeouts", 0, 478, 238, 30, 8, SS_LEFT, WS_EX_LEFTGROUPBOX "Receive Data", RDBOX, 15, 10, 235, 120, 0, WS_EX_LEFTEDITTEXT RDTEXT, 20, 25, 225, 75, ES_AUTOHSCROLL | ES_MULTILINE | ES_READONLY, WS_EX_LEFTAUTORADIOBUTTON "Char", RDCHAR, 26, 112, 31, 8, WS_GROUP, WS_EX_LEFTAUTORADIOBUTTON "Hex", RDHEX, 80, 112, 29, 8, 0, WS_EX_LEFTPUSHBUTTON "Clear", RDCLEAR, 196, 108, 45, 14, 0, WS_EX_LEFTAUTORADIOBUTTON "Char", SDCHAR, 26, 208, 31, 8, WS_GROUP, WS_EX_LEFTAUTORADIOBUTTON "Hex", SDHEX, 82, 208, 29, 8, 0, WS_EX_LEFTPUSHBUTTON "Clear", SDCLEAR, 132, 204, 45, 14, 0, WS_EX_LEFTPUSHBUTTON "Send", SDSEND, 196, 204, 45, 14, 0, WS_EX_LEFTAUTOCHECKBOX "Auto send", SDAS, 26, 228, 48, 8, 0, WS_EX_LEFTEDITTEXT SDASTIME, 86, 225, 40, 14, ES_RIGHT | ES_AUTOHSCROLL, WS_EX_LEFTCOMBOBOX SETCOMNO, 337, 27, 95, 30, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFTAUTORADIOBUTTON "Synchronous ", CTSYN, 326, 75, 59, 8, WS_GROUP, WS_EX_LEFTAUTORADIOBUTTON "Asynchronous ", CTASY, 472, 77, 63, 8, 0, WS_EX_LEFTCOMBOBOX SETBR, 337, 120, 48, 30, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFTEDITTEXT SDTEXT, 20, 147, 227, 45, ES_AUTOHSCROLL, WS_EX_LEFTEDITTEXT SETXONC, 325, 235, 40, 14, ES_AUTOHSCROLL, WS_EX_LEFTEDITTEXT SETXOFFC, 417, 235, 40, 14, ES_AUTOHSCROLL, WS_EX_LEFTEDITTEXT SETTO, 512, 235, 40, 14, ES_AUTOHSCROLL, WS_EX_RIGHTCOMBOBOX SETPAR, 338, 160, 48, 30, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFTCOMBOBOX SETSB, 512, 159, 48, 30, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFTCOMBOBOX SETBS, 512, 117, 48, 30, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFTPUSHBUTTON "Open Port", SETOP, 297, 272, 45, 14, 0, WS_EX_LEFTPUSHBUTTON "Close Port", SETCP, 387, 272, 45, 14, 0, WS_EX_LEFTDEFPUSHBUTTON "Stop I/O", SETSO, 473, 271, 45, 14, 0, WS_EX_LEFT}//// Manifest resources//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL1 RT_MANIFEST".\\manifest.xml"【源码】manifest.xml< ? xml version = "1.0" encoding = "UTF-8" standalone = "yes" ? ><assembly xmlns = "urn:schemas-microsoft-com:asm.v1" manifestVersion = "1.0"><dependency><dependentAssembly><assemblyIdentity type = "win32" name = "mon-Controls" version = "6.0.0.0" processorArchitecture = "*" publicKeyToken = "6595b64144ccf1df" language = "*" / >< / dependentAssembly>< / dependency><trustInfo xmlns = "urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level = "asInvoker" uiAccess = "false" / > < / requestedPrivileges> < / security>< / trustInfo>< / assembly>。
串口调试助手源代码
串口调试助手预源代码using System;using System.Collect ion s.Ge neric;using p onen tModel;using System.Data;using System.Draw ing;using System.Linq;using System.Text;using System.Thread in g.Tasks;using System.Wi ndows.Forms;using Syste m.IO;using Syste m.IO .Ports;using System.Thread ing;using DevExpress.XtraEditors;using System.Text.RegularExpressi ons;n amespace Win dowsFormsApplicatio n3 {public partial class Form1 : XtraForm {SerialPort sp1 = new SerialPort(); int Flag = 0;int StateCha nged = 0;int StateCha nged_Ascii = 1; int StateCha nged_16 = 0;string Temp = null;stri ng Temp_memoSe nd = n ull;private void memoSe nd_EditValueCha nged(object sen der, Even tArgs e) { - }public Form1(){In itializeComp onen t();sp1.DataReceived += sp1_DataReceived; }private void Form1_Load(object sen der, Even tArgs e) { -this.MaximizeBox = false;// 检查是否有串口stri ng[] str = SerialPort.GetPortNames();if (str == null) __________ |{MessageBox.Show(”本机没有串口!", "error");return;}// 添加串口项目foreach (stri ng port in Syste m.IO.P orts.SerialPort.GetPortNames()) { cbSerial.Properties .I tems.Add(port);}// 串口设置默认选择项cbSerial.Selectedl ndex = 0;Con trol.CheckForlllegalCrossThreadCalls = false; spl.DataReceived += new SerialDataReceivedEve ntHa ndler(sp1_DataReceived); //订阅委托e)//SerialPort sp1 = new SerialPort();if (!sp1.lsOpe n)〃串口是关闭的,设置参数,打开串口{try{// 获取串口号string serialName = cbSerial.Selectedltem.ToString(); sp1.PortName = serialName;// 设置各参数stri ng strBaudRate = cbBaudRate.Text;string strDateBits = cbDataBits.Text;string strStopBits = cbStop.Text;sp1.BaudRate = Con vert.ToI nt32(strBaudRate);〃波特率sp1.DataBits = Con vert.ToI nt32(strDateBi ts);// 数据位switch (cbStop.Text) // 停止位{case "1":sp1.StopBits = StopBits. On e;break;case "1.5":sp1.StopBits = StopBits. On e;break;case "2":sp1.StopBits = StopBits.Two;break; default:case " 奇校验":sp1.Parity = Parity.Odd; break;精品文档", "Error");case "偶校验":spl.Parity = Parity.Eve n; break; default:MessageBox.Show("Error: 参数不正确!break;labSerial.Text =" 串口号:” + sp1 .P ortName; labState.Text ="状 态:打开";}catch (System.Excepti on ex) {MessageBox.Show("Error:" + ex.Message, "Error"); return; } } }//private void CloseSerial_Click(object sen der, Even tArgs e) 〃{// if (sp1.lsOpe n) // { // sp1.Close(); // labSerial.Text =" 串口号:” + sp1.PortName; // labState.Text ="状 态:关闭";// } 〃}private void Sen d_Click(object sen der, Even tArgs e) { - stri ng StrSe nd = memoSe nd.Text; if (!sp1.lsOpe n) {MessageBox.Show (” 请先打开串口! ", "Error");return; } else {if (rbt nSen dStr.Checked)//〃bt nOpe n.En abled =false; 字符串发送{if (ckTimeSe nd.Checked&& !(stri ng.lsNullOrEmpty(textTime.Text)))//判断是否定时发送数据{string Time = textTime.Text;tmSe nd.l nterval = int. Parse(Time) * 1000;//时间单位是秒,化成毫秒单位后的空格//stri ng StrSe nd_2 = StrSe nd_1.Replace (” ", ""); //stri ng StrSe nd_3 = stri ng.J oi n (” ",Regex.Matches(StrSend_2, @"..|.").Cast<Match>().ToList());stri ng[] StrArray = StrSe nd_1.Split(' '); // 用空格符隔开字符串数组var Str_Se nd = new List<stri ng>();// i nt byteBufferLe ngth = StrArray.Le ngth; 数组StrArray 的长度for (int i = 0; i < StrArray.Le ngth; i++){if (StrArray[i].Trim()=="") {//byteBufferLe ngth--; con ti nue; }else} else //{if (ckTimeSe nd.Checked&& !(string.IsNullOrEmpty(textTime.Text))){卜六进制发送//tmSe nd.Start();//开启定时器{if (StrArray[i].Le ngth < 3){Str_Se nd.Add(StrArray[i]);}else{Str_Se nd.AddRa nge(Devide(StrArray[i]));}}}int byteBufferLe ngth = Str_Se nd.Cou nt; byte[] byteBuffer = new byte[byteBufferLe ngth];in t ii = 0;//decNum = Con vert.ToI nt32(Str_Se nd[i], 16); // 把字符串转成16进制数〃byteBuffer[ii] = Co nvert.ToByte(decNum);〃}try{decNum = Con vert.ToI nt32(Str_Se nd[i], 16); // 把字符串转成16进制数byteBuffer[ii] = Co nvert.ToByte(decNum);}catch (System.Exceptio n ex){MessageBox.Show(”输入错误!","提示");return;}ii++;}sp1.Write(byteBuffer, 0, byteBuffer.Length);// 从第0个开始写入byteBuffer ,长度bytebuffer 的长度。
经典串口调试助手源程序及串口通信设置
经典串口调试助手源程序及串口通信设置串口调试助手是一种用于串口通信调试的工具,它可以通过串口与外部设备进行数据的读写和处理,常用于单片机、嵌入式系统、电子设备等领域的开发调试中。
经典串口调试助手源程序经典串口调试助手是一款经典的串口调试工具,其源程序使用C语言编写,提供了丰富的功能和易于使用的界面,被广泛应用于各种领域的开发调试中。
该工具可以在Windows操作系统中运行,并支持多种串口通信协议,包括RS232、RS485、RS422等。
以下是经典串口调试助手部分源程序的示例:```c// 打开串口HANDLE OpenSerialPort(const char* portName){ HANDLE hCom; hCom = CreateFile(portName, // 串口名称GENERIC_READ | GENERIC_WRITE, // 读写访问0,// 无共享NULL,// 安全描述符OPEN_EXISTING,// 打开方式FILE_ATTRIBUTE_NORMAL, // 文件属性NULL); // 文件模板if (hCom ==INVALID_HANDLE_VALUE) // 判断是否打开成功{ return NULL; } return hCom;}// 发送数据int SendData(HANDLE hCom, const char* data, int len){ DWORD writeSize; if (!WriteFile(hCom, data, len, &writeSize, NULL)) // 写入数据{ return -1; } return writeSize;}// 接收数据int ReceiveData(HANDLE hCom, char* data, int len){ DWORD readSize; if (!ReadFile(hCom, data, len,&readSize, NULL)) // 读取数据{ return -1; } return readSize;}// 关闭串口int CloseSerialPort(HANDLE hCom){ if(!CloseHandle(hCom)) // 关闭句柄{ return-1; } return 0;}```上述函数实现了打开串口、发送数据、接收数据和关闭串口等基本功能,可以作为串口通信的底层驱动实现。
Comassistant串口助手详解和源代码分析
到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行程序不应该有任何错误, 不然,你肯定哪儿没看仔细,因为我是打开 VC6 对照着做一步写一行的,运行试试。没错吧?那么做下一 步: 6.打开串口和设置串口参数 码: // TODO: Add extra initialization here if(m_ctrlComm.GetPortOpen()) m_ctrlComm.SetPortOpen(FALSE); m_ctrlComm.SetCommPort(1); //选择 com1 if( !m_ctrlComm.GetPortOpen()) m_ctrlComm.SetPortOpen(TRUE);//打开串口 else AfxMessageBox("cannot open serial port"); m_ctrlComm.SetSettings("9600,n,8,1"); //波特率 9600,无校验,8 个数据位,1 个停止位 m_ctrlComm.SetInputModel(1); //1:表示以二进制方式检取数据 m_ctrlComm.SetRThreshold(1); //参数 1 表示每当串口接收缓冲区中有多于或等于 1 个字符时将引发一个接收数据的 OnComm 事件 m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为 0 m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据 现在你可以试试程序了,将串口线接好后(不会接?去看看我写的串口接线基本方法),打开串口调试助 手,并将串口设在 com2,选上自动发送,也可以等会手动发送。再执行你编写的程序,接收框里应该有数 据显示了。 7.发送数据 先为发送按钮添加一个单击消息即 BN_CLICKED 处理函数,打开 ClassWizard->Message 你可以在你需要的时候打开串口, 例如在程序中做一个开始按钮, 在该按钮
C语言串口通信助手代码
该程序全部由C写成没有C++更没用MFC完全是自娱自乐给需要的人一个参考#include "stdafx.h"#include <windowsx.h>#include "resource.h"#include "MainDlg.h"#include <windows.h>#include <stdio.h>#include <stdlib.h>HANDLE hComm;//用于获取串口打开函数的返回值(句柄或错误值)OVERLAPPED m_ov;COMSTAT comstat;DWORD m_dwCommEvents;TCHAR cRecs[200],cSends[100]; //接收字符串发送字符串char j=0,*cCom; //接收用统计数据大小变量端口选择BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam){switch(uMsg){HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose);}return FALSE;}/*系统初始化函数*/BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAMlParam){HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1);ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM3"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM4"));ComboBox_InsertString(hwndCombo1,-1,TEXT("COM5"));ComboBox_SetCurSel(hwndCombo1,0);void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime);SetTimer(hwnd,1,1000,TimerProc);return TRUE;}/*监视串口错误时使用的函数*/boolProcessErrorMessage(char* ErrorText){char *Temp = new char[200];LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Defaultlanguage (LPTSTR) &lpMsgBuf,0,NULL);sprintf(Temp, "WARNING: %s Failed with the following error:\n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, "com2"); MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP); LocalFree(lpMsgBuf);delete[] Temp;return true;}boolopenport(char *portname)//打开串口{hComm = CreateFile(portname, //串口号“com1”“com2”调用方法:bool open;open=openport("com2");GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE) //如果被占用或是没有打开时返回的是这个错误代码{CloseHandle(hComm);return FALSE;}elsereturn true;}boolsetupdcb(intrate_arg)//设置port的属性{DCB dcb;int rate= rate_arg;memset(&dcb,0,sizeof(dcb));if(!GetCommState(hComm,&dcb))//获取当前DCB配置return FALSE;// set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);dcb.BaudRate = rate;dcb.Parity = NOPARITY; //奇偶校验值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零dcb.fParity = 0; //为1的话激活奇偶校验检查dcb.StopBits = ONESTOPBIT;//停止位个数,0~2分别对应1位、1.5位、2位停止位dcb.ByteSize = 8; //数据位数dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLim = 2;dcb.XoffLim = 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;// set DCBif(!SetCommState(hComm,&dcb))return false;elsereturn true;}/*串口读取相关时间设置*/boolsetuptimeout(DWORDReadInterval,DWORDReadTotalMultiplier,DWORDReadTotalconstant,DWORDW riteTotalMultiplier,DWORDWriteTotalconstant){COMMTIMEOUTS timeouts;timeouts.ReadIntervalTimeout=ReadInterval; //读取两个字节间隔最大值mS 如超过立即返回不再读取timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //如果同下面一个都为0则无论是否读到数据都返回//可以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; //以毫秒为单位指定一个常数,用于计算读操作的总限时时间0表示不限时timeouts.WriteTotalTimeoutConstant=WriteTotalconstant;//写操作延时同上timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier;if(!SetCommTimeouts(hComm, &timeouts))return false;elsereturn true;}intClearn() //清除buff中的内容并返回buff中现有数据量的大小并读取错误原因{DWORD dwError = 0;DWORD BytesRead = 0;ClearCommError(hComm, &dwError, &comstat);return comstat.cbInQue; //返回buff中数据量}/*串口数据接收读取函数*/void ReceiveChar(){BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char i=0,n;char RXBuff;j=0;while (i-n){n=i;Sleep(10);bResult = ClearCommError(hComm, &dwError, &comstat); i=(char)comstat.cbInQue;}for (;i>0;i--){if (bRead)bResult = ReadFile(hComm, // Handle to COMM port&RXBuff, // RX Buffer Pointer1, // Read one byte&BytesRead, // Stores number of bytes read&m_ov); // pointer to the m_ov structure// printf("%c",RXBuff);cRecs[j++]=(char)RXBuff;if (!bResult){switch (dwError = GetLastError()){case ERROR_IO_PENDING:{bRead = FALSE;break;}default: break;}}elsebRead = TRUE; // close if (bRead)if (!bRead){bRead = TRUE;bResult = GetOverlappedResult(hComm, // Handle to COMM port&m_ov, // Overlapped structure&BytesRead, // Stores number of bytes readTRUE); // Wait flag}}}boolWriteChar(char* m_szWriteBuffer,DWORDm_nToSend) //写字符的函数{BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;HANDLE m_hWriteEvent;ResetEvent(m_hWriteEvent);if (bWrite){m_ov.Offset = 0;m_ov.OffsetHigh = 0;// Clear bufferbResult = WriteFile(hComm, // Handle to COMM Portm_szWriteBuffer, // Pointer to message buffer in calling finctionm_nToSend, // Length of message to send&BytesSent, // Where to store the number of bytes sent&m_ov ); // Overlapped structureif (!bResult){DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:// all other error codesbreak;}}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = GetOverlappedResult(hComm, // Handle to COMM port&m_ov, // Overlapped structure&BytesSent, // Stores number of bytes sentTRUE); // Wait flag// deal with the error codeif (!bResult){printf("GetOverlappedResults() in WriteFile()");}} // end if (!bWrite)// Verify that the data size send equals what we tried to sendif (BytesSent != m_nToSend){printf("WARNING: WriteFile() error.. Bytes Sent: %d; MessageLength: %d\n", BytesSent, strlen((char*)m_szWriteBuffer));}return true;}/*window时间函数回调*/void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime){SYSTEMTIME time; //定义机构体变量timeGetLocalTime(&time); //取系统时间以指针方式TCHAR strTime[256]; //程序只有一个作用wsprintf(strTime,"%04d-%02d-%02d %02d:%02d:%02d",time.wYear, //就是读取系统时间time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond);//然后写进strTimeSetDlgItemText(hwnd,IDC_TIME,strTime); //这个字符串}void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINTcodeNotify) {switch(id){case IDC_SEND:{GetDlgItemText (hwnd,IDC_EDIT2,cSends,sizeof(cSends));unsigned n=sizeof(cSends); //n是通知串口将发送字节的长度char send[100];wsprintf (send,"%s",cSends);WriteChar(send,n-1);SetCommMask(hComm, EV_RXCHAR); //监视串口是否接收有数据ReceiveChar(); //读取串口sbuff中数据cRecs[j]='\0'; //将cRecs转为字符串SetDlgItemText(hwnd,IDC_EDIT1,cRecs);} break;/*case IDC_RECEIVE: //暂时未用采用直接显示的方式{}break;*/case IDC_CHECK:{intctr;HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1); ctr = ComboBox_GetCurSel(hwndCombo1);switch (ctr){case 0:cCom="com1";break;case 1:cCom="com2";break;case 2:cCom="com3";break;case 3:cCom="com4";break;case 4:cCom="com5";break;default: cCom="com1";break;}if (openport(cCom)){ SetDlgItemText(hwnd,IDC_EDIT3,"OK !");MessageBox(hwnd,"串口打开成功!","",0); }elseSetDlgItemText(hwnd,IDC_EDIT3,"FAIL");if(setupdcb(9600)&&setuptimeout(1024,0,0,20,1000)) //初始化串口属性波特率9600SetDlgItemText(hwnd,IDC_EDIT4,"串口属性设置成功");elseSetDlgItemText(hwnd,IDC_EDIT4,"串口初始化失败!");PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR |PURGE_RXABORT | PURGE_TXABORT);}default:break;}}void Main_OnClose(HWND hwnd){EndDialog(hwnd, 0);}。
c上位机串口通信助手源代码详解
For personal use only in study andresearch; not for commercial usec#上位机串口通信助手源代码实例详解一、功能1软件打开时,自动检测有效COM端口2 软件打开时,自动复原到上次关闭时的状态3 不必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位),可按更改后的信息自动将串口重新打开4 可统计接收字节和发送字节的个数5 接收数据可按16进制数据和非16进制数据进行整体转换6 可将接收到数据进行保存7 可设置自动发送,发送时间可进行实时更改8可按字符串、16进制字节、文件方式进行发送,字符串和16进制字节可分别进行存储,内容互不干扰9 按16进制发送时,可自动校验格式,不会输错10 可清空发送或接收区域的数据二、使用工具Visual Studio2015三、程序详解1 界面创建图1用winform创建如图1所示界面,控件名字分别为:端口号:cbxCOMPort 波特率:cbxBaudRate数据位:cbxDataBits 停止位:cbxStopBits校验位:label5 打开串口按钮:btnOpenCom发送(byte):tbSendCount 接收(byte):tbReceivedCount 清空计数按钮:btnClearCount 按16进制显示:cb16Display接收区清空内容按钮:btnClearReceived 保存数据按钮:btnSaveFile接收数据框:tbReceivedData 发送数据框:tbSendData自动发送:cbAutomaticSend 间隔时间:tbSpaceTime按16进制发送:cb16Send 发送区清空内容按钮:btnClearSend 读入文件按钮:btnReadFile 发送按钮:btnSend2 创建一个方法类按Ctrl+shift+A快捷键创建一个类,名字叫Methods,代码为:using System;using System.Collections;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading.Tasks;namespace串口助手sdd{class Methods{//获取有效的COM口public static string[] ActivePorts(){ArrayList activePorts = new ArrayList();foreach (string pname in SerialPort.GetPortNames()){activePorts.Add(Convert.ToInt32(pname.Substring(3)));}activePorts.Sort();string[] mystr = new string[activePorts.Count];int i = 0;foreach (int num in activePorts){mystr[i++] = "COM" + num.ToString();}return mystr;}//16进制字符串转换为byte字符数组public static Byte[] _16strToHex(string strValues){string[] hexValuesSplit = strValues.Split(' ');Byte[] hexValues = new Byte[hexValuesSplit.Length];Console.WriteLine(hexValuesSplit.Length);for (int i = 0; i < hexValuesSplit.Length; i++){hexValues[i] = Convert.ToByte(hexValuesSplit[i], 16);}return hexValues;}//byte数组以16进制形式转字符串public static string ByteTo16Str(byte[] bytes){string recData = null;//创建接收数据的字符串foreach (byte outByte in bytes)//将字节数组以16进制形式遍历到一个字符串内 {recData += outByte.ToString("X2") + " ";}return recData;}//16进制字符串转换字符串public static string _16strToStr(string _16str){string outStr = null;byte[] streamByte = _16strToHex(_16str);outStr = Encoding.Default.GetString(streamByte);return outStr;}}}2 Form1.cs的代码为:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.IO.Ports;using System.Linq;using System.Text;using System.Text.RegularExpressions;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.Collections;namespace串口助手sdd{public partial class Form1 : Form{//声明变量SerialPort sp = new SerialPort();bool isSetProperty = false;//串口属性设置标志位private enum PortState//声明接口显示状态,枚举型{打开,关闭}string path = AppDomain.CurrentDomain.BaseDirectory + "confing.ini";//声明配置文件路径string tbSendDataStr = "";//发送窗口字符串存储string tbSendData16 = "";//发送窗口16进制存储List<byte> receivedDatas = new List<byte>();//接收数据泛型数组//接收串口数据private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) {byte[] ReceivedData = new byte[sp.BytesToRead];//创建接收字节数组sp.Read(ReceivedData, 0, ReceivedData.Length);//读取所接收到的数据receivedDatas.AddRange(ReceivedData);tbReceivedCount.Text = (Convert.ToInt32(tbReceivedCount.Text) + ReceivedData.Length).ToString();if (cb16Display.Checked)tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray());elsetbReceivedData.Text =Encoding.Default.GetString(receivedDatas.ToArray());sp.DiscardInBuffer();//丢弃接收缓冲区数据}//发送串口数据private void DataSend(){try{if (cb16Send.Checked){byte[] hexBytes = Methods._16strToHex(tbSendData16);sp.Write(hexBytes, 0, hexBytes.Length);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + hexBytes.Length).ToString();}else{sp.WriteLine(tbSendDataStr);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + tbSendDataStr.Length).ToString();}}catch (Exception ex){MessageBox.Show(ex.Message.ToString());return;}}//设置串口属性private void SetPortProperty(){sp.PortName = cbxCOMPort.Text.Trim();//设置串口名sp.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim());//设置波特率switch (cbxStopBits.Text.Trim())//设置停止位{case"1": sp.StopBits = StopBits.One; break;case"1.5": sp.StopBits = StopBits.OnePointFive; break;case"2": sp.StopBits = StopBits.Two; break;default: sp.StopBits = StopBits.None; break;}sp.DataBits = Convert.ToInt32(cbxDataBits.Text.Trim());//设置数据位switch (cbxParity.Text.Trim())//设置奇偶校验位{case"无": sp.Parity = Parity.None; break;case"奇校验": sp.Parity = Parity.Odd; break;case"偶校验": sp.Parity = Parity.Even; break;default: sp.Parity = Parity.None; break;}sp.ReadTimeout = 5000;//设置超时时间为5sControl.CheckForIllegalCrossThreadCalls = false;//这个类中我们不检查跨线程的调用是否合法(因为.net 2.0以后加强了安全机制,,不允许在winform中直接跨线程访问控件的属性)//定义DataReceived事件的委托,当串口收到数据后出发事件sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);}//设置端口显示状态private void DisplayPortState(PortState portState){toolStripStatusLabel1.Text = cbxCOMPort.Text + "端口处于" + portState + "状态 " + cbxBaudRate.Text + " " + cbxDataBits.Text + " " + cbxStopBits.Text + " " + cbxParity.Text;}//重新打开串口private void AgainOpenPort(){if (sp.IsOpen){try{sp.Close();SetPortProperty();isSetProperty = true;sp.Open();}catch (Exception){isSetProperty = false;btnOpenCom.Text = "打开串口";DisplayPortState(PortState.关闭);MessageBox.Show("串口无效或已被占用!", "错误提示");return;}DisplayPortState(PortState.打开);}else{DisplayPortState(PortState.关闭);}}public Form1(){InitializeComponent();}//软件启动时加载事件private void Form1_Load(object sender, EventArgs e){#region加载配置文件Hashtable ht = new Hashtable();if (File.Exists(path)){try{string myline = "";string[] str = new string[2];using (StreamReader sr = new StreamReader(path)) {myline = sr.ReadLine();while (myline != null){str = myline.Split('=');ht.Add(str[0], str[1]);myline = sr.ReadLine();}}}catch(Exception ex){MessageBox.Show(ex.Message.ToString());}}#endregion#region设置窗口为固定大小且不可最大化this.MaximumSize = this.Size;this.MinimumSize = this.Size;this.MaximizeBox = false;#endregion#region列出常用的波特率cbxBaudRate.Items.Add("1200");cbxBaudRate.Items.Add("2400");cbxBaudRate.Items.Add("4800");cbxBaudRate.Items.Add("9600");cbxBaudRate.Items.Add("19200");cbxBaudRate.Items.Add("38400");cbxBaudRate.Items.Add("43000");cbxBaudRate.Items.Add("56000");cbxBaudRate.Items.Add("57600");cbxBaudRate.Items.Add("115200");if (ht.ContainsKey("cbxBaudRate"))cbxBaudRate.SelectedIndex =cbxBaudRate.Items.IndexOf(ht["cbxBaudRate"].ToString());elsecbxBaudRate.SelectedIndex = 3;cbxBaudRate.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出停止位cbxStopBits.Items.Add("1");cbxStopBits.Items.Add("1.5");cbxStopBits.Items.Add("2");if (ht.ContainsKey("cbxStopBits"))cbxStopBits.SelectedIndex =cbxStopBits.Items.IndexOf(ht["cbxStopBits"].ToString());elsecbxStopBits.SelectedIndex = 0;cbxStopBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出数据位cbxDataBits.Items.Add("8");cbxDataBits.Items.Add("7");cbxDataBits.Items.Add("6");cbxDataBits.Items.Add("5");if (ht.ContainsKey("cbxDataBits"))cbxDataBits.SelectedIndex =cbxDataBits.Items.IndexOf(ht["cbxDataBits"].ToString());elsecbxDataBits.SelectedIndex = 0;cbxDataBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region列出奇偶校验位cbxParity.Items.Add("无");cbxParity.Items.Add("奇校验");cbxParity.Items.Add("偶校验");if (ht.ContainsKey("cbxParity"))cbxParity.SelectedIndex =cbxParity.Items.IndexOf(ht["cbxParity"].ToString());elsecbxParity.SelectedIndex = 0;cbxParity.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region COM口重新加载cbxCOMPort.Items.Clear();//清除当前串口号中的所有串口名称 cbxCOMPort.Items.AddRange(Methods.ActivePorts());if (ht.ContainsKey("cbxCOMPort") &&cbxCOMPort.Items.Contains(ht["cbxCOMPort"].ToString()))cbxCOMPort.SelectedIndex =cbxCOMPort.Items.IndexOf(ht["cbxCOMPort"].ToString());elsecbxCOMPort.SelectedIndex = 0;cbxCOMPort.DropDownStyle = ComboBoxStyle.DropDownList; #endregion#region初始化计数器tbSendCount.Text = "0";tbSendCount.ReadOnly = true;tbReceivedCount.Text = "0";tbReceivedCount.ReadOnly = true;#endregion#region初始化当前时间toolStripStatusLabel3.Text = DateTime.Now.ToString();#endregion#region初始化串口状态toolStripStatusLabel1.ForeColor = Color.Blue;if (!isSetProperty)//串口未设置则设置串口属性{SetPortProperty();isSetProperty = true;}try{sp.Open();btnOpenCom.Text = "关闭串口";DisplayPortState(PortState.打开);}catch (Exception){//串口打开失败后,串口属性设置标志位设为falseisSetProperty = false;MessageBox.Show("串口无效或已被占用!", "错误提示"); }#endregion#region初始化间隔时间if (ht.ContainsKey("tbSpaceTime"))tbSpaceTime.Text = ht["tbSpaceTime"].ToString();elsetbSpaceTime.Text = "1000";#endregion#region初始化按16进制显示状态if (ht.ContainsKey("cb16Display") && ht["cb16Display"].ToString() == "True") cb16Display.Checked = true;elsecb16Display.Checked = false;#endregion#region初始化按16进制发送状态if (ht.ContainsKey("cb16Send") && ht["cb16Send"].ToString() == "True")cb16Send.Checked = true;elsecb16Send.Checked = false;#endregion#region初始化发送区文本if(ht.ContainsKey("tbSendData16") && ht.ContainsKey("tbSendDataStr")){tbSendData16 = ht["tbSendData16"].ToString();tbSendDataStr = ht["tbSendDataStr"].ToString();if (cb16Send.Checked)tbSendData.Text = ht["tbSendData16"].ToString();elsetbSendData.Text = ht["tbSendDataStr"].ToString();}#endregiontbSendData.Focus();}//显示当前时间private void timer1_Tick(object sender, EventArgs e){toolStripStatusLabel3.Text = DateTime.Now.ToString();}//点击打开串口按钮private void btnOpenCom_Click(object sender, EventArgs e){if (!sp.IsOpen)//串口没有打开时{if (!isSetProperty)//串口未设置则设置串口属性{SetPortProperty();isSetProperty = true;}try{sp.Open();btnOpenCom.Text = "关闭串口";DisplayPortState(PortState.打开);}catch (Exception){//串口打开失败后,串口属性设置标志位设为falseisSetProperty = false;MessageBox.Show("串口无效或已被占用!", "错误提示"); }}else//串口已经打开{try{sp.Close();isSetProperty = false;btnOpenCom.Text = "打开串口";DisplayPortState(PortState.关闭);}catch (Exception){MessageBox.Show("关闭串口时发生错误", "错误提示"); }}}//发送串口数据private void btnSend_Click(object sender, EventArgs e){if (tbSendData.Text.Trim() == "")//检测发送数据是否为空{MessageBox.Show("请输入要发送的数据!", "错误提示");return;}if (sp.IsOpen){DataSend();}else{MessageBox.Show("串口未打开!", "错误提示");}}//点击端口号选择下拉框按钮private void cbxCOMPort_SelectedIndexChanged(object sender, EventArgs e){AgainOpenPort();}//点击波特率选择下拉框按钮private void cbxBaudRate_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击数据位选择下拉框按钮private void cbxDataBits_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击停止位选择下拉框按钮private void cbxStopBits_SelectedIndexChanged(object sender, EventArgs e) {AgainOpenPort();}//点击校验位选择下拉框按钮private void cbxParity_SelectedIndexChanged(object sender, EventArgs e){AgainOpenPort();}//点击数据接收区清空按钮private void btnClearReceived_Click(object sender, EventArgs e){receivedDatas.Clear();tbReceivedData.Text = "";}//点击是否按16进制显示接收数据private void cb16Display_CheckedChanged(object sender, EventArgs e){if (cb16Display.Checked)tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray());elsetbReceivedData.Text =Encoding.Default.GetString(receivedDatas.ToArray());//点击是否按16进制发送数据private void cb16Send_CheckedChanged(object sender, EventArgs e){if (cb16Send.Checked){tbSendData.Text = tbSendData16;}else{tbSendData.Text = tbSendDataStr;}}//发送文本框键盘按键检测private void tbSendData_KeyPress(object sender, KeyPressEventArgs e){if (cb16Send.Checked){//正则匹配string pattern = "[0-9a-fA-F]|\b";//\b:退格键Match m = Regex.Match(e.KeyChar.ToString(), pattern);if (m.Success){if(e.KeyChar != '\b'){if (tbSendData.Text.Length % 3 == 2){tbSendData.Text += " ";tbSendData.SelectionStart = tbSendData.Text.Length;}e.KeyChar = Convert.ToChar(e.KeyChar.ToString().ToUpper()); }e.Handled = false;}else{e.Handled = true;}}else{e.Handled = false;}}//点击清空发送内容private void btnClearSend_Click(object sender, EventArgs e){tbSendData.Text = "";if (cb16Send.Checked)tbSendData16 = "";elsetbSendDataStr = "";//点击清空计数器数据private void btnClearCount_Click(object sender, EventArgs e){tbReceivedCount.Text = "0";tbSendCount.Text = "0";}//点击是否设置自动发送private void cbAutomaticSend_CheckedChanged(object sender, EventArgs e) {if (cbAutomaticSend.Checked){timer2.Enabled = true;timer2.Interval = Convert.ToInt32(tbSpaceTime.Text);}else{timer2.Enabled = false;}}//自动发送时间文本框键盘按键检测private void tbSpaceTime_KeyPress(object sender, KeyPressEventArgs e) {//正则匹配string pattern = "[0-9]|\b";Match m = Regex.Match(e.KeyChar.ToString(),pattern);if (m.Success){timer2.Interval = Convert.ToInt32(tbSpaceTime.Text);e.Handled = false;}else{e.Handled = true;}}//串口显示状态private void timer2_Tick(object sender, EventArgs e){if (sp.IsOpen){DataSend();}else{timer2.Enabled = false;cbAutomaticSend.Checked = false;MessageBox.Show("串口未打开!", "错误提示");return;}if (tbSendData.Text.Trim() == "")//检测发送数据是否为空{timer2.Enabled = false;cbAutomaticSend.Checked = false;MessageBox.Show("请输入要发送的数据!", "错误提示");return;}}//关闭窗口时出发的事件private void Form1_FormClosed(object sender, FormClosedEventArgs e){try{using (StreamWriter sw = new StreamWriter(path, false)){sw.WriteLine("cbxCOMPort=" + cbxCOMPort.Text);sw.WriteLine("cbxBaudRate=" + cbxBaudRate.Text);sw.WriteLine("cbxDataBits=" + cbxDataBits.Text);sw.WriteLine("cbxStopBits=" + cbxStopBits.Text);sw.WriteLine("cbxParity=" + cbxParity.Text);sw.WriteLine("cb16Display="+ cb16Display.Checked.ToString()); sw.WriteLine("tbSpaceTime=" + tbSpaceTime.Text);sw.WriteLine("cb16Send=" + cb16Send.Checked.ToString());sw.WriteLine("tbSendDataStr=" + tbSendDataStr);sw.WriteLine("tbSendData16=" + tbSendData16);sp.Close();}}catch(Exception ex){MessageBox.Show(ex.Message.ToString());}}//发送文本框按键抬起时出发的事件private void tbSendData_KeyUp(object sender, KeyEventArgs e){if (cb16Send.Checked){tbSendData16 = tbSendData.Text.Trim();}else{tbSendDataStr = tbSendData.Text;}}//点击读入文件按钮private void btnReadFile_Click(object sender, EventArgs e){openFileDialog1.Filter = "所有文件(*.*)|*.*";//文件筛选器的设定openFileDialog1.FilterIndex = 1;openFileDialog1.Title = "选择文件";openFileDialog1.FileName = "";openFileDialog1.ShowHelp = true;if(openFileDialog1.ShowDialog() == DialogResult.OK){using (FileStream fs = newFileStream(openFileDialog1.FileName,FileMode.Open)){byte[] bufferByte = new byte[fs.Length];fs.Read(bufferByte, 0, Convert.ToInt32(fs.Length));sp.Write(bufferByte, 0, bufferByte.Length);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + bufferByte.Length).ToString();}}}//点击保存数据按钮private void btnSaveFile_Click(object sender, EventArgs e){saveFileDialog1.Filter = "所有文件(*.*)|*.*";if(saveFileDialog1.ShowDialog() == DialogResult.OK){string fName = saveFileDialog1.FileName;using(FileStream fs = File.Open(fName, FileMode.Append)){fs.Write(receivedDatas.ToArray(), 0, receivedDatas.Count);}}}}}需要源代码或有疑问的c#爱好者们,欢迎加入c#技术交流群(33647125),附加信息为”我以下载此文档”,进群后找群主索要源代码或进行技术交流。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第5章串口调试助手代码分析1、建立基于对话框的工程SCOMM2、绘制界面,如下图:接收区串口组合框:IDC_COMBO_COMSELECT,m_Com波特率组合框:IDC_COMBO_SPEED,m_Speed停止位组合框:IDC_COMBO_STOPBITS,m_StopBits数据位组合框:IDC_COMBO_DATABITS,m_DataBits校验位组合框:IDC_COMBO_PARITY,m_Parity十六进制显示(接收):IDC_CHECK_HEXRECIEVE,m_ctrlHexReceieve接收编辑框:IDC_EDIT_RECIVE ,m_ReceiveData m_ctrlReceiveData Style:Vertical Scroll MultiLine打开串口IDC_BUTTON_OPENPORT,m_ctrlOpenPort串口开关标志图标IDC _STATIC_OPENOFF,m_ctrlIconOpenoff数据文件保存路径IDC _EDIT_SA VEPATH,m_strCurPath保存显示数据文件路径IDC _EDIT_SA VEPATH, m_ctrlSavePath接收计数IDC_STATIC_RXCOUNT ,m_ctrlRXCOUNT发送区…。
3、添加CSeraiPort类文件将类文件SerialPort.h SerialPort.cpp 复制到工程所在文件夹中(选择改进后的类),然后单击VC 6.0菜单Projrct -> Add to Projrct ->Files… ,再在打开的文件选择对话框中选择SerialPort.h 和SerialPort.cpp ,点击OK,就把类文件加入当前工程,并在SCOMMDlg.h 中加入头文件,#include "SerialPort.h",通过上述步骤就在当前工程中加入了CSeraiPort类。
4、完成串口消息处理函数OnCommunicatiom在CserailPort 类中有多个串口事件可以响应。
在一般串口编程中,只需要处理WM_COMM_RXCHAR消息就可以了,该类所有的消息均需要人工添加消息处理函数。
我们将处理函数名定义为OnComm()。
首先在SCOMMDlg.h 中添加串口字符接收消息WM_COMM_RXCHAR(串口接收缓冲区内有一个字符)响应函数的声明:如下图然后,在SCOMMDlg.cpp文件中进行WM_COMM_RXCHAR消息映射:如下图;接着,在SCOMMDlg.cpp 文件中加入函数OnCommunication(WPARAM ch, LPARAM port)的实现,暂不添加代码。
LONG CSCOMMDlg::OnCommunication(WPARAM ch, LPARAM port){return 0;}以上步骤需要手工完成。
至此完成了程序的对话框模板,在工程中插入了串口操作类CserailPort类。
5、添加串口初始化及关闭程序中有两种方法大开串口,一是程序启动,调用OnInitDialog()函数,就可以打开串口,缺省的串口号为COM1,如果COM1不存在或占用,就会给出提示;另外,单击“打开串口”按钮也可以打开串口。
//在初始化中打开串口BOOL CSCOMMDlg::OnInitDialog(){m_nBaud=9600;//波特率m_nCom=1;//串口号m_cParity='N';//奇偶校验m_nDatabits=8;//数据位m_nStopbits=1;//停止位m_dwCommEvents = EV_RXFLAG | EV_RXCHAR;//串口事件//if (m_Port.InitPort(this, 1, 9600,'N',8,1,dwCommEvents,512))CString strStatus;if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))//如果启动串口成功{m_Port.StartMonitoring();//启动监测辅助线程strStatus.Format("STATUS:COM%d OPENED,%d,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits); //打印串口状态及参数m_ctrlIconOpenoff.SetIcon(m_hIconRed);//设置串口状态灯//m_ctrlIconOpenoff.SetIcon(m_hIconOff);//"当前状态:串口打开,无奇偶校验,8数据位,1停止位");}else //如果启动失败{AfxMessageBox("没有发现此串口");m_ctrlIconOpenoff.SetIcon(m_hIconOff);}m_ctrlPortStatus.SetWindowText(strStatus);//显示串口的状态及参数return b;}6、在Class Wizard 中为按钮“打开串口”控制IDC_BUTTON_OPENPORT 添加单击响应函数。
//打开,关闭串口void CSCOMMDlg::OnButtonOpenport(){// TODO: Add your control notification handler code herem_bOpenPort=!m_bOpenPort; //取反if(m_bOpenPort) //如果串口是打开的{if(m_ctrlAutoSend.GetCheck())//检测自动发送标志是否打开{m_bOpenPort=!m_bOpenPort; //恢复原来的标志AfxMessageBox("请先关掉自动发送");return;//返回}m_ctrlOpenPort.SetWindowText("打开串口");m_Port.ClosePort();//关闭串口m_ctrlPortStatus.SetWindowText("STATUS:COM Port Closed");m_ctrlIconOpenoff.SetIcon(m_hIconOff);//m_hIconRed; //串口打开时的红灯图标句柄//HICON m_hIconOff; //串口关闭时的指示图标句柄}else //打开串口{m_ctrlOpenPort.SetWindowText("关闭串口");CString strStatus;if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512)) {m_Port.StartMonitoring();//启动监视线程m_ctrlIconOpenoff.SetIcon(m_hIconRed);//m_hIconRed;串口打开时的红灯图标句柄strStatus.Format("STATUS:COM%d OPENED,%d,%c,%d,%d",m_nCom, m_nBaud,m_cParity,m_nDatabits,m_nStopbits);//"当前状态:串口打开,无奇偶校验,8数据位,1停止位");}else //如果没有打开串口成功{AfxMessageBox("没有发现此串口或被占用");m_ctrlIconOpenoff.SetIcon(m_hIconOff);//m_hIconOff串口关闭时的红灯指示图标句柄}m_ctrlPortStatus.SetWindowText(strStatus);}}7、为了在程序关闭时通过关闭串口并释放占用资源,在ClassWizard中为CSCOMMDlg添加了WM_DISTROY的消息响应函数OnDestroy(),函数在主窗口即将销毁时调用。
//为主窗口关闭时添加关闭响应函数void CSCOMMDlg::OnDestroy(){CDialog::OnDestroy();m_ctrlAutoSend.SetCheck(0); //强行关闭自动发送KillTimer(1); //关闭定时器KillTimer(4);m_Port.ClosePort(); //关闭串口m_ReceiveData.Empty(); //清空接收数据字符串}8、十六进制数据发送处理首先为CSCOMMDlg类添加两个成员函数Str2Hex()和HexChar,前者对后者进行了调用,Str2Hex()的作用是将一个字符串作为十六进制转化为一个字符组,其中,data即为返回的数组,函数的返回值为data数组的长度。
// 将一个字符串作为十六进制转化为一个字符数组,字节间可用空格分隔,//返回转换后的字节数组长度,同时字节数组长度自动设置int CSCOMMDlg::Str2Hex(CString str, char* data){int t,t1;int rlen=0,len=str.GetLength();//获取字符串的长度//data.SetSize(len/2);for(int i=0;i<len;){char l,h=str[i];if(h==' ')//如果有空格{i++;continue;//跳出本次循环,进入for语句下次循环}i++;if(i>=len) break; //跳出for循环l=str[i];t=HexChar(h);t1=HexChar(l);if((t==16)||(t1==16))break;elset=t*16+t1;i++;data[rlen]=(char)t;rlen++;}return rlen;}char CSCOMMDlg::HexChar(char c){if((c>='0')&&(c<='9'))return c-0x30;else if((c>='A')&&(c<='F'))return c-'A'+10;else if((c>='a')&&(c<='f'))return c-'a'+10;elsereturn 0x10;}9、手动发送处理在ClassWizard中为手动发送按钮IDC_BUTTON_MANUALSEND添加单击处理函数(或直接在对话框模板中双击该控件),在OnButtonManualsend()添加如下代码:long TX_count=0;void CSCOMMDlg::OnButtonManualsend(){// TODO: Add your control notification handler code hereif(m_Port.m_hComm==NULL)//发送时要检验串口是否打开,否则会出错{m_ctrlAutoSend.SetCheck(0);AfxMessageBox("串口没有打开,请打开串口");return;}else //如果串口已经打开{UpdateData(TRUE);//读取编辑框内容if(m_ctrlHexSend.GetCheck()) //发送十六进制数据{char data[512];//定义一个512字节的数组int len=Str2Hex(m_strSendData,data);m_Port.WriteToPort(data,len);TX_count+=(long)((m_strSendData.GetLength()+1)/3);//计数发送的十六进制数据,注意这里的计算方法,//只有严格按照规则输入才能正确计算//m_Port.WriteToPort(hexdata);}else //发送ASCII文本{m_Port.WriteToPort((LPCTSTR)m_strSendData); //发送数据TX_count+=m_strSendData.GetLength(); //发送计数}CString strTemp;strTemp.Format("TX:%d",TX_count);m_ctrlTXCount.SetWindowText(strTemp);//显示计数}}10、自动发送处理自动发送时,需要用到定时器。