首页 > 学院 > 开发设计 > 正文

串口通信--控制舵机运动

2019-11-17 03:12:24
字体:
来源:转载
供稿:网友

串口通信--控制舵机运动

界面部分使用krytonToolKit开发,整个软件实现了串口通信,并且控制四个自由度的舵机运动。

整个软件使用多线程开发,采集舵机指令保存到TXT文档中,然后调用TXT文档再现舵机运动过程,软件界面如下:

优化之后的界面 如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.IO.Ports;using System.Windows.Forms;using System.Text.RegularExPRessions;using System.Threading;using System.IO;//DotNetMagicusing Crownwood.DotNetMagic;using Crownwood.DotNetMagic.Common;using Crownwood.DotNetMagic.Controls;using Crownwood.DotNetMagic.Docking;using Crownwood.DotNetMagic.Forms;using System.Runtime.InteropServices;using System.Collections;namespace ComAssistant{ public partial class ComAssistantForm : DotNetMagicForm { private int received_count = 0;//接收计数 private long send_count = 0;//发送计数 private bool Listening = false;//是否没有执行完invoke相关操作 //private bool Closing = false;//是否正在关闭串口,执行application.DoEvents,并阻止再次invoke private bool Closing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke private bool Query = false;//查询状态 private List<byte> buffer = new List<byte>(4096);//默认分配1页内存,并始终限制不允许超过 private byte[] binary_data_1 = new byte[10];//FF FF 01 06 00 B1 0A 00 00 3D List<Array> dataList = new List<Array>(); //数据再现 string FILE_INFO_NAME = "FileInfo.txt"; private bool kaiguan = true; private bool openClose = true; string strShow = ""; public ComAssistantForm() { InitializeComponent(); } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { //返回指令格式:FF FF 01 06 00 B1 0A 00 00 3D , 其中B1 0A为ID为1的舵机当前位置,00 00为其当前速度 // 第2位是舵机,5、6位是位置,7、8位为速度 if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环 try { Listening = true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。 int n = serialPort1.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致 byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据 serialPort1.Read(buf, 0, n);//读取缓冲数据 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// //<协议解析> //1.缓存数据 buffer.AddRange(buf); //2.完整性判断 while (buffer.Count >= 10)//至少要包含头(2字节)+长度(7字节)+校验(1字节) { if (buffer[0] == 0xFF && buffer[1] == 0xFF && buffer[2] == 0xFF) { buffer.RemoveRange(0, 10);//从缓存中移除数据。 continue; } //2.1 查找数据头 if (buffer[0] == 0xFF && buffer[1] == 0xFF&& buffer[2] != 0xFF) { received_count++; //至此,已经被找到了一条完整数据。我们将数据直接分析,或是缓存起来一起分析 buffer.CopyTo(0, binary_data_1, 0, 9);//复制一条完整数据到具体的数据缓存 //3.分析数据 //根据舵机编号分类并存入TXT文件 string zhuanbian = binary_data_1[7].ToString("X2"); if (zhuanbian == "00") { zhuanbian = "01"; } //我们的数据都是定好格式的,所以当我们找到分析出的数据1,就知道固定位置一定是这些数据,我们只要显示就可以了 string data = binary_data_1[2].ToString("X2") + " " + binary_data_1[5].ToString("X2") + " " + binary_data_1[6].ToString("X2") + " " + zhuanbian + " " + binary_data_1[8].ToString("X2"); //更新界面 this.Invoke((EventHandler)(delegate { kryptonRichTextBox1.Text += data + "**"; WriteFile(data); })); if (received_count == 4) { WriteFileLine(); received_count = 0; //更新界面 this.Invoke((EventHandler)(delegate { kryptonRichTextBox1.Text += "/r/n"; })); } buffer.RemoveRange(0, 10);//正确分析一条数据,从缓存中移除数据。 } else { //这里是很重要的,如果数据开始不是头,则删除数据 buffer.RemoveAt(0); } } } catch (Exception) { MessageBox.Show("串口接收数据出错,请查看串口接收指令!", "软件提醒", MessageBoxButtons.OKCancel, MessageBoxIcon.Error); } finally { Listening = false;//我用完了,ui可以关闭串口了。 } } //初始化 private void ComAssistantForm_Load(object sender, EventArgs e) { int ii = 0; foreach (string s in SerialPort.GetPortNames()) { if (ii >= 1) { ktComboBoxCom.Items.Add(s); } ii++; } if (SerialPort.GetPortNames().Length != 0) { ktComboBoxCom.Text = (string)ktComboBoxCom.Items[0]; } //string[] strCom = new string[] { "COM1", "COM2", "COM3", "COM4" }; //ktComboBoxCom.DataSource = strCom; string[] ss = new string[] {"2000000" , "9600", "19200", "57600" }; ktComboBoxBount.DataSource = ss; ktComboBoxJiaoyan.DataSource = Enum.GetNames(typeof(Parity)); ss = new string[] { "5", "6", "7", "8" }; ktComboBoxData.DataSource = ss; ktComboBoxData.Text = "8"; ktComboBoxStop.DataSource = Enum.GetNames(typeof(StopBits)); ktComboBoxStop.Text = Enum.Format(typeof(StopBits), StopBits.One, "G"); kryptonTextBox1.Text = "FF FF 04 04 03 18 00 DC"; try { if (!serialPort1.IsOpen) { serialPort1.PortName = ktComboBoxCom.Text; serialPort1.BaudRate = Convert.ToInt32(ktComboBoxBount.Text); serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), ktComboBoxJiaoyan.Text); serialPort1.DataBits = Int32.Parse(ktComboBoxData.Text); serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), ktComboBoxStop.Text); serialPort1.Encoding = Encoding.GetEncoding("Gb2312"); serialPort1.Open(); pictureBox1.Image = Image.FromFile(Application.StartupPath + "//kai.jpg"); } } catch (Exception) { MessageBox.Show("初始化出问题,请检查串口设备", "软件提醒", MessageBoxButtons.OKCancel, MessageBoxIcon.Error); } } //连接串口 private void ktBtnLink_Click(object sender, EventArgs e) { try { if (!serialPort1.IsOpen) { serialPort1.PortName = ktComboBoxCom.Text; serialPort1.BaudRate = Convert.ToInt32(ktComboBoxBount.Text); serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), ktComboBoxJiaoyan.Text); serialPort1.DataBits = Int32.Parse(ktComboBoxData.Text); serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), ktComboBoxStop.Text); serialPort1.Encoding = Encoding.GetEncoding("Gb2312"); serialPort1.Open(); pictureBox1.Image = Image.FromFile(Application.StartupPath + "//kai.jpg"); } } catch (Exception) { MessageBox.Show("初始化出问题,请检查串口设备", "软件提醒", MessageBoxButtons.OKCancel, MessageBoxIcon.Error); } } //关闭串口 private void ktBtnClose_Click(object sender, EventArgs e) { try { if (serialPort1.IsOpen) { Closing = true; while (Listening) Application.DoEvents(); serialPort1.Close(); pictureBox1.Image = Image.FromFile(Application.StartupPath + "//guan.jpg"); //打开时点击,则关闭串口 Closing = false; } } catch (System.Exception ex) { MessageBox.Show("串口关闭出错,请检查串口连接!", "软件提醒", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); } } //发送数据 private void ktBtnSend_Click(object sender, EventArgs e) { if (!serialPort1.IsOpen) { MessageBox.Show("请打开串口!", "软件提醒", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); } else { string content = kryptonTextBox1.Text; byte[] bytes = MyClass.StringToHex(content); serialPort1.Write(bytes, 0, bytes.Length); } } //接收数据 private void ktBtnAccept_Click(object sender, EventArgs e) { //Closing = false; int n = serialPort1.BytesToRead; byte[] dbs = new byte[n]; int len = serialPort1.Read(dbs, 0, n); int[] num = new int[len]; string show = ""; show = MyClass.byteToHexStr(dbs); kryptonRichTextBox1.Text += show; } //清空数据 privat
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表