首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

VC串口通讯

2012-09-13 
VC串口通信我现在做的一个关于VC和单片机串口通信的程序,由于刚刚接触VC,有很多东西不明白,求个高手指教。

VC串口通信
我现在做的一个关于VC和单片机串口通信的程序,由于刚刚接触VC,有很多东西不明白,求个高手指教。
联系QQ715156386

[解决办法]
网上收集读写RS232口的程序,现转贴过来,这些程序虽然不能直接进行工业上的应用,但是在与PLC和各种现场设备的通讯应用中还是可以借鉴的.
程序一:
1.建立项目 
   打开VC++6.0,建立一个基于对话框的MFC应用程序SCommTest 
2.在项目中插入MSComm控件 
   选择Project菜单下Add To Project子菜单中的 Components and Controls…选项,在弹出的对话框中双击Registered ActiveX Controls项(稍等一会,这个过程较慢),则所有注册过的ActiveX控件出现在列表框中。 选择Microsoft Communications Control, version 6.0,,单击Insert按钮将它插入到我们的Project中来,接受缺省的选项。(如果你在控件列表中看不到Microsoft Communications Control, version 6.0,那可能是你在安装VC6时没有把ActiveX一项选上,重新安装VC6,选上ActiveX就可以了), 
  这时在ClassView视窗中就可以看到CMSComm类了,(注意:此类在ClassWizard中看不到,重构clw文件也一样),并且在控件工具栏Controls中出现了电话图标.现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用ClassWizard定义CMSComm类控制对象 
   打开ClassWizard->Member Viariables选项卡,选择CSCommTestDlg类,为IDC_MSCOMM1添加控制变量:m_ctrlComm,这时你可以看一看,在对话框头文件中自动加入了//{{AFX_INCLUDES() #i nclude "mscomm.h" //}}AFX_INCLUDES (这时运行程序,如果有错,那就再从头开始)。 
4.在对话框中添加控件
   向主对话框中添加两个编辑框,一个用于接收显示数据ID为IDC_EDIT_RXDATA,另一个用于输入发送数据,ID为IDC_EDIT_TXDATA,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其ID设为IDC_BUTTON_MANUALSEND。别忘记了将接收编辑框的Properties->Styles中把Miltiline和Vertical Scroll属性选上,发送编辑框若你想输入多行文字,也可选上Miltiline。 
  再打开ClassWizard->Member Viariables选项卡,选择CSCommTestDlg类, 为IDC_EDIT_RXDATA添加CString变量m_strRXData, 为IDC_EDIT_TXDATA添加CString变量m_strTXData。说明: m_strRXData和m_strTXData分别用来放入接收和发送的字符数据。 
5.添加串口事件消息处理函数OnComm() 
   打开ClassWizard->Message Maps,选择类CSCommTestDlg,选择IDC_MSCOMM1,双击消息OnComm,将弹出的对话框中将函数名改为OnComm,(好记而已)OK。 
  这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码: 
void CSCommTestDlg::OnComm() 

