You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C# WinForms控制Arduino UNO实现鼠标光标移动模拟?

Arduino UNO模拟鼠标 + WinForms C#控制实现方案

前提说明

Arduino UNO主芯片(ATmega328P)无原生USB控制器,无法直接使用官方Mouse库(该库适用于Leonardo/Micro等带原生USB的板子),需通过V-USB库模拟USB HID设备实现鼠标功能。


Arduino UNO端实现

1. 准备工作

  • 安装V-USB库:在Arduino IDE的库管理器中搜索"V-USB"并安装,或手动下载源码导入。
  • 硬件接线:将UNO的D2引脚接USB D-,D3引脚接USB D+,同时在D+引脚和VCC之间接一个1.5kΩ电阻(具体接线参考V-USB官方文档)。

2. 示例代码

该代码实现串口接收坐标指令、计算相对位移并发送HID鼠标报告:

#include "usbdrv.h"

// HID报告描述符,定义鼠标设备
PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};

static uchar reportBuffer[4]; // 鼠标报告:按键状态 + X/Y位移

void buildReport(char xDelta, char yDelta) {
    reportBuffer[0] = 0; // 无按键按下
    reportBuffer[1] = xDelta;
    reportBuffer[2] = yDelta;
}

usbMsgLen_t usbFunctionSetup(uchar data[8]) {
    usbRequest_t *rq = (usbRequest_t *)data;
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){
        if(rq->bRequest == USBRQ_HID_GET_REPORT){
            usbMsgPtr = reportBuffer;
            return sizeof(reportBuffer);
        }
    }
    return 0;
}

int currentX = 0;
int currentY = 0;

void setup() {
    usbInit();
    usbDeviceDisconnect();
    delay(250);
    usbDeviceConnect();
    Serial.begin(9600); // 开启串口接收C#指令
}

void loop() {
    usbPoll();
    
    if (Serial.available() > 0) {
        String data = Serial.readStringUntil('\n');
        int commaIdx = data.indexOf(',');
        if (commaIdx != -1) {
            int targetX = data.substring(0, commaIdx).toInt();
            int targetY = data.substring(commaIdx + 1).toInt();
            
            // 限制位移在HID允许的范围(-127~127)
            char deltaX = constrain(targetX - currentX, -127, 127);
            char deltaY = constrain(targetY - currentY, -127, 127);
            
            buildReport(deltaX, deltaY);
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
            
            currentX = targetX;
            currentY = targetY;
            delay(10);
        }
    }
}

C# WinForms端实现

1. 核心依赖

使用.NET自带的System.IO.Ports库操作串口,无需额外安装。

2. 示例代码

创建WinForms项目,添加两个文本框(输入X/Y坐标)和一个发送按钮,代码如下:

using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace ArduinoMouseControl
{
    public partial class MainForm : Form
    {
        private readonly SerialPort _serialPort;

        public MainForm()
        {
            InitializeComponent();
            // 替换为你的Arduino COM端口号
            _serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
            try
            {
                _serialPort.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"串口打开失败:{ex.Message}");
            }
        }

        private void btnSendCoords_Click(object sender, EventArgs e)
        {
            if (!_serialPort.IsOpen)
            {
                MessageBox.Show("串口未连接");
                return;
            }

            if (int.TryParse(txtXCoord.Text, out int targetX) && int.TryParse(txtYCoord.Text, out int targetY))
            {
                _serialPort.WriteLine($"{targetX},{targetY}");
            }
            else
            {
                MessageBox.Show("请输入有效的整数坐标");
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_serialPort.IsOpen)
                _serialPort.Close();
        }
    }
}

注意:需在设备管理器中查看Arduino对应的COM端口,替换代码中的COM3。


所需库汇总

  • Arduino端:
    • V-USB:用于UNO模拟USB HID设备;若使用Leonardo/Micro,直接用官方Mouse库即可。
  • C#端:
    • System.IO.Ports:.NET内置串口操作库。

资料获取渠道

  • Arduino官方文档:查阅HID设备开发规范、V-USB库的接线与使用说明。
  • Arduino社区:搜索"UNO USB HID mouse"获取实操案例与问题排查方案。
  • .NET官方文档:查看SerialPort类的API细节,掌握串口读写的最佳实践。
  • 开源代码仓库:参考已有的Arduino鼠标模拟项目和C#串口控制项目,完善实现逻辑。

内容的提问来源于stack exchange,提问作者Dobroslav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:05:02