我是靠谱客的博主 可靠金鱼,最近开发中收集的这篇文章主要介绍C#三通道示波器-串口通信,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

三通道示波器

【说明】
【语言】:C#
【平台】:Win10 .NETFrameWork
【硬件】:采用CH340作TTL转串口电平转换器
【信道复用方式】:分时复用
【下位机软件要求】:见代码注释
【代码使用方式】:使用vs建立C#窗体应用后直接将代码作为主文件即可
【注意事项】:目前的设定是PC连上串口设备后才能运行


下位机软件要求截取:

        /*FuncTip 
 * 
* @Name:YlocsOfChannlesInload
* @Arg:None
* @Func:将ylocs的数据加载到各通道缓冲区ylocsofChannelX
* 下位机发送数据格式:
* —————————————————————
* 标志数据|CH1数据|CH2数据|CH3数据|标志数据...
* —————————————————————
* 数据长度:8bits
* 建议二进制形式发送
* 如使用标准库printf
* 建议采用%c格式发送数据
*  */

完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
using System.IO.Ports;
using System.Threading;


namespace RubbishDrawer
{
    public partial class Form1 : Form
    {

        //窗体初始化 
        public Form1()
        {
            InitializeComponent();
            /* 绘制作图区域边框 */
            DrawTable();
            /* 添加按钮 */
            AddbtnStop();
            ylocsInit();
            /* 初始化时钟 */
            TimerConfig(100);//时钟TIC间隔搞长点----<帧数>搞低点
            /* 初始化串口 */
            PortConfig(115200);//波特率设置为9600             串口在连接后才可被检测到

        }

        /* ----------A-作图---------- */

        /* 作图区相关常量 */
        private const short TableLength = 63;//图板的长度
        private const short TableHeight = 70;//图版的高度

        private const int TableLeft = 50;//图板左边沿
        private const int TableTop = 20;//图板上边沿
        int[] ylocs = new int[TableLength * 4];//缓存发来的数据,用作points的y坐标元数据
        int[] ylocsOfCh1 = new int[TableLength];
        int[] ylocsOfCh2 = new int[TableLength];
        int[] ylocsOfCh3 = new int[TableLength];

        /* 计时器相关常量 */
        private const int TicMax = TableLength + 2;//TIMENOW的上限(周期TIC数)

        /*FuncTip 
 * 
* @Name:ylocsInit
* @Arg:None
* @Func:将各通道缓冲区ylocsofchX初始化位对应Y轴0刻度位置
*  */
        public void ylocsInit()
        {
            for(int ptr=0;ptr<TableLength;ptr++){
                ylocsOfCh1[ptr] = TableTop;
                ylocsOfCh2[ptr] = TableTop + TableHeight / 3;
                ylocsOfCh3[ptr] = TableTop + 2 * TableHeight / 3;                                      
            }
            
        }

        /*FuncTip 
 * 
* @Name:DrawTable
* @Arg:None
* @Func:绘制作图区域边界
*  */
        public void DrawTable()
        {
            Point[] Edges = {
                        new Point(TableLeft-1, TableTop),
                        new Point(TableLeft+TableLength-1, TableTop),
                        new Point(TableLeft+TableLength-1, TableTop+TableHeight-1),
                        new Point(TableLeft-1, TableTop+TableHeight-1),
                        new Point(TableLeft-1, TableTop),
                    };
            Graphics Table = CreateGraphics();
            Table.PageUnit = GraphicsUnit.Millimeter;
            Pen TablePen = new Pen(Color.Black, 0.1F);
            Table.DrawLines(TablePen, Edges);
            Point[] CrossLines = {
                        new Point(TableLeft-1, TableTop+TableHeight/3),
                        new Point(TableLeft+TableLength-1, TableTop+TableHeight/3),
                        new Point(TableLeft+TableLength-1, TableTop+2*TableHeight/3),
                        new Point(TableLeft-1, TableTop+2*TableHeight/3),
            };
            //TablePen.Width = 0.5F;
            Table.DrawLines(TablePen, CrossLines);
        }

        /* 添加控制按钮(绘图允许控制) */
        /*FuncTip 
 * 
* @Name:AddbtnStop
* @Arg:None
* @Func:添加按钮btnStop到窗体
*  */
        public void AddbtnStop()
        {
            Button btnStop = new Button();
            btnStop.Text = "Stop";
            btnStop.Top = TableTop + TableHeight + 2;
            btnStop.Left = TableLeft;

            btnStop.Click += new System.EventHandler(btnStopClk);
            this.Controls.Add(btnStop);
        }

        /*VarTip 
 * 
* @Name:ShowOrNot
* Function:绘图允许标志
*  */
        bool ShowOrNot = true;

        /*FuncTip 
 * 
* @Name:btnStopClk
* @Arg:sender触发事件的控件
* e事件(通用写法)
* @Func:按键btnStop的单击事件响应函数
* 改变Var:ShowOrNot的值
*  */
        public void btnStopClk(object sender, EventArgs e)
        {
            ShowOrNot = ShowOrNot == true ? false : true;

        }