// TODO: Add your control notification handler code here 
VARIANT variant_inp; 
COleSafeArray safearray_inp; 
LONG len,k; 
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed. 
CString strtemp; 
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符 
{ ////////以下你可以根据自己的通信协议加入处理代码 
variant_inp=m_ctrlComm.GetInput(); //读缓冲区 
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 
len=safearray_inp.GetOneDimSize(); //得到有效数据长度 
for(k=0;k<len;k++) 
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组 
for(k=0;k<len;k++) //将数组转换为Cstring型变量 

BYTE bt=*(char*)(rxdata+k); //字符型 
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放 
m_strRXData+=strtemp; //加入接收编辑框对应字符串 


UpdateData(FALSE); //更新编辑框内容 


  到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行程序不应该有任何错误,不然,你肯定哪儿没看仔细,因为我是打开VC6对照着做一步写一行的,运行试试。没错吧?那么做下一步: 
6.打开串口和设置串口参数 
   你可以在你需要的时候打开串口,例如在程序中做一个开始按钮,在该按钮的处理函数中打开串口。现在我们在主对话框的CSCommTestDlg::OnInitDialog()打开串口,加入如下代码: 
// 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 Maps,选择类CSCommTestDlg,选择IDC_BUTTON_MANUALSEND,双击BN_CLICKED添加OnButtonManualsend()函数,并在函数中添加如下代码: 


void CSCommTestDlg::OnButtonManualsend() 

// TODO: Add your control notification handler code here 
UpdateData(TRUE); //读取编辑框内容 
m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送数据 

  运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一端的 串口调试助手 (或别的调试工具)接收框里出现了什么。 
  最后说明一下,由于用到VC控件,在没有安装VC的计算机上运行时要从VC中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到Windows目录下的System子目录中(win2000为System32)并再进行注册设置. 
8.发送十六进制字符 
  在主对话框中加入一个复选接钮,ID为IDC_CHECK_HEXSEND Caption: 十六进制发送,再利用ClassWizard为其添加控制变量:m_ctrlHexSend; 
  在ClassView中为SCommTestDlg类添加以下两个PUBLIC成员函数,并输入相应代码; 
//由于这个转换函数的格式限制,在发送框中的十六制字符应该每两个字符之间插入一个空隔 
//如:A1 23 45 0B 00 29 
//CByteArray是一个动态字节数组,可参看MSDN帮助 
int CSCommTestDlg::String2Hex(CString str, CByteArray &senddata) 

int hexdata,lowhexdata; 
int hexdatalen=0; 
int len=str.GetLength(); 
senddata.SetSize(len/2); 
for(int i=0;i<len;) 

char lstr,hstr=str[i]; 
if(hstr==' ') 

i++; 
continue; 

i++; 
if(i>=len) 
break; 
lstr=str[i]; 
hexdata=ConvertHexChar(hstr); 
lowhexdata=ConvertHexChar(lstr); 
if((hexdata==16)||(lowhexdata==16)) 
break; 
else 
hexdata=hexdata*16+lowhexdata; 
i++; 
senddata[hexdatalen]=(char)hexdata; 
hexdatalen++; 

senddata.SetSize(hexdatalen); 
return hexdatalen; 

//这是一个将字符转换为相应的十六进制值的函数 
//好多C语言书上都可以找到 
//功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1 
char CSCommTestDlg::ConvertHexChar(char ch) 

if((ch>='0')&&(ch<='9')) 
return ch-0x30; 
else if((ch>='A')&&(ch<='F')) 
return ch-'A'+10; 
else if((ch>='a')&&(ch<='f')) 
return ch-'a'+10; 
else return (-1); 

再将CSCommTestDlg::OnButtonManualsend()修改成以下形式: 
void CSCommTestDlg::OnButtonManualsend() 

// TODO: Add your control notification handler code here 
UpdateData(TRUE); //读取编辑框内容 
if(m_ctrlHexSend.GetCheck()) 

CByteArray hexdata; 
int len=String2Hex(m_strTXData,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数 
m_ctrlComm.SetOutput(COleVariant(hexdata)); //发送十六进制数据 

else 
m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送ASCII字符数据 


  现在,你先将串口线接好并打开串口调试助手V2.1,选上以十六制显示,设置好相应串口,然后运行我们这个程序,在发送框中输入00 01 02 03 A1 CC等十六进制字符,并选上以十六进制发送,单击手动发送,在串口调试助手的接收框中应该可以看到00 01 02 03 A1 CC了。 
9.在接收框中以十六进制显示 
  这就容易多了: 在主对话框中加入一个复选接钮,IDC_CHECK_HEXDISPLAY Caption: 十六进制显示,再利用ClassWizard为其添加控制变量:m_ctrlHexDiaplay。 然后修改CSCommTestDlg::OnComm()函数: 
void CSCommTestDlg::OnComm() 

// TODO: Add your control notification handler code here 
VARIANT variant_inp; 
COleSafeArray safearray_inp; 
LONG len,k; 
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed. 
CString strtemp; 
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符 

variant_inp=m_ctrlComm.GetInput(); //读缓冲区 
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 
len=safearray_inp.GetOneDimSize(); //得到有效数据长度 
for(k=0;k<len;k++) 
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组 
for(k=0;k<len;k++) //将数组转换为Cstring型变量 

BYTE bt=*(char*)(rxdata+k); //字符型 
if(m_ctrlHexDisplay.GetCheck()) 
strtemp.Format("%02X ",bt); //将字符以十六进制方式送入临时变量strtemp存放,注意这里加入一个空隔 
else 
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放 


m_strRXData+=strtemp; //加入接收编辑框对应字符串 


UpdateData(FALSE); //更新编辑框内容 

  测试:在串口调试助手发送框中输入00 01 02 03 A1 CC等十六进制字符,并选上以十六进制发送,单击手动发送,在本程序运行后选上以十六进制显示,在串口调试助手中单击手动发送或自动发送,则在本程序的接收框中应该可以看到00 01 02 03 A1 CC了。 
10.如何设置自动发送 
  最简单的设定自动发送周期是用SetTimer()函数,这在数据采集中很有用,在控制中指令的传送也可能用到定时发送。 
  方法是:在ClassWizard中选上MessageMap卡,然后在Objects IDs选中CSCommTestDlg类,再在Messages框中选上WM_TIMER消息,单击ADD_FUNCTION加入void CSCommTestDlg::OnTimer(UINT nIDEvent) 函数,这个函数是放入“时间到”后要处理的代码: 
void CSCommTestDlg::OnTimer(UINT nIDEvent) 

// TODO: Add your message handler code here and/or call default 
OnButtonManualsend(); 
CDialog::OnTimer(nIDEvent); 


  再在在主对话框中加入一个复选接钮,ID为IDC_CHECK_AUTOSEND Caption: 自动发送(周期1秒),再利用ClassWizard为其添加BN_CLICK消息处理函数void CSCommTestDlg::OnCheckAutosend(): 
void CSCommTestDlg::OnCheckAutosend() 

// TODO: Add your control notification handler code here 
m_bAutoSend=!m_bAutoSend; 
if(m_bAutoSend) 

SetTimer(1,1000,NULL);//时间为1000毫秒 

else 

KillTimer(1); //取消定时 


  其中:m_bAutoSend为BOOL型变量,在CLASSVIEW中为CSCommTestDlg类加入,并在构造函数中初始化: 
m_bAutoSen=FALSE; 
现在可以运行程序测试了。

[解决办法]
串口的我写过,收数据是一个
void CSCommTestDlg::OnComm()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
if(m_ctrlHexDisplay.GetCheck())
strtemp.Format("%02X ",bt); //将字符以十六进制方式送入临时变量strtemp存放,注意这里加入一个空隔
else
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
}
UpdateData(FALSE); //更新编辑框内容
}

楼上的qlizhang写的很详细 没问题的
[解决办法]
还有问题可以加我670538107

热点排行