C# 学习笔记(15)自己的串口助手----波形显示
Posted 不咸不要钱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 学习笔记(15)自己的串口助手----波形显示相关的知识,希望对你有一定的参考价值。
C# 学习笔记(15)自己的串口助手----波形显示
chart控件
chart控件共有5大集合,最重要的两个集合就是绘图空间和线
坐标系
坐标系的设置在绘图空间集合内
设置坐标系样式
框选放大功能
显示鼠标坐标功能
开启游标回调函数
private void chartWave_CursorPositionChanged(object sender, System.Windows.Forms.DataVisualization.Charting.CursorEventArgs e)
{
if (e.Axis.Name.ToLower().StartsWith("x"))
{
labX.Text = e.NewPosition.ToString();
}
else if (e.Axis.Name.ToLower().StartsWith("y"))
{
labY.Text = e.NewPosition.ToString();
}
}
缩放位置设置
位置和大小可以在程序中直接通过代码控制,Y轴的也是如此
线
一个坐标轴空间可以绘制多条线
显示线上点数值
线类型
线的类型一般选FastPoint 或者FastLine 其他的会影响曲线绘制效率,绘制的点越多,刷新越慢
chart绑定数据源
和列表控件一样,chart控件可以绑定DataTable,绑定分为三步,首先为DataTable创建列,然后将DataTable的列名和线的x,y绑定起来,最后将chart和DataTable绑定起来,接下来向DataTable添加列数据,刷新图表即可显示曲线
/// <summary>
/// chart控件数据源类型
/// </summary>
private DataTable dataTableType = new DataTable("Wave");
/// <summary>
/// chart控件数据源列表
/// </summary>
List<DataTable> dataTables = new List<DataTable>();
/// <summary>
/// 图表刷新线程
/// </summary>
Thread thread;
private void ChartWaveInit()
{
//1。 创建一个dataTable 10列 第一列存数据点x坐标 其它九列存y
for(int i = 0; i < 10; i ++)
{
dataTableType.Columns.Add("Series"+i);
dataTableType.Columns["Series" + i].DataType = typeof(int);
}
//2. 绑定数据列 给九条曲线指定x y列名
for(int i = 0; i < chartWave.Series.Count; i++)
{
chartWave.Series[i].XValueMember = "Series0";
chartWave.Series[i].YValueMembers = "Series"+ (i+1);
}
dataTables.Add(dataTableType.Clone());
//3. 绑定数据源
chartWave.DataSource = dataTables[0];
//刷新图表
chartWave.DataBind();
}
实际使用chart时,发现当数据点过多时,使用 chartWave.DataBind();刷新图表数据点越多越慢,因此程序中1s左右刷新一次图表。当数据点超过1w时,1s刷新一次都不行,因此创建了DataTables 列表,当DataTable行数大于1w后,切换图表数据源到下一个DataTable,防止数据点过多越来越卡。
/// <summary>
/// 帧头
/// </summary>
byte frameHead = 0xaa;
/// <summary>
/// 帧长
/// </summary>
int frameLen = 38;
private void Analysis()
{
List<byte> listBytes = new List<byte>(1024);
int counter = 0;
int yValue = int.MaxValue;
while (true)
{
Thread.Sleep(50);
counter++;
if (serialPortCOM.IsOpen)
{
byte[] bytes = new byte[serialPortCOM.BytesToRead];
serialPortCOM.Read(bytes, 0, bytes.Length);
this.Invoke(new Action(() => RxCounter += bytes.Length));
listBytes.AddRange(bytes);
while (listBytes.Contains(frameHead) && (listBytes.Count - listBytes.IndexOf(frameHead)) >= frameLen)
{
int Index = listBytes.IndexOf(frameHead);
if (listBytes[Index + 1] == 0xFF && listBytes[Index + 2] == 0xF1 && listBytes[Index + 3] == 32)
{
byte[] tempBytes = listBytes.ToArray();
int Wave1 = BitConverter.ToInt32(tempBytes, Index + 4);
int Wave2 = BitConverter.ToInt32(tempBytes, Index + 8);
int Wave3 = BitConverter.ToInt32(tempBytes, Index + 12);
int Wave4 = BitConverter.ToInt32(tempBytes, Index + 16);
int Wave5 = BitConverter.ToInt32(tempBytes, Index + 20);
int Wave6 = BitConverter.ToInt32(tempBytes, Index + 24);
int Wave7 = BitConverter.ToInt32(tempBytes, Index + 28);
int Wave8 = BitConverter.ToInt32(tempBytes, Index + 32);
lock (chartLock)
{
dataTables[dataTables.Count - 1].Rows.Add(WaveXIndex++, Wave1, Wave2, Wave3, Wave4, Wave5, Wave6, Wave7, Wave8);
//记录y值, 后面修改y轴位置
for(int i = 1; i < 9; i++)
{
if(chartWave.Series[i].Enabled)
{
yValue = (int)dataTables[dataTables.Count - 1].Rows[dataTables[dataTables.Count - 1].Rows.Count - 1][i];
break;
}
}
//表中超过 MaxSeriesLen 条数据 切换下一个表 一个表中数据越长则图表刷新时间越长
if (dataTables[dataTables.Count - 1].Rows.Count >= MaxSeriesLen)
{
dataTables.Add(dataTableType.Clone());
for (int i = MaxSeriesLen/2; i < MaxSeriesLen; i++)
{
dataTables[dataTables.Count - 1].Rows.Add(dataTables[dataTables.Count - 1 - 1].Rows[i].ItemArray);
}
this.BeginInvoke(new Action(() => trackBar1.Maximum += 10));
if (ckbUpdata.Checked)
{
//显示最新数据点
chartWave.DataSource = dataTables[dataTables.Count - 1];
this.BeginInvoke(new Action(() => { trackBar1.Value = trackBar1.Maximum; }));
}
}
}
listBytes.RemoveRange(0, Index + frameLen);
}
else
{
listBytes.RemoveRange(0, Index);
}
}
if (counter > 20 && yValue < int.MaxValue)
{
int temp = yValue;
counter = 0;
yValue = int.MaxValue;
this.BeginInvoke(new Action(() => {
lock (chartLock)
{
//X轴 滚动条位置 保持最新位置 - 99
if (ckbUpdata.Checked)
{
if (dataTables[dataTables.Count - 1].Rows.Count > chartWave.ChartAreas[0].AxisX.ScaleView.Size)
{
chartWave.ChartAreas[0].AxisX.ScaleView.Position = WaveXIndex - chartWave.ChartAreas[0].AxisX.ScaleView.Size;
}
else
{
chartWave.ChartAreas[0].AxisX.ScaleView.Position = 0;
}
//Y轴 滚动条位置 保持最新位置
chartWave.ChartAreas[0].AxisY.ScaleView.Position = temp - chartWave.ChartAreas[0].AxisY.ScaleView.Size/2;
}
//X轴 数据的起始位置和结束位置
//chart1.ChartAreas[0].AxisX.Minimum = 1000;
//chart1.ChartAreas[0].AxisX.Maximum = dataTables[dataTables.Count - 1].Rows.Count;
//刷新图表
chartWave.DataBind();
}
}));
}
}
}
}
传输协议
传输协议使用匿名上位机V7的用户自定义帧F1格式
#include "ANO_DT.h"
#include "stm32f1xx.h"
#define BYTE3(dwTemp) ( *( (char *)(&dwTemp) ) )
#define BYTE2(dwTemp) ( *( (char *)(&dwTemp) + 1) )
#define BYTE1(dwTemp) ( *( (char *)(&dwTemp) + 2) )
#define BYTE0(dwTemp) ( *( (char *)(&dwTemp) + 3) )
/*!
* @brief 发送底层
*
* @param dataToSend : 发送数据
* @param length : 发送数据长度
*
* @return 无
*
* @note 移植时,需要自己实现该发送函数
*
* @see
*
* @date 2019/5/28 ???
*/
void ANO_DT_Send_Data(uint8_t *dataToSend , uint8_t length)
{
extern UART_HandleTypeDef huart1;
HAL_UART_Transmit(&huart1, dataToSend, length, 1000);
}
/** ?????? */
uint8_t data_to_send[50];
/*!
* @brief 发送8个int32 数据给上位机
*
* @param data1 - data8 : 数据
*
* @return 无
*
* @note
*
* @see ANO_DT_send_int32(1, 2, 3, 0, 0, 0, 0, 0);
*
* @date 2019/5/28 ???
*/
void ANO_DT_send_int32(int32_t data1, int32_t data2, int32_t data3,int32_t data4 ,int32_t data5, int32_t data6, int32_t data7, int32_t data8)
{
uint8_t _cnt=0;
data_to_send[_cnt++] = 0xAA; //帧头 0xAAAA
data_to_send[_cnt++] = 0xFF;
data_to_send[_cnt++] = 0xF1; //功能字 0xF1
data_to_send[_cnt++] = 32; //帧长
data_to_send[_cnt++]=BYTE3(data1);
data_to_send[_cnt++]=BYTE2(data1);
data_to_send[_cnt++]=BYTE1(data1);
data_to_send[_cnt++]=BYTE0(data1);
data_to_send[_cnt++]=BYTE3(data2);
data_to_send[_cnt++]=BYTE2(data2);
data_to_send[_cnt++]=BYTE1(data2);
data_to_send[_cnt++]=BYTE0(data2);
data_to_send[_cnt++]=BYTE3(data3);
data_to_send[_cnt++]=BYTE2(data3);
data_to_send[_cnt++]=BYTE1(data3);
data_to_send[_cnt++]=BYTE0(data3);
data_to_send[_cnt++]=BYTE3(data4);
data_to_send[_cnt++]=BYTE2(data4);
data_to_send[_cnt++]=BYTE1(data4);
data_to_send[_cnt++]=BYTE0(data4);
data_to_send[_cnt++]=BYTE3(data5);
data_to_send[_cnt++]=BYTE2(data5);
data_to_send[_cnt++]=BYTE1(data5);
data_to_send[_cnt++]=BYTE0(data5);
data_to_send[_cnt++]=BYTE3(data6);
data_to_send[_cnt++]=BYTE2(data6);
data_to_send[_cnt++]=BYTE1(data6);
data_to_send[_cnt++]=BYTE0(data6);
data_to_send[_cnt++]=BYTE3(data7);
data_to_send[_cnt++]=BYTE2(data7);
data_to_send[_cnt++]=BYTE1(data7);
data_to_send[_cnt++]=BYTE0(data7);
data_to_send[_cnt++]=BYTE3(data8);
data_to_send[_cnt++]=BYTE2(data8);
data_to_send[_cnt++]=BYTE1(data8);
data_to_send[_cnt++]=BYTE0(data8);
uint8_t sum = 0;
uint8_t sumCheck = 0;
for(uint8_t i=0;i<_cnt;i++)
{
sum += data_to_send[i];
sumCheck+= sum;
}
data_to_send[_cnt++]=sum;
data_to_send[_cnt++]=sumCheck;
ANO_DT_Send_Data(data_to_send, _cnt);
}
最后,说实话这个串口助手的波形显示功能还是比较鸡肋的,刷新太慢了,后面有时间会研究一下github上的开源图表控件 https://github.com/beto-rodriguez/LiveCharts2
以上是关于C# 学习笔记(15)自己的串口助手----波形显示的主要内容,如果未能解决你的问题,请参考以下文章