        /*FuncTip 
* 
* @Name:TimerConfig
* @Arg:None
* @Func:时钟(计时器)配置
*  */
        public void TimerConfig(int TimerTic)
        {
            /* 获取timer对象 */
            System.Timers.Timer ATimer = new System.Timers.Timer(TimerTic);
            ATimer.AutoReset = true;//自动回填
            ATimer.Elapsed += new System.Timers.ElapsedEventHandler(TimerEvent);
            ATimer.Enabled = true;//使能时钟
        }

        /*FuncTip 
* 
* @Name:TimerEvent
* @Arg:通用写法
* @Func:计时器事件响应函数
* 清空绘图区图像
* 读取串口数据
* 绘制新数据图像
*  */
        public void TimerEvent(object sender, ElapsedEventArgs e)
        {

            if (!ShowOrNot)
                return;

            /* 更新ylocs */
            //清空图板
            {
                Graphics ForNext = CreateGraphics();
                PointF[] points = new PointF[TableLength];
                PointF[] pointsForCh1 = new PointF[TableLength];
                PointF[] pointsForCh2 = new PointF[TableLength];
                PointF[] pointsForCh3 = new PointF[TableLength];
                for (int jj = 0; jj < TableLength; jj++)//填充本次绘制的部分
                {
                    points[jj] = new PointF((float)jj + TableLeft, ylocs[jj]);
                    pointsForCh1[jj] = new PointF((float)jj + TableLeft, ylocsOfCh1[jj]);
                    pointsForCh2[jj] = new PointF((float)jj + TableLeft, ylocsOfCh2[jj]);
                    pointsForCh3[jj] = new PointF((float)jj + TableLeft, ylocsOfCh3[jj]);
                }

                ForNext.PageUnit = GraphicsUnit.Millimeter;
                //ForNext.DrawCurve(new Pen(this.BackColor, 5F), points);
                ForNext.DrawCurve(new Pen(this.BackColor, 5F), pointsForCh1);
                ForNext.DrawCurve(new Pen(this.BackColor, 5F), pointsForCh2);
                ForNext.DrawCurve(new Pen(this.BackColor, 5F), pointsForCh3);
                /* 获取y坐标数据到ylocs[]  -- GetData() */
                //RandYlocs();//-测试阶段用randylocs
                ReadData();
            }

            /* 按TIMENOW特征绘图 */

            /*
                * 绘图方式为从低到高刷新图样
                * TIMENOW作为刷新尺度的标定
            */

            /* 按参数绘制数据对应图像 */
            //if(TIMENOW<TableLength-3)//3是前后两种颜色曲线的隔离区-否则“清空”操作不好做
            MkPntAndDraw();

        }
     
       /*FuncTip 
* 
* @Name:MkPntAndDraw
* @Arg:None
* @Func:在TimerEvent中被调用
* 将串口数据转换成绘图区坐标点
* 加载到ylocsofChannelX中
*  */
        public void MkPntAndDraw()
        {
            DrawTable();
            PointF[] points = new PointF[TableLength];
            PointF[] pointsForCh1 = new PointF[TableLength];
            PointF[] pointsForCh2 = new PointF[TableLength];
            PointF[] pointsForCh3 = new PointF[TableLength];
            for (int jj = 0; jj < TableLength; jj++)//填充本次绘制的部分
            {
                points[jj] = new PointF((float)jj + TableLeft, ylocs[jj]);
                pointsForCh1[jj] = new PointF((float)jj+TableLeft,ylocsOfCh1[jj]);
                pointsForCh2[jj] = new PointF((float)jj + TableLeft, ylocsOfCh2[jj]);
                pointsForCh3[jj] = new PointF((float)jj + TableLeft, ylocsOfCh3[jj]);
            }
            /* 两种色笔 */
            Pen RedPen = new Pen(Color.Red, 0.5F);
            Pen GreenPen = new Pen(Color.Green, 0.5F);
            /* 获取 graphis实列对象 -- 用于调用drawCurve()  */
            Graphics Drawer = CreateGraphics();
            Drawer.PageUnit = GraphicsUnit.Millimeter;//以毫米为单位绘制图形
            //Drawer.DrawCurve(GreenPen, points);
            Drawer.DrawCurve(GreenPen, pointsForCh1);
            Drawer.DrawCurve(GreenPen, pointsForCh2);
            Drawer.DrawCurve(GreenPen, pointsForCh3);
            Drawer.Dispose();

        }


        /* ---------B-串口通信---------- */

   
        /*VarcTip 
* 
* @Name:_SerialPort
* @Func:串口通信封装类 对象实例
* 用于读取串口数据
*  */
        System.IO.Ports.SerialPort _serialPort = new SerialPort();
     
