Introduction
Whoever work with standard RS232 components from a .NET environment, and need real, embedded-like RS232 communication, realize in a short time that the component needs to be wrapped, or at least, additionally supported by custom software. I designed this tutorial because I couldn*t find something similar on the web. The code is an excerpt from a huge GPS tracking application, and it proved to work nicely. Just to mention, that there are other methods for RS232 communication such as using hand-shaking protocols, and hardware/software enabled pin control.
Background
I won*t go in to the details of basic RS232 communication, except that it is a point-to-point communication between two hosts, and they could be computers or embedded devices. My point here will be the software implementation part, using C# in a .NET 2.0 environment to be precise, but the principles are adoptable to any other language and IDE. Also, the type of data I*m going to send/read is string, but with little more effort, the code can be adopted to send/receive any type of serializable data. One more restriction, the demo code is adopted to receive a huge block of data and then process it. Another way is to continually append read data to some FIFO buffer, and do an online parsing of whatever data has arrived at the time (search for delimiters inside the arrived data before the reading ends), for continual receiving of data without any pause between two packets.
Methods used
We will need as few as the following four methods to do the job:
void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e);
private void ReadData(object s, EventArgs e);
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e);
private void AddRecieve(object s, EventArgs e);
Using the code
The first thing we need for an RS232 communication is a SerialPort component from the Components tab in the form editor's toolbox. The component itself supports both synchronous and asynchronous (event driven) communication. That means, for reading the port, we can use:
1. Blocking methods
Wait for the hardware to do the job, and then return to the app, so the read operation waits until the reading is finished (a few methods give us different ways of reading the port).
2. Non-blocking methods
We don*t wait in a loop for reading the port, we use interrupts, so when the port has something in an input buffer, the SerialPort component alarms us via delegate methods, such as DataRecieved.
Here, we will use event driven communication, because in my belief, this is the only true RS232 robust communication. So, lets begin. Let*s create some private members for our form, like:
Collapse Copy Code
private System.Timers.Timer timer1;
private StringBuilder recievedB = new StringBuilder();
private string recievedData;
Now, what we first need to do is a basic setup of the component we put on our form, meaning, set the component name (say, serialPort1), baudRate, parity, stopBits, etc. On the Events tab in Properties window, we create the delegate for DataRecieved (actually, the MVS will do that for us when we desire it), and name it serialPort1_DataReceived(). We will see later what we need the timer for. As for the recieveB, we use a StringBuilder class because it has a nice method Append, which doesn*t recreate the string every time we do a concatenation, rather it uses something like linking lists of strings (actually, you don*t have to know how it works). And finally, when all data has arrived, we will need a string to hold the received data needed for further parsing, recievedData. Next comes the coding of the delegate method we created. If we intend to update some controls in the form (as is the usual case), we need to call this.Invoke(some_delegate_method), because of the cross-thread operations. Check MSDN help for help on Invoke. We will create the method like this:
Collapse Copy Code
private void serialPort1_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
this.Invoke(new EventHandler(AddRecieve));
}
And next, we need to create and code the actual delegate to perform the reading:
Collapse Copy Code
private void AddRecieve(object s, EventArgs e)
{
string st = serialPort1.ReadExisting();
recievedB.Append(st);
timer1.Interval = 1000;
timer1.Start();
}
Let*s comment this code a bit. First, we call ReadExisting, which means reading anything that is in the SerialPorts input buffer. There can be a few bytes, or as many as a few kilobytes of data. Anyway, we read what*s arrived up to now, and Append that to our main holder for the received data 每 the recieveB (the StringBuilder class instance).
Now, the second part of this method. How do we know that the other side of the communication link finished sending data, so we can process it? Think logically for yourselves# For those who figured it out, yes, we know this when for some time (predefined time) there is nothing to read, meaning the event serialPort1_DataRecieved() isn*t firing for some time. This time can vary from 30ms (arguable) up to a minute, it's up to us to decide. In this case, we*ll be using a one second interval so called deadTimePeriod (there is a term for a similar thing, called readTimeout). What do we do with this timer? We crate the timer in the form's constructor, add the onElapsed method for firing up when the time has elapsed, and, I prefer the garbage collector not to destroy my timer. On every firing of the serialPort1_DataReceived() event, we restart the timer1 to the initial interval (in our case 1s), and start it again. Here is the form's construction:
Collapse Copy Code
public Form1()
{
InitializeComponent();
serialPort1.Open();
timer1 = new System.Timers.Timer(1000);
timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Elapsed);
GC.KeepAlive(timer1);
}
The method that will execute on the timer overflow is called timer1_Elapsed. Following that, we will code the method as:
Collapse Copy Code
void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer1.Stop();
this.Invoke(new EventHandler(ReadData));
}
First, we stop the timer, and second, we do the final receiving of the data. And again, just in case, we call Invoke. The actual method for reading the received data and parsing it looks something like:
Collapse Copy Code
private void ReadData(object s, EventArgs e)
{
recievedData = recievedB.ToString();
int j = recievedB.Length;
if (recievedData.Contains("RMR0" /*some delimiting end*/))
{
labelCard.Text = "Read " + j.ToString() + " bytes...";
// finally we have the data, we need to process it
ProcessData();
}
else
{
DialogResult dr = MessageBox.Show("Bad card data detected!," +
" Read good data?", "Error!",
MessageBoxButtons.YesNo,
MessageBoxIcon.Error);
if (dr == DialogResult.Yes)
{
}
}
}
Of course, the method ProcessData() is open for you to code it. The send method is trivial, on buttonSend_Click, just send whatever you need - in this case, the text from textBoxSend. This could be done as an asynchronous method as well, using standard asynchronous method, invoking in .NET 2.0.
Points of Interest
Finally, I feel I need to explain the whole process again. The communication points are A and B. Both sides open their ports, and side B starts sending bytes over the comm. link. A serialPort1 component on side A is receiving data in almost a byte-by-byte basis, and is filling some sort of a buffer. The point here, was knowing when side B has sent us all data it wished to send in this transmission so side A can start examining the data in whole. Point A does this by using a timer which co
UnityWind
- 粉丝: 11
- 资源: 31
最新资源
- 基于mmse的不确定电力系统有限次测量的分析估计 源代码, matlab代码按照高水平文章复现,保证正确 大量可再生分布式能源的预期渗透正推动下一代电力系统走向不确定性,这可能对状态估计的可靠性和复杂
- 西南科技大学数据分析期末大作业.zip
- 西门子PLC1200立体库机器人码垛机伺服视觉AGV程序 包括2台西门子PLC1215程序和2台西门子触摸屏TP700程序 PLC和基恩士相机视觉定位Modbus TCP通讯(SCL语言) PLC和A
- 知名扫地机代码方案 某知名大厂扫地机代码 适合需要学习项目与代码规范的工程师 硬件驱动包含 陀螺仪姿态传感器bmi160、电源管理bq24733等 软件驱动包括 IIC、PWM、SPI、多路A
- siddhi-execution-json jar包用于在处理事件中对json字符串进行处理
- 直流充电桩,双枪控制板方案,需要的砸单
- 埃斯顿量产控制器 埃斯顿量产伺服控制器C代码和硬件图纸 1)TMS320F28335+FPGA全套代码;全C写的DSP代码,VHDL写的FPGA代码(Lattice MXO1200) 2)AD电
- 信捷XC PLC与西门子V20变频器通讯程序 原创可直接用于生产的程序,程序带注释,并附送触摸屏程序,有接线方式和设置,通讯地址说明等 程序采用轮询,可靠稳定 器件:信捷XC3的PLC,西门子V20
- 台达DVP ES系列PLC与3台英威腾GD变频器通讯 程序带注释,并附送昆仑通态和威纶通触摸屏程序,有接线方式,设置 器件:台达DVP ES系列的PLC,3台英威腾GD系列变频器,昆仑通态,威纶通触
- 控制系统的数学建模,被控对象的数学模型建立,simulink模型实现 提供四旋翼和带尾翼直升机,共轴式直升机的数学模型、simulink模型,推导 提供资料,文献 刚体飞行动力学模型,运动学模型
- 深度学习中的Fashion-MNIST数据集与卷积神经网络实现及其训练分析
- MPC控制器设计,模型预测控制,线性时变模型预测控制,LTV MPC,提供理论讲解与应用实现 提供MPC算法、LTV MPC 算法在直升机和四旋翼中的应用实例 提供模型预测控制资料 提供matl
- Flink Forward Asia 2024 上海站(脱敏)PPT合集.zip
- Node.js安装与环境配置指南:覆盖Windows、macOS及Linux系统全流程
- 微信小程序开发全流程详解:从准备到发布的全面指南与关键技术解析
- 斑马打印机C#控制程序源代码,适合自己进行二次开发 文档齐全,包括驱动程序和如何设置斑马打印机的说明文档 源代码可以打印条形码标签和二维码标签
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
- 4
- 5
- 6
前往页