VC++_串口上位机编程实例
vc串口编程实例 -回复
vc串口编程实例-回复VC串口编程实例,是指使用VC(Visual C++)进行串口编程的实例。
串口编程是指通过串口(在计算机中又称通信端口)与外部设备进行数据的收发和通信。
串口编程在很多应用中都非常常见,例如与嵌入式设备、传感器、单片机等进行通信。
本文将以串口编程为主题,详细介绍如何在VC中进行串口编程的步骤和相关实例。
第一步,准备工作。
在进行串口编程之前,需要准备好一些必要的工作和工具。
首先,我们需要一台计算机和一个可用的串口接口。
然后,我们需要安装一个适合的集成开发环境(IDE)。
在本例中,我们选择使用VC进行编程。
确保已经安装好VC及其相关的开发工具和库。
第二步,创建工程。
在VC中创建一个新的工程。
在创建工程的界面中,选择“Windows桌面应用程序”作为项目类型。
输入一个项目名称,选择工作空间的目录。
点击“确定”按钮创建工程。
第三步,设置串口参数。
在VC中进行串口编程,首先需要设置串口的参数,包括波特率、数据位、停止位和校验位等。
通过设置这些参数,我们可以控制串口的通信速度和数据的可靠性。
在VC的代码中使用DCB 结构体来设置这些参数。
下面是一个示例代码段:c++DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams); GetCommState(hSerial, &dcbSerialParams); 获取串口配置参数dcbSerialParams.BaudRate = 9600; 设置波特率dcbSerialParams.ByteSize = 8; 设置数据位dcbSerialParams.StopBits = ONESTOPBIT; 设置停止位dcbSerialParams.Parity = NOPARITY; 设置校验位SetCommState(hSerial, &dcbSerialParams); 设置串口配置参数在上述代码中,首先定义一个DCB结构体变量dcbSerialParams,用于保存串口参数。
vc++上位机程序
VC++编写简单串口上位机程序2010年4月13日10:23:40串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C 语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享一下,体验一下单片机和PC通信的乐趣。
编译环境:VC++6.0操作系统:VMWare虚拟出来的Windows XP程序实现功能:1、PC初始化COM1口,使用n81方式,波特率57600与单片机通信。
PC的COM口编号可以通过如下方式修改:当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。
COM1口可用的话,会提示串口初始化完毕。
否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。
2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC转换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。
(见文章末尾图)3、为防止串口被一只占用,点击关闭串口可以关闭COM1,供其它程序使用,点击后按钮变为打开串口,点击可重新打开COM1。
程序的编写:1、打开VC++6.0建立基于对话框的MFC应用程序Test,2、在项目中插入MSComm控件:工程->增加到工程->Components and Controls->双击Registered ActiveX Controls->选择Microsoft Communications Control, version 6.0->Insert,按默认值添加,你会发现多了个电话图标,这是增加后串口通信控件。
VC实现串口通信项目源码
VC实现串口通信项目源码以下是一个简单的VC实现串口通信项目的源码:```cpp#include <windows.h>#include <iostream>using namespace std;//定义串口类class SerialPortpublic:SerialPort(const char* portName)//打开串口hSerial = CreateFile(portName, GENERIC_READ , GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//检查串口是否成功打开if (hSerial == INVALID_HANDLE_VALUE)if (GetLastError( == ERROR_FILE_NOT_FOUND)cerr << "Error: " << portName << " 不存在" << endl;} elsecerr << "Error: 打开串口失败" << endl;}}//配置串口DCB dcbSerialParams = {0};dcbSerialParams.DCBlength = sizeof(dcbSerialParams);cerr << "Error: 获取串口配置信息失败" << endl;}dcbSerialParams.BaudRate = CBR_9600; // 设置波特率为9600dcbSerialParams.ByteSize = 8; // 设置数据位为8位dcbSerialParams.StopBits = ONESTOPBIT; // 设置停止位为1个dcbSerialParams.Parity = NOPARITY; // 设置奇偶校验方式为无校验cerr << "Error: 设置串口配置信息失败" << endl;}//配置读写操作的超时时间cerr << "Error: 设置串口超时时间失败" << endl;}}//读取串口数据int readData(char* buffer, int bufferSize)DWORD bytesRead;if (!ReadFile(hSerial, buffer, bufferSize, &bytesRead, NULL)) cerr << "Error: 读取串口数据失败" << endl;return -1;}return bytesRead;}//发送串口数据bool writeData(const char* buffer, int bufferSize)DWORD bytesWritten;if (!WriteFile(hSerial, buffer, bufferSize, &bytesWritten, NULL))cerr << "Error: 发送串口数据失败" << endl;return false;}return true;}//关闭串口void closePorCloseHandle(hSerial);}private:HANDLE hSerial;};int mai// 创建SerialPort对象,指定串口名称(根据实际情况修改)SerialPort serialPort("COM1");//读取串口数据char buffer[256];int bytesRead = serialPort.readData(buffer, sizeof(buffer)); if (bytesRead == -1)cerr << "Error: 读取串口数据失败" << endl;} elsecout << "读取到的数据: " << buffer << endl;}//发送串口数据const char* data = "Hello, Serial Port!";if (!serialPort.writeData(data, strlen(data)))cerr << "Error: 发送串口数据失败" << endl;} elsecout << "成功发送串口数据" << endl;}//关闭串口serialPort.closePort(;return 0;```上述代码实现了一个简单的串口通信项目,包括串口初始化、读取串口数据、发送串口数据和关闭串口的功能。
用VC_实现ABB工业控制系统与上位机的通信
命令消息: 〈115201RD 3 17 18 返回消息: 〉115201OK # 001 9. 85196E + 02 # 001 9. 20957E+ 02 2. 2 批号数据 M asterP iece200 /1 主机定 时从 DSCA 114 通信 板卡 的 CH0 信道发出一批字符流信 号, 这个 信号原来 是送 到打印机去打印的。本数据采集系统为了使从现场获 取的生产数据能 够与 位于 ERP 中 的线 材质 量指 标数 据对应起来, 需要从中获取线材的批号数据。 字符流信号的一部分如下所示: # 459111 2205 930 1212 2007 0 0 & 上面的字符 流信号中, # 4后的 59111 表示这 是第 591批的第 11 根钢, 为了与 ERP中的质量指标 数据中 批 号 相 一 致, 还 要 加 上 日 期, 最 终 的 批 号 数 据 为 5102559111, 这表示 2005年 10月 25 日的第 591 批的 第 11 根钢。
EXCOM 允许外部计 算机 采用异 步串 行通信 连接 M asterP iece200 / 1主机 后 通 过 命 令 读写 主 机 数 据 库。 EXCOM 采用一种基于 7位 ASCII代 码通信协议, 协议 元素为命 令 和答 复。外 部计 算机 和 M asterP iece200 /1 主机之间命令和数 据的交换 为异 步全双 工传输 处理, 标准 V. 24 ( R S232C) 信 号接口 和 XON /OFF 流量 控制 协议, 7 位或 8位的数据, 1、1. 5或 2位停止 位, 传输速 度为 110 ~ 19 200 bp s。
上位机串口通信编程
上位机串⼝通信编程摘要本⽂主要描述了利⽤PC机与AT89C51单⽚机之间的通信程序设计实现温度显⽰。
并详述了在VC6.0环境下,上位机利⽤MSCOMM通信控件与单⽚机之间串⼝通信实现温度显⽰。
由单⽚机采集⼀个温度信号,将采集到的温度信号传送给PC机显⽰,PC机⽤VC6.0编写程序,单⽚机程序⽤C语⾔编写,最后⽤PROTUES软件进⾏仿真实现温度显⽰。
关键词:单⽚机MSCOMM控件VC6.0 AT89C51 温度显⽰⽬录摘要1 引⾔ (1)2 结构设计与⽅案选择 (2)2.1设计任务 (2)2.1.1单⽚机的选择 (2)2.1.2电平转换 (2)2.1.1单⽚机的选择 (2)2.1.3单⽚机与pc机通信原理 (2)2.2软件⽅案选择 (2)2.2.1 上位机编程⽅案选择 (3)2.2.2 单⽚机编程⽅案选择 (3)2.3 总体⽅案选择 (2)3 硬件设计 (8)3.1单⽚机主要特性 (5)3.2 MAX232电平芯⽚介绍10 (10)3.3 硬件电路设计图 (11)3.3.1 PC机与单⽚机通信接⼝电路设计框图 (11)3.3.2整体设计原理图 (11)4软件设计 (12)4.1上位机程序设计 (12)4.2下位机程序设计 (13)5 软硬件调试部分 (21)5.1 PROTEUS软件仿真 (21)5.1.1 Protues简介 (21)5.1.2 Protues仿真电路图 (22)5.2 VC软件仿真 (21)结束语 (27)致谢 (28)参考⽂献 (29)1引⾔随着⼈们⽣活⽔平的不断提⾼,单⽚机控制⽆疑是⼈们追求的⽬标之⼀,它所给⼈带来的⽅便也是不可否定的,要为现代⼈⼯作、科研、⽣活、提供更好的更⽅便的设施就需要从单⽚机技术⼊⼿,⼀切向着数字化控制,智能化控制⽅向发展。
现代化集中管理需要对现场数据进⾏统计、分析、制表、打印、绘图、报警等,同时,⼜要求对现场装置进⾏实时控制,完成各种规定操作,达到集中管理的⽬的。
串口调试助手VC源程序及编程详细过程
串口调试助手VC源程序及编程详细过程作者:龚建伟可以任意转载,注明作者和说明来自◆龚建伟技术主页◆目次:1.建立项目2.在项目中插入MSComm控件3.利用ClassWizard定义CMSComm类控制变量4.在对话框中添加控件5.添加串口事件消息处理函数OnComm()6.打开和设置串口参数7.发送数据如果你还没有下载源程序,又对本文有兴趣,请立即下载在众多网友的支持下,串口调试助手从2001年5月21日发布至今,短短一个月,在全国各地累计下载量近5000人次,在近200多个电子邮件中,20多人提供了使用测试意见,更有50多位朋友提出要串口调试助手的源代码,为了答谢谢朋友们的支持,公开推出我最初用VC控件MSComm编写串口通信程序的源代码,并写出详细的编程过程,姑且叫串口调试助手源程序V1.0或VC串口通讯源程序吧,我相信,如果你用VC编程,那么有了这个代码,就可以轻而易举地完成串口编程任务了。
(也许本文过于详细,高手就不用看)开始吧: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中出现了电话图标(如图1所示),现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
VC实现串口通信项目源码
VC实现串口通信项目源码以下是一个简单的串口通信项目的VC实现源码,包括了串口初始化、发送数据、接收数据等基本功能。
```#include <Windows.h>#include <stdio.h>#define BUFFER_SIZE 1024HANDLE hSerial;//初始化串口参数BOOL InitSerialPort//打开串口hSerial = CreateFile("\\\\.\\COM1", GENERIC_READ ,GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hSerial == INVALID_HANDLE_VALUE)printf("Failed to open serial port\n");return FALSE;}//配置串口参数DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams); printf("Failed to get serial port state\n"); CloseHandle(hSerial);return FALSE;}dcbSerialParams.BaudRate = CBR_9600; // 波特率为9600 dcbSerialParams.ByteSize = 8; // 8位数据位dcbSerialParams.Parity = NOPARITY; // 无奇偶校验dcbSerialParams.StopBits = ONESTOPBIT;// 1位停止位printf("Failed to set serial port state\n"); CloseHandle(hSerial);return FALSE;}//设置超时操作CloseHandle(hSerial);return FALSE;}return TRUE;//发送数据BOOL SendData(const char* data)DWORD bytesWritten;if (!WriteFile(hSerial, data, strlen(data), &bytesWritten, NULL))printf("Failed to send data\n");CloseHandle(hSerial);return FALSE;}return TRUE;//接收数据BOOL ReceiveData(char* buffer, DWORD size)DWORD bytesRead;if (!ReadFile(hSerial, buffer, size, &bytesRead, NULL))printf("Failed to receive data\n");CloseHandle(hSerial);return FALSE;}return TRUE;if (!InitSerialPort()return 1;}char sendBuffer[BUFFER_SIZE];char receiveBuffer[BUFFER_SIZE];//发送数据printf("Enter data to send: ");gets_s(sendBuffer, BUFFER_SIZE);if (!SendData(sendBuffer))return 1;}//接收数据printf("Receiving data...\n");if (!ReceiveData(receiveBuffer, BUFFER_SIZE)) return 1;}printf("Received data: %s\n", receiveBuffer); CloseHandle(hSerial);```这个项目使用了Windows的串口通信API函数来实现串口的初始化、发送数据和接收数据操作。
VC实现串口通信项目源码
VC实现串口通信项目源码以下是一个基于VC++实现串口通信的简单项目源码:```#include <windows.h>#include <iostream>using namespace std;//串口通信类class SerialPortprivate:HANDLE hSerial; // 串口句柄public:SerialPorhSerial = NULL;}bool openPort(const char* portName)//打开串口hSerial = CreateFileA(portName,GENERIC_READ,GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hSerial == INVALID_HANDLE_VALUE)cerr << "Failed to open serial port!" << endl;return false;}//配置串口参数DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams);cerr << "Failed to get serial parameters!" << endl; CloseHandle(hSerial);return false;}dcbSerialParams.BaudRate = CBR_9600; // 波特率设置为9600 dcbSerialParams.ByteSize = 8; // 数据位设置为8 dcbSerialParams.StopBits = ONESTOPBIT; // 停止位设置为1 dcbSerialParams.Parity = NOPARITY; // 校验位设置为无cerr << "Failed to set serial parameters!" << endl; CloseHandle(hSerial);return false;}//设置读写超时时间CloseHandle(hSerial);return false;}return true;}bool closePor//关闭串口if (hSerial != NULL && hSerial != INVALID_HANDLE_VALUE) CloseHandle(hSerial);hSerial = NULL;return true;}return false;}bool writeData(const char* data, int dataSize)//向串口写数据DWORD bytesWritten;if (!WriteFile(hSerial, data, dataSize, &bytesWritten, NULL)) cerr << "Failed to write data!" << endl;return false;}if (bytesWritten != dataSize)cerr << "Failed to write all data!" << endl;return false;}return true;}bool readData(char* buffer, int bufferSize)//从串口读数据DWORD bytesRead;if (!ReadFile(hSerial, buffer, bufferSize, &bytesRead, NULL)) cerr << "Failed to read data!" << endl;return false;return true;}};int maiSerialPort serialPort;//打开串口if (!serialPort.openPort("COM1"))return 1;}//从用户输入获取数据char sendBuffer[256];cout << "Enter data to send: ";cin.getline(sendBuffer, sizeof(sendBuffer));//发送数据至串口if (!serialPort.writeData(sendBuffer, strlen(sendBuffer) + 1))serialPort.closePort(;return 1;//从串口接收数据char recvBuffer[256];if (!serialPort.readData(recvBuffer, sizeof(recvBuffer)))serialPort.closePort(;return 1;}//输出接收到的数据cout << "Received data: " << recvBuffer << endl;//关闭串口serialPort.closePort(;return 0;```这个项目实现了一个简单的串口通信程序,通过命令行交互,用户可以输入要发送的数据,程序将数据发送到串口,然后从串口接收并打印接收到的数据。
基于C的串口通信上位机和下位机源程序
基于单片机串口通信的上位机和下位机实践串口是计算机上一种非常通用设备通信的协议(不要与通用串行总线Universal Serial Bus或者USB混淆)。
大多数计算机包含两个基于RS232的串口。
串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。
同时,串口通信协议也可以用于获取远程采集设备的数据。
串口通信的概念非常简单,串口按位(bit)发送和接收字节。
尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
它很简单并且能够实现远距离通信。
比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。
首先亮出C#的源程序吧。
主要界面:只是作为简单的运用,可以扩展的。
源代码:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO.Ports;using System.Timers;namespace 单片机功能控制{public partial class Form1 : Form{public Form1(){InitializeComponent();}SerialPort sp = new SerialPort();private void button1_Click(object sender, EventArgs e){String str1 = comboBox1.Text;//串口号String str2 = comboBox2.Text;//波特率String str3 = comboBox3.Text;//校验位String str4 = comboBox5.Text;//停止位String str5 = comboBox4.Text;//数据位Int32 int2 = Convert.ToInt32(str2);//将字符串转为整型Int32 int5 = Convert.ToInt32(str5);//将字符串转为整型groupBox3.Enabled = true;//LED控制界面变可选try{if (button1.Text == "打开串口"){if (str1 == null){MessageBox.Show("请先选择串口!", "Error");return;}sp.Close();sp = new SerialPort();sp.PortName = comboBox1.Text;//串口编号sp.BaudRate = int2;//波特率switch (str4)//停止位{case "1":sp.StopBits = StopBits.One;break;case "1.5":sp.StopBits = StopBits.OnePointFive;break;case "2":sp.StopBits = StopBits.Two;break;default:MessageBox.Show("Error:参数不正确", "Error");break;}switch (str3){case "NONE":sp.Parity = Parity.None; break;case "ODD":sp.Parity = Parity.Odd; break;case "EVEN":sp.Parity = Parity.Even; break;default:MessageBox.Show("Error:参数不正确", "Error");break;}sp.DataBits = int5;//数据位sp.Parity = Parity.Even;//设置串口属性sp.Open();//打开串口button1.Text = "关闭串口";textBox1.Text = Convert.ToString(sp.PortName) + "已开启!";}else{sp.Close();button1.Text = "打开串口";groupBox3.Enabled = false;//LED控制界面变灰色textBox1.Text = Convert.ToString(sp.PortName) + "已关闭!";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void Form1_Load(object sender, EventArgs e){//初始化textBox1.Text = "欢迎使用简易的串口助手!";groupBox3.Enabled = false;//LED控制界面变灰色groupBox6.Enabled = false;groupBox7.Enabled = false;groupBox8.Enabled = false;button3.Enabled = false;button6.Enabled = false;timer1.Start();try{foreach (string com in System.IO.Ports.SerialPort.GetPortNames()) //自动获取串行口名称boBox1.Items.Add(com);//默认设置comboBox1.SelectedIndex = 0;//选择第一个com口comboBox2.SelectedIndex = 4;//波特率4800comboBox3.SelectedIndex = 0;//校验位NONEcomboBox4.SelectedIndex = 0;//停止位为1comboBox5.SelectedIndex = 0;//数据位为8}catch{MessageBox.Show("找不到通讯端口!", "串口调试助手");}}private void timer1_Tick(object sender, EventArgs e){label6.Text = DateTime.Now.ToString();}private void button2_Click(object sender, EventArgs e){try {if (button2.Text == "开启"){groupBox6.Enabled = true;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;checkBox1.Checked = false;checkBox2.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;button3.Enabled = true;textBox2.Text = String.Empty;button2.Text = "关闭";}else{groupBox6.Enabled = false;button3.Enabled = false;button2.Text = "开启";textBox2.Text = String.Empty;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void button3_Click(object sender, EventArgs e){groupBox6.Enabled = true;label7.Text = "已发送";if (textBox2.Text == "")MessageBox.Show("发送失败,请选择发送的数据!");elsesp.WriteLine(textBox2.Text);//往串口写数据}private void checkBox1_CheckedChanged(object sender, EventArgs e) {try {if (checkBox1.Checked){checkBox1.Checked = true;checkBox2.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;label7.Text = "准备发送";textBox2.Text = "1";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox2_CheckedChanged(object sender, EventArgs e) {try {if (checkBox2.Checked){checkBox1.Checked = false;checkBox2.Checked = true;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;label7.Text = "准备发送";textBox2.Text = "2";radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox3_CheckedChanged(object sender, EventArgs e) {try{if (checkBox3.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = true;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "3";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox4_CheckedChanged(object sender, EventArgs e) {try{if (checkBox4.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = true;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "4";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox5_CheckedChanged(object sender, EventArgs e) {try{if (checkBox5.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = true;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "5";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox6_CheckedChanged(object sender, EventArgs e) {try{if (checkBox6.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = true;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "6";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox7_CheckedChanged(object sender, EventArgs e) {try{if (checkBox7.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = true;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "7";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox8_CheckedChanged(object sender, EventArgs e) {try{if (checkBox8.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = true;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "8";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void button5_Click(object sender, EventArgs e){try{if (button5.Text == "开启"){radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;groupBox7.Enabled = true;button6.Enabled = true;textBox2.Text = String.Empty;button5.Text = "关闭";}else{groupBox7.Enabled = false;button6.Enabled = false;button5.Text = "开启";textBox2.Text = String.Empty;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void button6_Click(object sender, EventArgs e){label7.Text = "已发送";if (textBox2.Text == "")MessageBox.Show("发送失败。
VC上位机For51
VC上位机For51济南职业学院电子工程系朱志强2010年8月17日概述:此文章作为学习上位机的复习资料和总结性资料。
是《VC++MSComm串口接收程序制做》的后继制作,在前文的基础上添加了部分新的功能,可以实现接收十六进制单个字符。
但是还是没有完成上位机对下位机的发送。
对于图片的应用和静态文本的更换,这此也没有解决。
第一步制作上位机程序,参考《VC++MSComm串口接收程序制做》。
步骤如下:新建一个基于对话框的程序,全部选择默认选项。
得到如下的对话框。
图1 新创建的对话框我们去掉上面的所有的控件,向工程中添加入MSCOMM控件,添加变量为m_ctrlComm。
再添加一个编辑框,作为接收框,使用类向导添加变量为m_strRXData。
同时,我们也给对话框添加上最小化按钮(方法:右键对话框,属性,样式里勾选上最小化按钮)。
双击MSCOMM控件,添加入如下的代码:void CFor51Dlg::OnOnCommMscomm1(){// TODO: Add your control notification handler code hereV ARIANT 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; //V ARIANT型变量转换为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("%02X",bt); //将字符送入临时变量strtemp存放strtemp=" 按下的按钮编号是"+strtemp+"\r\n";m_strRXData+=strtemp; //加入接收编辑框对应字符串}}UpdateData(FALSE); //更新编辑框内容}编译可以通过。
VC串口上位机编程及在实际
TTL 电平
双向仅需2条线
TTL 电平
Visual C++串口应用开发
用VisualC + + 语言开发串行通信程序有两种方 法:
使用ActiveX 控件。 优点:比较简单。 缺点:易发生数据丢失的情况,不适用于实时系统, 且灵活性差。 使用WindowsAPI 函数。 优点:较为方便且灵活性较强。其对串行口的操作 如文件一样,打开和关闭串行设备与打开和关闭文件 使用的是相同的函数,是目前广泛采用的一种方式。
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
• lpFileName:将要打开的串口逻辑名,如“COM1” ;
• dwDesiredAccess:指定串口访问的类型,可以是读 取、写入或二者并列;
间隙任意 接 收 10100100 设 备
1 0 10100100 1 0 11100110 1
发 送 0 11100110 设 备
异步通信的数据格式 :
一个字符帧 空 闲 起 始 位 数据位 校 验 位 停 止 位 空 闲
下一字符 起始位
LSB
MSB
异步通信的特点:通信双方以一个字符(包括特定 附加位)作为数据传输单位,且发送方传送字符的 间隔时间是不定的。在传输一个字符时总是以起始 位开始,以停止位结束。
2、代码和校验
代码和校验是发送方将所发数据块求和(或各字节异或),产生 一个字节的校验字符(校验和)附加到数据块末尾。接收方接收 数据同时对数据块(除校验字节外)求和(或各字节异或),将 所得的结果与发送方的“校验和”进行比较,相符则无差错,否 则即认为传送过程中出现了差错。 3、循环冗余校验
VC++控制计算机串口收发程序源代码
//~~~~~上位机C++控制计算机串口源程序~~~~~~~~////选择串口参数后,将该串口的TXD和RXD短接,然后点击“关闭串口”->”打开串口”,->“刷盘启动”观察串口发送和接收的数据////@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//~~~~~~~~~源代码如下,请复制相关部分进行编译测试~~~~~~~~~~~~~~~~~~BOOL CTEST_9Dlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization heregllen = 0; //记录转换次数全局变量清零if(! m_comm1.GetPortOpen())//判断串口是否已经打开{m_comm1.SetCommPort(1); //选择串口号1((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0);//设置combo初始显示行((CComboBox*)GetDlgItem(IDC_COMBO2))->SetCurSel(5);((CComboBox*)GetDlgItem(IDC_COMBO3))->SetCurSel(0);((CComboBox*)GetDlgItem(IDC_COMBO4))->SetCurSel(1);((CComboBox*)GetDlgItem(IDC_COMBO5))->SetCurSel(0);m_comm1.SetPortOpen(TRUE); //打开串口m_comm1.SetRThreshold(1); //收到两个字节引发OnComm事件m_comm1.SetInputMode(1);//输入模式选为二进制m_comm1.SetSettings("115200,n,8,1"); //设置串口参数,波特率115200,无奇偶校验,1位停止位,8位数据位// MessageBox("串口初始化完毕","提示"); //提示串口成功初始化m_serial.SetWindowText("关闭串口");//按钮显示状态改变}else MessageBox("串口被占用","提示"); //如果已经打开串口,消息框提醒pbar = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);//获得指向IDC_PROGRESS1的指针pbar -> SetRange(0,1023);//设置进度条的范围0~1023pbar -> SetPos(0);//当前位置为0return TRUE; // return TRUE unless you set the focus to a control}void CTEST_9Dlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below// to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CTEST_9Dlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags// the minimized window.HCURSOR CTEST_9Dlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}BEGIN_EVENTSINK_MAP(CTEST_9Dlg, CDialog)//{{AFX_EVENTSINK_MAP(CTEST_9Dlg)ON_EVENT(CTEST_9Dlg, IDC_MSCOMM2, 1 /* OnComm */, OnOnCommMscomm2, VTS_NONE)//}}AFX_EVENTSINK_MAPEND_EVENTSINK_MAP()void CTEST_9Dlg::OnOnCommMscomm2(){// TODO: Add your control notification handler code hereV ARIANT variant1;//定义V ARIANT型变量,用于存放接收到的数据COleSafeArray safearray;//定义safearray型变量LONG len,k=0;//定义长整型变量len,kBYTE rxdata[2048];//定义BYTE型数组CString stremp1,stremp2;//定义两个字符串if(m_comm1.GetCommEvent()==2) //判断引起OnComm事件的原因{//如果是接收到特定个字节数,则读取接收到的数据variant1 = m_comm1.GetInput();//把接收到的数据存放到V ARIANT型变量里safearray = variant1;//VARIANT型变量转换为ColeSafeArray型变量len = safearray.GetOneDimSize();for(k=0;k<len;k++){safearray.GetElement(&k,rxdata+k); //得到接接收到的数据放到BYTE型数组rxdata里stremp2.Format("%x ",rxdata[k]);//显示接收到的数据strRXDdata += stremp2;//把新的数据放到全局的字符串里}// BYTE bt = (*(unsigned char*)(rxdata+k)); //读取AD转换的高字节gllen++;//全局的变量,对接收到的转换结果的个数进行计算stremp2.Format("%x\r\n",Get_a1);strRXDdata += stremp2;//把新的数据放到全局的字符串里// int temp = bt*4+((*(unsigned char *)(rxdata+k+1))>>6); //高低字节合并成实际的转换结果,注意转换结果是左对齐// stremp1.Format("%2.2f",(2.56*temp/1024));//计算成实际电压值// SetDlgItemText(IDC_STA TIC,("当前电压值为:"+stremp1+" V")); //更新静态文本控件// pbar -> SetPos(temp);//更新进度条的当前位置}SetDlgItemText(IDC_EDIT1,strRXDdata);//更新文本控件的显示}void CTEST_9Dlg::OnButton1() //发送数据{// TODO: Add your control notification handler code herem_comm1.SetOutput(COleV ariant(str_Get1));}void CTEST_9Dlg::OnButton2() //开关串口{// TODO: Add your control notification handler code hereif(! m_comm1.GetPortOpen())//判断串口是否已经打开{int nInPort = m_cbPort.GetCurSel();//串口号选择int nInBaudRate = m_cbBaudRate.GetCurSel();//波特率选择int nInNEOBits = m_cbNEOBits.GetCurSel();//校验位选择int nInDatBits = m_cbDatBits.GetCurSel();//数据位选择int nInStopBits = m_cbStopBits.GetCurSel();//停止位选择CString strPortSelect;CString strBaudRate;CString strNEOBits;CString strDatBits;CString strStopBits;CString strCBText;CString strCTRCOMMText;m_cbBaudRate.GetLBText( nInBaudRate, strBaudRate);m_cbNEOBits.GetLBText( nInNEOBits, strNEOBits);m_cbDatBits.GetLBText( nInDatBits, strDatBits);m_cbStopBits.GetLBText( nInStopBits, strStopBits);m_comm1.SetCommPort(nInPort+1); //选择串口号m_comm1.SetPortOpen(TRUE); //打开串口m_comm1.SetRThreshold(1); //收到两个字节引发OnComm事件m_comm1.SetInputMode(1);//输入模式选为二进制strCTRCOMMText.Format("%s,%s,%s,%s",strBaudRate,strNEOBits,strDatBits,strStopBits); //控制参数初始化设置m_comm1.SetSettings(strCTRCOMMText); //设置串口参数,波特率115200,无奇偶校验,1位停止位,8位数据位m_serial.SetWindowText("关闭串口");//按钮显示状态改变strCBText.Format("***************************\r\n串口号:COM%d \r\n波特率:%s \r\n校验位:%s \r\n数据位:%s \r\n停止位:%s \r\n",nInPort+1,strBaudRate,strNEOBits,strDatBits,strStopBits);//增加更新文本strRXDdata += strCBText;SetDlgItemText(IDC_EDIT1,strRXDdata);//更新文本控件的显示}else{m_comm1.SetPortOpen(FALSE); //如果已经打开串口,则关闭串口m_serial.SetWindowText("打开串口");//按钮显示状态改变}}void CTEST_9Dlg::OnButton3() //清除EDIT{// TODO: Add your control notification handler code herestrRXDdata.Format("\0");SetDlgItemText(IDC_EDIT1,strRXDdata);//更新文本控件的显示}void CTEST_9Dlg::OnEditchangeCombo1(){// TODO: Add your control notification handler code here}void CTEST_9Dlg::OnChangeEdit2(){// TODO: If this is a RICHEDIT control, the control will not// send this notification unless you override the CDialog::OnInitDialog()// function and call CRichEditCtrl().SetEventMask()// with the ENM_CHANGE flag ORed into the mask.// TODO: Add your control notification handler code here// int x;// x= GetDlgItemInt(IDC_EDIT2); //读出整数GetDlgItem(IDC_EDIT2)->GetWindowText(str_Get1); //读出字符sscanf(str_Get1,"%x",&Get_a1);//将读取的数据转换成整数}void CTEST_9Dlg::OnButton4(){// TODO: Add your control notification handler code hereCByteArray m_Array; //定义字节数组m_Array.RemoveAll(); //字节数组清空m_Array.SetSize(7); //设定维数为1m_Array.SetAt(0,0x3A); //给m_array[0]赋值0m_Array.SetAt(1,0x01); //给m_array[0]赋值0m_Array.SetAt(2,0x00); //给m_array[0]赋值0m_Array.SetAt(3,0x00); //给m_array[0]赋值0m_Array.SetAt(4,0x48); //给m_array[0]赋值0m_Array.SetAt(5,0x3F); //给m_array[0]赋值0m_Array.SetAt(6,0x4D); //给m_array[0]赋值0m_comm1.SetOutput(COleV ariant(m_Array));}。
windows串口通信vc++编程实例
串口通信在嵌入式系统、物联网设备等领域中广泛应用,其中在Windows平台上使用C++编程实现串口通信是一种常见的需求。
以下是一个简单的Windows串口通信的VC++编程实例,涵盖串口的打开、配置、发送和接收数据的基本操作。
**1. 创建一个VC++项目:**打开Visual Studio,创建一个新的Win32控制台应用程序项目。
选择C++语言。
**2. 引入头文件:**在项目中引入Windows API的头文件和一些必要的库文件。
```cpp#include <windows.h>#include <tchar.h>#include <iostream>```**3. 定义串口句柄:**在全局范围内定义串口句柄,用于后续的串口操作。
```cppHANDLE hSerial;```**4. 初始化串口:**创建一个初始化串口的函数,用于打开并配置串口。
```cppbool InitSerialPort(const TCHAR* portName, DWORD baudRate) {hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hSerial == INVALID_HANDLE_VALUE) {std::cerr << "Error opening serial port!" << std::endl;return false;}DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams);if (!GetCommState(hSerial, &dcbSerialParams)) {std::cerr << "Error getting serial port state!" << std::endl;CloseHandle(hSerial);return false;}dcbSerialParams.BaudRate = baudRate;dcbSerialParams.ByteSize = 8;dcbSerialParams.StopBits = ONESTOPBIT;dcbSerialParams.Parity = NOPARITY;if (!SetCommState(hSerial, &dcbSerialParams)) {std::cerr << "Error setting serial port state!" << std::endl;CloseHandle(hSerial);return false;}return true;}```**5. 发送数据:**创建一个发送数据的函数,用于向串口发送数据。
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),附加信息为”我以下载此文档”,进群后找群主索要源代码或进行技术交流。
3 串口发送实例(VC)
15
pCmbComStopbits->ResetContent(); pCmbComStopbits->AddString(L"1"); pCmbComStopbits->AddString(L"1.5"); pCmbComStopbits->AddString(L"2"); pCmbComStopbits->SetCurSel(0); //1
“已安装的 SDK”中,选择我们要使用的 SDK,将它添加到右侧的列表框中,如图这 里是 ce50_2440a_test,选中它,然后下一步。
3
“应用程序类型”选择基于对话框,选择“在静态库中使用 MFC”。如果选择“在共享 DLL 中使用 MFC”的话,生成的可执行程序在目标机中运行时,可能会因为找不到相应 DLL 而出错。
pCmbComBaud->GetWindowTextW(strTmp);
m_portNo = pCmbComNo->GetCurSel() + 1;
//串口号
m_baud = _wtoi(strTmp);
//波特率
m_parity = pCmbComParity->GetCurSel();
IDC_BTN_DISC
数据发送
IDC_BTN_SEND
程序退出
IDC_BTN_EXIT
然 后 添 加 一 个 静 态 文 本 框 , 内 容 为 “ 发 送 数 据 ”。 添 加 一 个 编 辑 框 , ID 为
IDC_EDT_SEND。将 MultiLine,Auto VScroll 设置为 TRUE,将 Auto Hscroll 设置为 FALSE。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC++串口上位机简单例程(源码及详细步骤)(4.33MB)VC++编写简单串口上位机程序2010年4月13日10:23:40串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享一下,体验一下单片机和PC通信的乐趣。
编译环境:VC++6.0操作系统:VMWare虚拟出来的Windows XP程序实现功能:1、PC初始化COM1口,使用n81方式,波特率57600与单片机通信。
PC的COM口编号可以通过如下方式修改:当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。
COM1口可用的话,会提示串口初始化完毕。
否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。
2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC转换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。
(见文章末尾图)3、为防止串口被一只占用,点击关闭串口可以关闭COM1,供其它程序使用,点击后按钮变为打开串口,点击可重新打开COM1。
程序的编写:1、打开VC++6.0建立基于对话框的MFC应用程序Test,2、在项目中插入MSComm控件:工程->增加到工程->Components and Controls->双击Registered ActiveX Controls->选择Microsoft Communications Control,version6.0->Insert,按默认值添加,你会发现多了个电话图标,这是增加后串口通信控件。
3、删除确认、取消和提示框,添加“电话”、进程、静态文本、按钮、编辑框,拖动添加的控件,根据喜好布局。
4、右击编辑框Edit选择属性,在样式里设置,勾选多行、垂直滚动,其它可按默认值。
右击静态文本Text选择属性,在常规设置里,修改标题。
右击按钮PushButton选择属性,在在常规设置里,修改标题。
修改后界面如下,程序写出来运行时“电话”标志会自动消失。
5、查看->建立类向导MFC ClassWizard->Member Viariable,选择ClassName为CTestDlg 的类,Control ID为MSCOMM1,双击它,为它添加控制变量m_comm1。
类似的,选择IDC_BUTTON2添加控制变量m_serial。
(建立类向导也可以右击然后在弹出的快捷菜单里选择建立类向导)至此,基本框架已经出来了,编译后运行可以看到如下所示的界面。
(组建->全部组件,然后组建->执行)6、点击左侧的视图窗口,可以在三种模式下切换,第三个是打开我们的源代码窗口,第一个是类,第二个是窗体的资源视图。
选择File View,展开test files->Header Files,打开testDlg.h,在全局变量下添加如下代码,然后保存:int gllen;//定义整型标量gllen,用于记录接收数据的个数CProgressCtrl*pbar;//指向进度条的指针,用于操作进度条CString strRXDdata;//编辑框显示的文本,记录历次转换值7、点击Recourse View,展开test recourses->Dialog,双击IDD_TEST_DIALOG,编辑我们的主界面对话框。
双击击“电话”,弹出如下对话框,按确认键:VC会进入源码编辑窗口,这个函数是用来处理串口事件的,当PC串口接收到数据时,会产生一个数据缓冲区有数据的消息事件,然后调用执行这个函数。
添加如下代码,进行数据处理,窗口更新等操作:VARIANT variant1;//定义VARIANT型变量,用于存放接收到的数据COleSafeArray safearray;//定义safearray型变量LONG len,k;//定义长整型变量len,kBYTE rxdata[2048];//定义BYTE型数组CString stremp1,stremp2;//定义两个字符串if(m_comm1.GetCommEvent()==2)//判断引起OnComm时间的原因{//如果是接收到特定个字节数,则读取接收到的数据variant1=m_comm1.GetInput();//把接收到的数据存放到VARIANT型变量里safearray=variant1;//VARIANT型变量转换为ColeSafeArray型变量len=safearray.GetOneDimSize();for(k=0;k<len;k++){safearray.GetElement(&k,rxdata+k);//得到接接收到的数据放到BYTE型数组rxdata里}for(k=0;k<len;k++){BYTE bt=(*(unsigned char*)(rxdata+k));//读取AD转换的高字节if((k%2)==0)if((k+1)<len){gllen++;//全局的变量,对接收到的转换结果的个数进行计算stremp2.Format("第%d次转换结果:",gllen);//显示第几次转换int temp=bt*4+((*(unsigned char*)(rxdata+k+1))>>6);//高低字节合并成实际的转换结果,注意转换结果是左对齐stremp1.Format("%2.2f",(2.56*temp/1024));//计算成实际电压值SetDlgItemText(IDC_STA TIC,("当前电压值为:"+stremp1+"V"));//更新静态文本控件pbar->SetPos(temp);//更新进度条的当前位置strRXDdata+=stremp2;//把新的数据放到全局的字符串里strRXDdata+=stremp1;strRXDdata+="V\r\n";//字符串加单位V后换行}}}SetDlgItemText(IDC_EDIT1,strRXDdata);//更新文本控件的显示这时重新编译一下,看会不会有什么错误,出现下面提示,可以选择全部组建来清除。
LINK:LNK4073:cannot create map for.ILK file;linking nonincrementally出现下面错误,请关闭运行的test.exe后重试。
LINK:fatal error LNK1104:cannot open file"Debug/test.exe"出现下面错误两种错误,是由于空间编号问题引起的,当我们添加了编辑框或者“电话”后再添加,其编号自动加一,就会出现控件没定义。
Z:\vc++串口上位机\test\testDlg.cpp(32):error C2065:'IDC_MSCOMM1':undeclared identifier Z:\vc++串口上位机\test\testDlg.cpp(139):error C2065:'IDC_EDIT1':undeclared identifier解决方法是,在RecourseView里,打开窗体IDD_TEST_DIALOG,右击“电话”或者编辑框等其它出错的控件,右击选择属性,在常规里修改ID,这里的程序,除BUTTON有1、2两个之外,其它都是1全部组建编译一下,看看有没有错误,没有错误就可以运行一下,可以看到界面更原来是一样的。
有错误就修改一下,省得弄多了,错在哪里都不知道,查起来麻烦。
8、在源码编辑里,打开testDlg.cpp文件,进行窗口初始化函数的编写。
找到BOOL CTestDlg::OnInitDialog()函数,在SetIcon(m_hIcon,FALSE);//Set small icon//TODO:Add extra initialization here后面添加如下初始化代码:gllen=0;//记录转换次数全局变量清零if(!m_comm1.GetPortOpen())//判断串口是否已经打开{m_comm1.SetCommPort(1);//选择串口号1m_comm1.SetPortOpen(TRUE);//打开串口m_comm1.SetRThreshold(2);//收到两个字节引发OnComm事件m_comm1.SetInputMode(1);//输入模式选为二进制m_comm1.SetSettings("57600,n,8,1");//设置串口参数,波特率57600,无奇偶校验,1位停止位,8位数据位MessageBox("串口初始化完毕","提示");//提示串口成功初始化}else MessageBox("串口被占用","提示");//如果已经打开串口,消息框提醒pbar=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);//获得指向IDC_PROGRESS1的指针pbar->SetRange(0,1023);//设置进度条的范围0~1023pbar->SetPos(0);//当前位置为0m_serial.SetWindowText("关闭串口");//按钮显示状态改变可以看到,串口的参数等等都在在这里初始化的,可以根据自己的需要修改的,具体可以查看VC++里的详细介绍,看看有哪些参数可以给我们修改来用。
添加后再编译一下,运行后可以看到多了一个串口初始化的提示信息窗口。
至此,我们已经完成了主要的串口操作及界面,剩下的就是两个按钮的操作了。
9、回到资源视图的IDD_TEST_DIALOG窗口,双击开始转换按钮,给它添加事件,点击后PC通过串口发送0xaa出来,给单片机接收。
添加如下代码:CByteArray m_Array;//定义字节数组m_Array.RemoveAll();//字节数组清空m_Array.SetSize(1);//设定维数为1m_Array.SetAt(0,0xaa);//给m_array[0]赋值0m_comm1.SetOutput(COleVariant(m_Array));//由于SetOutput函数的参数为V ARIANT型,必须强制转换后才能发送同样地,双击另外一个按钮,给串口操作按钮添加代码,用于关闭或者打开串口。