        /*FuncTip 
* 
* @Name:PortConfig
* @Arg:BaudRate 串口的波特率
* @Func:配置串口
*  */
        public void PortConfig(int BaudRate)///需要读取数据--使用thread类 多线程 - 再看看哦
        {
            //配置COM口参数
            /* 端口名  串口在连接后才可被检测到 */
            try
            {
                string[] portnames = SerialPort.GetPortNames();
                _serialPort.PortName = portnames[0];
            }
            catch (Exception e)
            {
                MessageBox.Show("未在COM口检测到设备,请连接串口通信设备后重新启动应用程序n" + e.ToString());
            }

            /* 波特率 */
            _serialPort.BaudRate = BaudRate;
            /* 数据位 */
            _serialPort.DataBits = 8;
            /* 校验位 */
            _serialPort.Parity = Parity.None;
            /* 停止位 */
            _serialPort.StopBits = StopBits.One;
            /* 配置COM口超时参数 */
            _serialPort.ReadTimeout = SerialPort.InfiniteTimeout;
            _serialPort.WriteTimeout = SerialPort.InfiniteTimeout;

            /* 打开COM口 */
            _serialPort.Open();
        }

        /*FuncTip 
 * 
* @Name:ReadData
* @Arg:None
* @Func:读取数据到ylocs
*  */
        public void ReadData()
        {
            byte[] buffer = new byte[TableLength * 4];/* (通道数3+起始标志1)四个 */
            _serialPort.Read(buffer, 0, TableLength * 4);
            int ptrForYlocs = 0;
            /* 将byte数据转换成int16(short)类型 */
            //for(int ptr = 0; ptr+2 < buffer.Length; ptr +=2){
            for (int ptr = 0; ptr < ylocs.Length; ptr++)
            {
                ylocs[ptrForYlocs] = buffer[ptr];//BitConverter.ToInt16(buffer,ptr);
                ptrForYlocs++;
            }
            //MessageBox.Show(ylocs[0].ToString());
            /* 将ylocs中的数数据分配到各个通道的缓冲区 */

            /**使用readInt方法读取数据到ylocs,已经废弃  **/
            /**ylocs[ptr] = ReadInt() % (TableHeight - 5) + TableTop;**/

            /* 装填ylocs到各个通道的缓冲区(ptrforchX) */
            YlocsOfChannlesInload();

            /* 清空_serialport数据缓冲区 */
            _serialPort.DiscardInBuffer();
            _serialPort.DiscardOutBuffer();
        }

        /*FuncTip 
 * 
* @Name:YlocsOfChannlesInload
* @Arg:None
* @Func:将ylocs的数据加载到各通道缓冲区ylocsofChannelX
* 下位机发送数据格式:
* —————————————————————
* 标志数据|CH1数据|CH2数据|CH3数据|标志数据...
* —————————————————————
* 数据长度:8bits
* 建议二进制形式发送
* 如使用标准库printf
* 建议采用%c格式
*  */
        private void YlocsOfChannlesInload()
        {
            short ptrofylocsstart = 0;/* 数据开始位置标志,找到第一个255的位置 */
            /* 检索第一个数据包&找到刷新后第一个完整数据包的起始位置 */
            while ((ptrofylocsstart < 5) && (ylocs[ptrofylocsstart] != 88))
            {
                ptrofylocsstart++;
            }
            int ptrforinload = 0;/* 装填数据时的迭代器,每个channel都re0 */
            for (int ptrforch1 = ptrofylocsstart + 1; ptrforch1 + 4 < ylocs.Length; ptrforch1 += 4)
            {
                ylocsOfCh1[ptrforinload] = ylocs[ptrforch1] % (TableHeight / 3) + TableTop;
                ptrforinload++;
            }
            ptrforinload = 0;
            for (int ptrforch2 = ptrofylocsstart + 2; ptrforch2 + 4 < ylocs.Length; ptrforch2 += 4)
            {
                ylocsOfCh2[ptrforinload] = ylocs[ptrforch2] % (TableHeight / 3) + TableTop + TableHeight / 3;
                ptrforinload++;
            }
            ptrforinload = 0;
            for (int ptrforch3 = ptrofylocsstart + 3; ptrforch3 + 4 < ylocs.Length; ptrforch3 += 4)
            {
                ylocsOfCh3[ptrforinload] = ylocs[ptrforch3] % (TableHeight / 3) + TableTop + 2 * TableHeight / 3;
                ptrforinload++;
            }
            for (int ptrforfinalPoints = TableLength - 1; ptrforfinalPoints >= TableLength - 2; ptrforfinalPoints--)
            {
                ylocsOfCh1[ptrforfinalPoints] = TableTop;
                ylocsOfCh2[ptrforfinalPoints] = TableTop + TableHeight / 3;
                ylocsOfCh3[ptrforfinalPoints] = TableTop + 2 * TableHeight / 3;
            }
        }
        
    }

}



最后

以上就是可靠金鱼为你收集整理的C#三通道示波器-串口通信的全部内容,希望文章能够帮你解决C#三通道示波器-串口通信所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部