C#通过串口读取数据(时间间隔为3秒),使用gdi+绘制实时曲线

顽主小贝 2012-03-09 09:25:09
请问各位,如果使用此种方法能否将串口中读取出的数据实时绘制出来(不丢数)?刚实习就遇上这么个难题,小弟表示压力很大、、、、、、、有老各位给小弟讲讲实现思路,或者给小弟发个demo,小弟邮箱121056759@qq.com。。。小弟在此谢过了
...全文
1249 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
顽主小贝 2012-03-15
  • 打赏
  • 举报
回复
求各位大哥大姐给小弟翻一下下边的这两段vb源代码啊。。。看不懂鸟(主要想知道原程序的通信协议和曲线图相关变量的计算表达式)

Public gDiameter(55) As Single '粒径数组
Public gDataInDiamete(55) As Long '每次从串口读取的粒径通道的数据(52个粒径通道)
Public gChannelData(65) As Long '从串口读取的强度通道数据(64个强度通道)

'CRC-16校验函数,参数待校验的数组,返回值 余数
Function CRC16(data() As Byte) As String
Dim CRC16Lo As Byte, CRC16Hi As Byte 'CRC寄存器
Dim CL As Byte, CH As Byte '多项式码 & H8001
Dim SaveHi As Byte, SaveLo As Byte
Dim i As Integer
Dim Flag As Integer
CRC16Lo = &HFF
CRC16Hi = &HFF
CL = &H1
CH = &H80
For i = 0 To UBound(data)
CRC16Lo = CRC16Lo Xor data(i) '每一个数据与CRC寄存器进行异或
For Flag = 0 To 7
SaveHi = CRC16Hi
SaveLo = CRC16Lo
CRC16Hi = CRC16Hi \ 2 '高位右移一位
CRC16Lo = CRC16Lo \ 2 '低位右移一位
If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1
CRC16Lo = CRC16Lo Or &H80 '则低位字节右移后前面补1
End If '否则自动补0
If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或
CRC16Hi = CRC16Hi Xor CH
CRC16Lo = CRC16Lo Xor CL
End If
Next Flag
Next i
Dim ReturnData(1) As Byte
ReturnData(0) = CRC16Hi 'CRC高位
ReturnData(1) = CRC16Lo 'CRC低位
CRC16 = ReturnData
End Function

'处理串口数据
Private Sub MSComm1_OnComm()
'Dim rs_sChannelData(55) As Long
'Dim rs_sIntensityData(52, 64) As Long
'Dim rs_pIntensity(65) As Long
Dim vbReceive As Variant
Dim i, j As Integer
Dim L As Integer
Dim dSum As Long
Dim pm25t As Single
Dim pm10t As Single
pm25t = 0
pm10t = 0

If MSComm1.CommEvent = comEvReceive Then
'wait (50) 'Receive the rs232 chars

If MSComm1.InBufferCount >= 6764 Then
vbReceive = ((MSComm1.Input))
If ((vbReceive(0) = 255) And (vbReceive(1) = 1)) Then

' //接下来是52个粒径通道的生物粒子浓度
dSum = 0

gDataInDiamete(1) = -1
gDataInDiamete(2) = -1
gDataInDiamete(3) = -1
gDataInDiamete(4) = (vbReceive(2 + 2 * 52 * 64) * 256 + vbReceive(2 + 2 * 52 * 64 + 1)) ' + Int(800 * Rnd + 1)

dSum = dSum + gDataInDiamete(4)

For i = 1 To 51
gDataInDiamete(i + 4) = vbReceive(2 + 2 * 52 * 64 + 2 * i) * 256 + vbReceive(2 + 2 * 52 * 64 + 2 * i + 1) ' + Int(800 * Rnd + 1)
dSum = dSum + gDataInDiamete(i + 4)

Next i

For i = 0 To 22

pm25t = pm25t + gDataInDiamete(i + 4) * gDiameter(i + 4) * gDiameter(i + 4) * gDiameter(i + 4)

Next i

For i = 0 To 41

pm10t = pm10t + gDataInDiamete(i + 4) * gDiameter(i + 4) * gDiameter(i + 4) * gDiameter(i + 4)

Next i

pm25t = pm25t * 1.7 * 3.14159 * 0.00001 / 3
pm10t = pm10t * 1.7 * 3.14159 * 0.00001 / 3
pm25 = pm25 + pm25t
pm10 = pm10 + pm10t
count_t = count_t + 1
gSaveFileFlag = 0
If (count_t = 20) Then

pm25 = pm25 / count_t
pm10 = pm10 / count_t
pm25 = Format(pm25, "#.####")
pm10 = Format(pm10, "#.####")

If gAutoSave = 1 Then
'自动保存文件
If gSaveFileFlag >= gSaveFileCycle Or gSaveFileFlag = 0 Then
'周期到
AutoSaveFile
gSaveFileFlag = 1
' End Select
End If
End If
count_t = 0
pm25 = 0
pm10 = 0

End If


' //接下来是64个强度通道的生物粒子荧光强度
sSum = 0

'For i = 0 To 51
' For j = 0 To 63
' rs_sIntensityData(i + 1, j + 1) = 0
' rs_sIntensityData(i + 1, j + 1) = vbReceive(2 + 2 * i * 64 + 2 * j) * 256 + vbReceive(2 + 2 * i * 64 + 2 * j + 1)
' Next j
' Next i

