| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- using System;
- using System.Windows.Forms;
- using System.Drawing;
- using CCDCount.DLL.CanBus;
- namespace CanOpenSlaveTest
- {
- /// <summary>
- /// CANopen从站设备测试界面
- /// </summary>
- public class SlaveTestForm : Form
- {
- private CanOpenSlaveDevice m_slaveDevice;
-
- // UI控件
- private GroupBox grpDeviceInfo;
- private Label lblNodeId;
- private Label lblState;
- private Label lblStatus;
-
- private GroupBox grpControl;
- private Button btnStart;
- private Button btnStop;
- private Button btnSendTpdo1;
- private Button btnSendTpdo2;
- private Button btnSendAllTpdos;
-
- private GroupBox grpHeartbeat;
- private NumericUpDown nudHeartbeatTime;
- private Button btnConfigureHeartbeat;
-
- private TextBox txtLog;
-
- private System.Windows.Forms.Timer m_updateTimer;
-
- public SlaveTestForm()
- {
- InitializeComponent();
-
- // 在构造函数中创建从站设备(避免设计器错误)
- if (!DesignMode)
- {
- m_slaveDevice = new CanOpenSlaveDevice(nodeId: 1);
-
- // 注册事件
- m_slaveDevice.OnRpdoReceived += SlaveDevice_OnRpdoReceived;
- m_slaveDevice.OnNmtStateChanged += SlaveDevice_OnNmtStateChanged;
- m_slaveDevice.OnSdoReadRequest += SlaveDevice_OnSdoReadRequest;
- m_slaveDevice.OnSdoWriteRequest += SlaveDevice_OnSdoWriteRequest;
-
- // 初始化日志
- AppendLog("CANopen从站测试程序已启动");
- AppendLog("节点ID: " + m_slaveDevice.NodeId.ToString());
- AppendLog("点击'启动从站'按钮开始测试\n");
- }
- }
-
- private void InitializeComponent()
- {
- this.Text = "CANopen从站设备测试";
- this.Size = new Size(800, 600);
- this.StartPosition = FormStartPosition.CenterScreen;
-
- // 设备信息组
- grpDeviceInfo = new GroupBox();
- grpDeviceInfo.Text = "设备信息";
- grpDeviceInfo.Location = new Point(10, 10);
- grpDeviceInfo.Size = new Size(380, 100);
-
- lblNodeId = new Label();
- lblNodeId.Text = "节点ID: -";
- lblNodeId.Location = new Point(10, 25);
- lblNodeId.AutoSize = true;
-
- lblState = new Label();
- lblState.Text = "状态: -";
- lblState.Location = new Point(10, 50);
- lblState.AutoSize = true;
-
- lblStatus = new Label();
- lblStatus.Text = "运行状态: 未启动";
- lblStatus.Location = new Point(10, 75);
- lblStatus.AutoSize = true;
-
- grpDeviceInfo.Controls.AddRange(new Control[] { lblNodeId, lblState, lblStatus });
-
- // 控制组
- grpControl = new GroupBox();
- grpControl.Text = "控制";
- grpControl.Location = new Point(400, 10);
- grpControl.Size = new Size(380, 100);
-
- btnStart = new Button();
- btnStart.Text = "启动从站";
- btnStart.Location = new Point(10, 25);
- btnStart.Size = new Size(100, 30);
- btnStart.Click += BtnStart_Click;
-
- btnStop = new Button();
- btnStop.Text = "停止从站";
- btnStop.Location = new Point(120, 25);
- btnStop.Size = new Size(100, 30);
- btnStop.Click += BtnStop_Click;
- btnStop.Enabled = false;
-
- btnSendTpdo1 = new Button();
- btnSendTpdo1.Text = "发送TPDO1";
- btnSendTpdo1.Location = new Point(10, 60);
- btnSendTpdo1.Size = new Size(100, 30);
- btnSendTpdo1.Click += BtnSendTpdo1_Click;
- btnSendTpdo1.Enabled = false;
-
- btnSendTpdo2 = new Button();
- btnSendTpdo2.Text = "发送TPDO2";
- btnSendTpdo2.Location = new Point(120, 60);
- btnSendTpdo2.Size = new Size(100, 30);
- btnSendTpdo2.Click += BtnSendTpdo2_Click;
- btnSendTpdo2.Enabled = false;
-
- btnSendAllTpdos = new Button();
- btnSendAllTpdos.Text = "发送所有TPDO";
- btnSendAllTpdos.Location = new Point(230, 60);
- btnSendAllTpdos.Size = new Size(120, 30);
- btnSendAllTpdos.Click += BtnSendAllTpdos_Click;
- btnSendAllTpdos.Enabled = false;
-
- grpControl.Controls.AddRange(new Control[] {
- btnStart, btnStop, btnSendTpdo1, btnSendTpdo2, btnSendAllTpdos
- });
-
- // 心跳配置组
- grpHeartbeat = new GroupBox();
- grpHeartbeat.Text = "心跳配置";
- grpHeartbeat.Location = new Point(10, 120);
- grpHeartbeat.Size = new Size(770, 60);
-
- Label lblHeartbeat = new Label();
- lblHeartbeat.Text = "心跳时间(ms):";
- lblHeartbeat.Location = new Point(10, 25);
- lblHeartbeat.AutoSize = true;
-
- nudHeartbeatTime = new NumericUpDown();
- nudHeartbeatTime.Location = new Point(110, 22);
- nudHeartbeatTime.Size = new Size(100, 25);
- nudHeartbeatTime.Minimum = 0;
- nudHeartbeatTime.Maximum = 10000;
- nudHeartbeatTime.Value = 100;
-
- btnConfigureHeartbeat = new Button();
- btnConfigureHeartbeat.Text = "配置心跳";
- btnConfigureHeartbeat.Location = new Point(220, 20);
- btnConfigureHeartbeat.Size = new Size(100, 30);
- btnConfigureHeartbeat.Click += BtnConfigureHeartbeat_Click;
- btnConfigureHeartbeat.Enabled = false;
-
- grpHeartbeat.Controls.AddRange(new Control[] { lblHeartbeat, nudHeartbeatTime, btnConfigureHeartbeat });
-
- // 日志显示
- txtLog = new TextBox();
- txtLog.Multiline = true;
- txtLog.ScrollBars = ScrollBars.Vertical;
- txtLog.ReadOnly = true;
- txtLog.Location = new Point(10, 190);
- txtLog.Size = new Size(770, 360);
- // 使用支持中文的字体(微软雅黑或宋体)
- txtLog.Font = new Font("Microsoft YaHei", 9);
- txtLog.ForeColor = Color.Black;
- txtLog.BackColor = Color.White;
-
- // 添加控件到窗体
- this.Controls.AddRange(new Control[] {
- grpDeviceInfo, grpControl, grpHeartbeat, txtLog
- });
-
- // 更新定时器
- m_updateTimer = new System.Windows.Forms.Timer();
- m_updateTimer.Interval = 500;
- m_updateTimer.Tick += UpdateTimer_Tick;
- m_updateTimer.Start();
- }
-
- private void BtnStart_Click(object sender, EventArgs e)
- {
- try
- {
- AppendLog("正在启动从站...");
-
- if (m_slaveDevice.Start(CanBaudRate.BaudRate_1M))
- {
- AppendLog("✓ 从站启动成功");
-
- btnStart.Enabled = false;
- btnStop.Enabled = true;
- btnSendTpdo1.Enabled = true;
- btnSendTpdo2.Enabled = true;
- btnSendAllTpdos.Enabled = true;
- btnConfigureHeartbeat.Enabled = true;
-
- UpdateDeviceInfo();
- }
- else
- {
- AppendLog("✗ 从站启动失败");
- MessageBox.Show("启动失败!请检查CAN设备连接。", "错误",
- MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 启动错误: {ex.Message}");
- MessageBox.Show(ex.Message, "错误",
- MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
-
- private void BtnStop_Click(object sender, EventArgs e)
- {
- try
- {
- AppendLog("正在停止从站...");
- m_slaveDevice.Stop();
- AppendLog("✓ 从站已停止");
-
- btnStart.Enabled = true;
- btnStop.Enabled = false;
- btnSendTpdo1.Enabled = false;
- btnSendTpdo2.Enabled = false;
- btnSendAllTpdos.Enabled = false;
- btnConfigureHeartbeat.Enabled = false;
-
- UpdateDeviceInfo();
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 停止错误: {ex.Message}");
- }
- }
-
- private void BtnSendTpdo1_Click(object sender, EventArgs e)
- {
- try
- {
- m_slaveDevice.SendTpdo(1);
- AppendLog("→ 已发送TPDO1");
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 发送TPDO1失败: {ex.Message}");
- }
- }
-
- private void BtnSendTpdo2_Click(object sender, EventArgs e)
- {
- try
- {
- m_slaveDevice.SendTpdo(2);
- AppendLog("→ 已发送TPDO2");
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 发送TPDO2失败: {ex.Message}");
- }
- }
-
- private void BtnSendAllTpdos_Click(object sender, EventArgs e)
- {
- try
- {
- m_slaveDevice.SendAllTpdos();
- AppendLog("→ 已发送所有TPDO");
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 发送TPDO失败: {ex.Message}");
- }
- }
-
- private void BtnConfigureHeartbeat_Click(object sender, EventArgs e)
- {
- try
- {
- ushort heartbeatTime = (ushort)nudHeartbeatTime.Value;
- m_slaveDevice.ConfigureHeartbeat(heartbeatTime);
- AppendLog($"✓ 心跳已配置: {heartbeatTime}ms");
- }
- catch (Exception ex)
- {
- AppendLog($"✗ 配置心跳失败: {ex.Message}");
- }
- }
-
- private void SlaveDevice_OnRpdoReceived(byte nodeId, byte pdoNumber, byte[] data)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(() =>
- SlaveDevice_OnRpdoReceived(nodeId, pdoNumber, data)));
- return;
- }
-
- string dataStr = BitConverter.ToString(data).Replace("-", " ");
- AppendLog($"← 收到RPDO{pdoNumber} [节点{nodeId}]: {dataStr}");
- }
-
- private void SlaveDevice_OnNmtStateChanged(NmtState oldState, NmtState newState)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(() =>
- SlaveDevice_OnNmtStateChanged(oldState, newState)));
- return;
- }
-
- AppendLog($"⟳ NMT状态改变: {oldState} → {newState}");
- UpdateDeviceInfo();
- }
-
- private void SlaveDevice_OnSdoReadRequest(byte nodeId, ushort index, byte subIndex)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(() =>
- SlaveDevice_OnSdoReadRequest(nodeId, index, subIndex)));
- return;
- }
-
- AppendLog($"? SDO读取请求: 索引0x{index:X4}, 子索引{subIndex}");
- }
-
- private void SlaveDevice_OnSdoWriteRequest(byte nodeId, ushort index, byte subIndex, uint value)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(() =>
- SlaveDevice_OnSdoWriteRequest(nodeId, index, subIndex, value)));
- return;
- }
-
- AppendLog($"↓ SDO写入请求: 索引0x{index:X4}, 子索引{subIndex}, 值0x{value:X8}");
- }
-
- private void UpdateTimer_Tick(object sender, EventArgs e)
- {
- UpdateDeviceInfo();
- }
-
- private void UpdateDeviceInfo()
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(UpdateDeviceInfo));
- return;
- }
-
- lblNodeId.Text = $"节点ID: {m_slaveDevice.NodeId}";
- lblState.Text = $"状态: {m_slaveDevice.CurrentState}";
- lblStatus.Text = $"运行状态: {(m_slaveDevice.IsRunning ? "运行中" : "已停止")}";
- }
-
- private void AppendLog(string message)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action<string>(AppendLog), message);
- return;
- }
-
- string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
- // 使用字符串拼接而非插值,确保兼容性
- txtLog.AppendText("[" + timestamp + "] " + message + "\r\n");
-
- // 自动滚动到底部
- txtLog.SelectionStart = txtLog.Text.Length;
- txtLog.ScrollToCaret();
- }
-
- protected override void OnFormClosing(FormClosingEventArgs e)
- {
- if (m_slaveDevice != null)
- {
- m_slaveDevice.Stop();
- m_slaveDevice.Dispose();
- }
-
- m_updateTimer?.Stop();
- m_updateTimer?.Dispose();
-
- base.OnFormClosing(e);
- }
- }
- }
|