同学在用FPGA做读卡器,上位机准备用labview做,因为不熟悉所以让我用C#做个备份,备不时之需。
菜鸟级别就跑去给人家帮忙,越帮越忙。他的要求是自定义串口属性,上位机发送命令,然后读取每次8096bytes的回复数据,然后利用接收到的数据画图,做一些统计和计算。自己做的过程中将问题分解了下:
1、串口读取数据
2、读取的串口数据存储到txt中
3、在winform中画图
从实习开始就有接触到串口,控制GSM模块的时候有用过,自以为比较有点认识。首先是发现原来串口的可选择的波特率是与电脑的配置有关的。我的直接使用主机自带的串口最大支持的波特率为115200;然后通过USB转串口可以支持最高的256000。接着直接将ReceivedBytesThreshold设置成了8096,准备坐等其成。貌似需要加大ReadBufferSize。
直到sleep 2秒才能保证正确的数据接收,而且还会出现完成数据接收后还会触发接收事件的现象,接收到的明显是0,搞不清楚。去查各种C#书,想要看明白串口操作,结果发现C#貌似对网络支持的很强大的样子,串口几乎没有提及,发帖,qq群 有的也就是之言片语。有说是开个线程专门去接收的,但是接收事件不是本身就是一个单独的线程吗。最后通过一直读知道收到足够的数据的方式加快了点速度。 但是同学的labview做出来的没有什么明显的需要接收时间的问题,看来串口操作还是没设置好啊
当还在读数据的时候关闭串口,会报错,添加了个标志。
将接收数据存储下来,网上抄袭各种代码,结果总是得到乱码。不解啊,看了下之前的一个人家的代码,原来少了码制转换。总算可以存储了。
画图,折腾了好久才知道是用graphics来做的,panel上面做图片问题老是会有闪烁的很厉害的问题。picturebox的绘制不是说画上去马上就表现出来的。
顺便贴上自己粗略的代码,记忆一下。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
namespace UpperConputer
{
public partial class Form1 : Form
{
private SerialPort m_serialport = new SerialPort();
//private string fullData = "";
private byte[] fulldata = new byte[8005];
private List
private uint[] intData = new uint[2001];
private bool serialPortMark=false;
private string xmark;
public Graphics graphicsObject;
private Thread threadshow;
private bool portclosing = false;
private bool localPortListening = false;
private delegate void showdelegate();
private DateTime begin, end;
//private string selectedFrequency;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBoxSerialPortN.SelectedIndex = 3;
comboBoxStopBit.SelectedIndex = 0;
comboBoxDataBit.SelectedIndex = 3;
comboBoxBuadRate.SelectedIndex = 6;
comboBoxSelF.SelectedIndex = 7;
//设置双缓冲
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
//newthread=new Thread(new ThreadStart(rec));
//newthread.Start();
CreateImage();
}
private void showtext(string str)
{
textBox1.Text = str;
}
private void initializeSerialPort()
{
m_serialport.PortName = comboBoxSerialPortN.Text;
m_serialport.BaudRate =Convert.ToInt32( comboBoxBuadRate.Text);
m_serialport.DataBits = Convert.ToInt16(comboBoxDataBit.Text);
m_serialport.Parity = Parity.None;
//m_serialport.ReadTimeout = 1000;
switch (comboBoxStopBit.Text)
{
case"1":
m_serialport.StopBits = StopBits.One;
break;
case"1.5":
m_serialport.StopBits = StopBits.OnePointFive;
break;
case"2":
m_serialport.StopBits = StopBits.Two;
break;
}
//can used
m_serialport.ReadBufferSize = 10000;
m_serialport.ReceivedBytesThreshold = 1;
//thread_com_read();
}
private void m_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (portclosing) return;
try
{
localPortListening = true;
byte firstByte = Convert.ToByte(m_serialport.ReadByte());
int bytesRead = m_serialport.BytesToRead;
byte[] bytesData = new byte[bytesRead + 1];
bytesData[0] = firstByte;
int count = buffer.Count();
for (int i = 1; i <= bytesRead; i++)
{
bytesData[i] = Convert.ToByte(m_serialport.ReadByte());
}
//MessageBox.Show(Convert.ToString(bytesRead));
for (int j = 0; j <=bytesRead; j++)
{
buffer.Add(bytesData[j]);
}
count = buffer.Count();
if (buffer.Count() == 8004)
{
for (int i = 0; i < 8004; i++)
{
fulldata[i] = buffer[i];
}
for (int i = 0, j = 0; i < 8004; i += 4, ++j)
{
intData[j] = System.BitConverter.ToUInt32(fulldata, i);
}
//Thread.Sleep(100);
drawImage(intData);
//Thread.Sleep(100);
buffer.Clear();
}
string str = byteToHexStr(bytesData);
File.WriteAllText("data1.txt", str);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message+" At datareceived");
//处理超时错误
}
finally
{
localPortListening = false;
}
//can used
//if (portclosing) return;
//try
//{
// localPortListening = true;
// System.Threading.Thread.Sleep(2000);
// byte[] receivedData = new byte[m_serialport.BytesToRead];
// int count = m_serialport.Read(receivedData, 0, m_serialport.BytesToRead);
// //m_serialport.DiscardInBuffer();//清空接收缓冲区数据
// if (count == 8004)
// {
// for (int i = 0, j = 0; i < 8004; i += 4, ++j)
// {
// intData[j] = System.BitConverter.ToUInt32(receivedData, i);
// }
// }
// else
// {
// return;
// }
// for (int i = 0, j = 0; i < 8004; i += 4, ++j)
// {
// intData[j] = System.BitConverter.ToUInt32(receivedData, i);
// }
// drawImage(intData);
//}
//catch (Exception ex)
//{
// MessageBox.Show(ex.Message);
//}
//finally
//{
// localPortListening = false;
//}
}
public string byteToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
private void drawImage(uint[] intData)
{
float xcoordone,xcoordtwo;
double xmax,ymax;
double y1, y2;
int count = 0;
double centreFrequency;
Graphics g = Graphics.FromImage(pictureBox1.Image);
//pictureBox1.Refresh();
//Graphics g = pictureBox1.CreateGraphics();
if (xmark == "0")
{
xcoordone = 40;
g.DrawString("0",new Font("Arial",16),Brushes.Red,new Point(30,378));
}
else
{
xcoordone = 100;
g.DrawString(xmark, new Font("Arial", 16), Brushes.Red, new PointF(90, 378));
}
xmax = xcoordone;
ymax = 0;
xcoordtwo = xcoordone + (float)0.3;
Pen mypen = new Pen(Brushes.Blue, 1);
Pen dashLinePen = new Pen(Brushes.Red, 1);
dashLinePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
//draw every point and using line to link each other
for (int i = 0; i < intData.Count()-1; ++i)
{
y1 = (double)intData[i] / 16777216 * 300;
y2=(double)intData[i+1]/16777216*300;
// obtain the max point
if (ymax < y1)
{
ymax = y1;
xmax = xcoordone;
count=i;
}
g.DrawLine(new Pen(Color.Black,1),new PointF(xcoordone,(float)(378 - y1)),new PointF(xcoordtwo, (float)(378 - y2)));
xcoordone += (float)0.3;
xcoordtwo += (float)0.3;
}
//画x轴第二个标示点
int nextxcoord = int.Parse(xmark);
nextxcoord=nextxcoord+2;
g.DrawString(Convert.ToString( nextxcoord),new System.Drawing.Font("Arial",16),Brushes.Red,new PointF(xcoordone,378));
//画最高频率线并加注释
nextxcoord -= 2;
g.DrawLine(dashLinePen, (float)xmax, (float)(378-ymax), (float)xmax, 378);
centreFrequency=nextxcoord+count*0.001;
g.DrawString("f:" + Convert.ToString(centreFrequency),new Font("Arial",16), Brushes.Red, (float)xmax, 388);
//寻找0.707两点,画线,计算Q值
mypen.Dispose();
dashLinePen.Dispose();
g.Dispose();
showdelegate show = new showdelegate(showpicture);
this.Invoke(show);
}
private void showpicture()
{
pictureBox1.Visible = false;
pictureBox1.Visible = true;
}
private void CreateImage()
{
pictureBox1.Refresh();
int height = 418, width = 820;
Image image = new Bitmap(820, 418);//定义图象大小
Graphics g = Graphics.FromImage(image); //定义gdi绘图对象
Pen mypen = new Pen(Brushes.DeepSkyBlue, 1);
try
{
g.Clear(Color.White);//清除整个绘图面并以指定背景色填充。
//g.FillRectangle(Brushes.WhiteSmoke, 0, 0, width, height);//填充由一对坐标、一个宽度和一个高度指定的矩形的内部。
//画边框
g.DrawRectangle(mypen, 0, 0, width - 9, height - 3);//绘制由坐标对、宽度和高度指定的矩形。
g.DrawLine(new Pen(Brushes.Black, 1), 40, height - 40, width - 40, height - 40);//x轴
g.DrawLine(new Pen(Brushes.Black, 1), width - 50, height - 30, width - 40, height - 40);//箭头
g.DrawLine(new Pen(Brushes.Black, 1), width - 50, height - 50, width - 40, height - 40);
g.DrawLine(new Pen(Brushes.Black, 1), 40, height - 40, 40, 40);//y轴
g.DrawLine(new Pen(Brushes.Black, 1), 30, 50, 40, 40);
g.DrawLine(new Pen(Brushes.Black, 1), 50, 50, 40, 40);
g.DrawString("频率、Q值测试图", new Font("宋体", 16), Brushes.Green, new PointF(300, 20));
g.DrawString("电压值", new Font("Arial", 16), Brushes.Aqua, new PointF(50, 40));
g.DrawString("频率", new Font("宋体", 16), Brushes.Aqua, new PointF(width - 90, height - 30));
g.DrawString("中心频率:", new Font("宋体", 16), Brushes.Aqua, new PointF(width - 190, 30));
g.DrawString("Q值:", new Font("宋体", 16), Brushes.Aqua, new PointF(width - 140, 50));
mypen.Dispose();
g.Dispose();
pictureBox1.Image = image;
}
catch
{ }
}
private void button1_Click(object sender, EventArgs e)
{
if (!m_serialport.IsOpen)
{
MessageBox.Show("打开串口!");
return;
}
if (comboBoxSelF.Text == "")
{
MessageBox.Show("请选择测试频率!");
}
else
{
xmark = comboBoxSelF.Text;
m_serialport.Write(comboBoxSelF.Text);
}
}
private void button2_Click(object sender, EventArgs e)
{
}
private void buttonOpen_Click(object sender, EventArgs e)
{
try
{
if (!m_serialport.IsOpen)
{
//CreateImage();
initializeSerialPort();
m_serialport.Close();
m_serialport.Open();
//thread_com_read();
m_serialport.DataReceived += new SerialDataReceivedEventHandler(m_DataReceived);
serialPortMark = true;
buttonOpen.Text = "关闭串口";
}
else
{
portclosing = true;
while (localPortListening) Application.DoEvents();
serialPortMark = false;
buttonOpen.Text = "打开串口";
m_serialport.DataReceived -= new SerialDataReceivedEventHandler(m_DataReceived);
m_serialport.Close();
portclosing = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void buttonRefresh_Click(object sender, EventArgs e)
{
CreateImage();
}
}
}