For j = 0 To 65
gChannelData(j) = 0
'For i = 0 To 52
' rs_pIntensity(j) = 0
' rs_pIntensity(j) + rs_sIntensityData(i, j)
'Next i
sSum = 0 'sSum + rs_pIntensity(j)
Next j

TransitSign = True
Else
runstop
Call Stopd_Click
wait (1000)
Call Start_Click
End If
'这里可以不作拷贝,在上面直接用gDataInDiamete,这样可以节省oncomm的运行时间
'CopyData gDataInDiamete, rs_sChannelData
'CopyData gChannelData, rs_pIntensity
'可能这个地方比较费时
ShowDiameterData False
'ShowChannelData False
ShowDpsAndFrq Picture5, dSum \ 3, sSum \ 3
'以上是绘图的部分,可能会比较费时
Text5.Text = str(dSum \ 3)
Text6.Text = Format(pm25t, "#.####")
Text1.Text = Format(pm10t, "#.####")
MSComm1.InBufferCount = 0 '...清空输入寄存器
timer4public = 1
End If
End If
End Sub
顽主小贝 2012-03-13
  • 打赏
  • 举报
回复
我用gdi+做个了实时曲线的demo,请问程序运行后为什么会出现闪烁的情况?
顽主小贝 2012-03-12
  • 打赏
  • 举报
回复
太感谢各位了,小弟在此一一谢过了,那啥我再研究研究,请等候小弟的随时骚扰。。。嘎嘎
beifang1986 2012-03-12
  • 打赏
  • 举报
回复
加这个群 8345950 ,里面有例子,,,也发给你了
火星大能猫 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 xb550453621 的回复:]

各位大哥大姐,能否给小弟发个demo,线程还有绘图和串口通信这块以前从未接触过,经理只给了一个vb的源程序,看不懂啊,很茫然。。。小弟邮箱121056759@qq.com
[/Quote]
真的很简单,你先从串口下手.绘图更简单.
顽主小贝 2012-03-12
  • 打赏
  • 举报
回复
各位大哥大姐,能否给小弟发个demo,线程还有绘图和串口通信这块以前从未接触过,经理只给了一个vb的源程序,看不懂啊,很茫然。。。小弟邮箱121056759@qq.com
songxh20122 2012-03-09
  • 打赏
  • 举报
回复
串口读数据 可以用串口自带的DataReceived事件
bytes[] bb=port1.Read(bb,0,port1.BytesToRead);
也可以写死循环 过一段时间
string xxx=port1.ReadLine();
totalBuffer+=xxx;
string xxx=prot1.ReadExisting();等等
很多方法都可以读的 关键看你串口进来的数据是什么样子
读完以后 存起来 放在画面上 就哦了
dai78 2012-03-09
  • 打赏
  • 举报
回复
设置个Timer每通过3秒发送读取数据指令,在串口接收数据事件中接收数据并绘制出来即可
顽主小贝 2012-03-09
  • 打赏
  • 举报
回复
求大家给点相关的资料,小弟不胜感激啊
顽主小贝 2012-03-09
  • 打赏
  • 举报
回复
我现在感觉我的主要难点在于:
1、不知道怎么从串口读取数据?
2、不知道如何将从串口读取出的数据绘制成实时曲线?
3、按照3秒的时间间隔会不会造成丢数的情况?
bdmh 2012-03-09
  • 打赏
  • 举报
回复
将数据保存到内存,然后搞个线程从内存中读取数据,根据你画图区域的长宽和实际数据折算成一个坐标,然后就在OnPaint事件中画就是了
kong19 2012-03-09
  • 打赏
  • 举报
回复
这个不难,串口通讯资料很多,读取数据不难,

读取到的数据用picturebox创建Graphics对象,然后上面画上x(时间),y(数据)轴,把数据用Graphics里面的DrawLines画上就可以了。

读取到的数据变成Point保存到数组,在DrawLines中可以指定数组,直接就画出来了。



王顺起 2012-03-09
  • 打赏
  • 举报
回复
读串口数据可以用serilport对象的,mychart没有用过,如果有用过的可以解答一下,但是用picturebox肯定是可以的。

你可以写个线程,一直监听串口,有数据的话你就解析出来,你读到的数据肯定都是ascii码,你需要根据你实际接收协议的格式处理后得到实时数据的value,这需要你自己分析了。

给个建议,为了展示方便,你可以把曲线部分做成一个组件,其它程序调用的时候只需要传递坐标轴的value就行了,这样省事。 楼上的哪位写到的port1应该就是serilport对象,你可以从网上搜个例子,一堆一堆的,呵呵


---------------------------------------------------------------
可以用串口自带的DataReceived事件
bytes[] bb=port1.Read(bb,0,port1.BytesToRead);
也可以写死循环 过一段时间
string xxx=port1.ReadLine();
totalBuffer+=xxx;
string xxx=prot1.ReadExisting();等等
很多方法都可以读的 关键看你串口进来的数据是什么样子
读完以后 存起来 放在画面上 就哦了
顽主小贝 2012-03-09
  • 打赏
  • 举报
回复
我刚刚发现vs自带了一个mychart控件和serilport控件,请问如果使用这两个控件可以满足我的条件么?之前没接触过这些,所以现在还是一头雾水中

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