类库文件:cncomm.h 加入VC++工程
StdAfx.h中加入#include "CnComm.h"
界面头文件加入COM口定义 CnComm m_Com;
界面头文件加入消息响应函数afx_msg LRESULT OnReceive(WPARAM, LPARAM);
初始化打开串口m_Com.Open(5);
设置波特率等参数(可选)
m_Com.SetState(DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT);
dwBaudRate:波特率,9600,19200,38400等;
btParity:奇偶校验,{ NOPARITY 无校验, ODDPARITY 偶校验, EVENPARITY 奇校验, MARKPARITY 1校验, SPACEPARITY 0校验}
btByteSize:数据位数,{4, 5, 6, 7, 8}
btStopBits:停止位数,{ ONESTOPBIT 1位 , ONE5STOPBITS 1.5位 , TWOSTOPBITS 2位}
串口绑定界面m_Com.SetWnd(this->GetSafeHwnd());
加入接收函数消息映射ON_MESSAGE(ON_COM_RECEIVE, OnReceive)
实现接收数据函数OnReceive
1、导入cnComm类所包含的唯一一个文件:cnComm.h
2、在主对话框中增加一个cnComm类型的成员变量
public:
cnComm m_Com;//默认启动监视线程, 异步
3、编写“打开”按钮响应事件
voidCCnComm_DemoDlg::OnBtnOpen()
{
UpdateData(TRUE);//保存发送编辑框里的内容
//先关闭已经被打开的串口
if(m_Com.IsOpen())
{
m_Com.Close();
}
//打开串口
m_Com.Open(m_ctrlComList.GetCurSel()+1,"9600,8,n,1");
//设定需要监视串口数据接收的窗口
m_Com.SetWnd(this->GetSafeHwnd());
//判断是否打开成功
if(m_Com.IsOpen())
{
m_strStatus.Format("COM%d 已经被打开",m_ctrlComList.GetCurSel()+1);
UpdateData(FALSE);
}
else
{
m_strStatus.Format("COM%d 打开失败",m_ctrlComList.GetCurSel()+1);
UpdateData(FALSE);
}
}
4、编写“关闭”按钮响应事件
voidCCnComm_DemoDlg::OnBtnClose()
{
UpdateData(TRUE);//保存发送编辑框里的内容
if(m_Com.IsOpen())
{
m_Com.Close();
}
if(!m_Com.IsOpen())
{
m_strStatus ="没有串口被打开";
UpdateData(FALSE);
}
}
5、完成发送功能:
voidCCnComm_DemoDlg::OnBtnSend()
{
charcTx[256];
UpdateData(TRUE);//取得发送编辑框中的内容
//没有任何内容则立即返回
if(m_strTx.GetLength() == 0)
return;
//没有打开串口也立即返回
if(!m_Com.IsOpen())
{
AfxMessageBox("请先打开串口");
return;
}
int Hex2Ascii(const char* hex, char* ascii)
{
int len = strlen(hex), tlen, i, cnt;
for (i = 0, cnt = 0, tlen = 0; i
{
char c = toupper(hex[i]);
if ((c>='0'&& c<='9') || (c>='A'&& c<='F'))
{
BYTE t = (c >= 'A') ? c - 'A' + 10 : c - '0';
if (cnt)
ascii[tlen++] += t, cnt = 0;
else
ascii[tlen] = t << 4, cnt = 1;
}
}
ascii[tlen] = '\0';
return tlen;
}
_tcscpy(cTx,m_strTx.GetBuffer(m_strTx.GetLength()));
m_Com.Write(cTx);
}
用Write()函数发送数据时,如果字符串中有00,则被丢弃,建议使用WritePort()函数。例如:m_Com.WritePort(buf,len);
8、完成读串口功能。cnComm类可以自己启动一个监视线程来监视串口是否收到数据,当收到数据时会向由cnComm::SetWnd(hWnd)函数设定的窗口发送ON_COM_RECEIVE消息。下面我们在主窗口中完成ON_COM_RECEIVE消息响应函数,这里就不啰嗦怎么加了,不知道的话可以google“VC 怎么添加自定义消息”。下面是消息响应函数内容:
//字符串转16进制
int Ascii2Hex(const char* ascii, char* hex,int len)
{
int i;
char chHex[] = "0123456789ABCDEF";
for (i = 0; i
{
hex[i*3]= chHex[((BYTE)ascii[i]) >> 4];
hex[i*3 +1]= chHex[((BYTE)ascii[i]) & 0xf];
hex[i*3 +2]= ' ';
}
hex[len * 3] = '\0';
return len * 3;
}
//判断字符串是否为16进制
int CCommToolDlg::isHex(const char* pBuf, int bufSize)
{
int i = 0;
if ((NULL == pBuf) || (0 == bufSize))
{
return -1;
}
for (i = 0; i < bufSize; ++i)
{
if (('0' > pBuf[i] || '9' < pBuf[i])
&& ('A' > pBuf[i] || 'F' < pBuf[i])
&& ('a' > pBuf[i] || 'f' < pBuf[i]))
{
return -1;
}
}
return 1;
}
void CCommToolDlg::ProcessData(char *str,int len)
{
//CString s;
//s.Format("length :%s\r\n",len);
//if(isHex(str,len))
//DDX_Check(pDX, IDC_CHECK_HEX, m_bHex);
//m_bHex = FALSE;
if(m_bHex)
{
char hex_buf[1024*3];
Ascii2Hex(str,hex_buf,len);
comm_data += hex_buf;
}
UpdateData(FALSE);
AfxMessageBox(_T("File write."));
file.Write(str,len);
}
voidCCnComm_DemoDlg::OnComReceive()
{
charcRx[1024];
CString strTemp;
int len =m_Com.Read(cRx,1024);//读取一个字符(意第二个参数含义)
str[len] = _T('\0');
ProcessData(cRx,len);
strTemp.Format("%s",cRx);
m_strRx = m_strRx + strTemp;
UpdateData(FALSE);//显示接收内容
}
9、测试接收功能,这里我利用了只用一个串口测试通信程序的方法,我把我电脑上的唯一一个串口的第2和第3脚短接(相当于短接了发送和接收脚),打开程序,在发送框中填入要发送的字符串,点发送,接收框里马上会收到刚发送的内容。