神农鼎 发表于 2026-6-28 23:16:32

STC8H8K64U如何做个HID鼠标

<p>STC8H8K64U如何做个HID鼠标</p>
<p><img src="data/attachment/forum/202606/28/231558c4k11xxlac3uxmbd.png" alt="image.png" title="image.png" /></p>

神农鼎 发表于 2026-6-28 23:17:49

<p>好的!STC8H8K64U 也内置 <strong>USB 2.0-FS</strong> 硬件,完全支持做 HID 鼠标。和 STC32G 思路类似,但有几个关键区别(Keil C51、USB 初始化方式等),下面给你梳理好。</p>
<hr />
<h2>🖱️ STC8H8K64U HID 鼠标 — 完整实现指南</h2>
<h3>第1步:硬件连接</h3>
<pre><code>电脑 USB─┬─ DP → P3.0 (USB_D+)
         ├─ DN → P3.1 (USB_D-)
         ├─ VCC → 3.3V/5V
         └─ GND → GND

按键(接任意IO,以P1为例):
P1.0 → 左移    P1.1 → 右移
P1.2 → 上移    P1.3 → 下移
P1.4 → 左键    P1.5 → 右键    P1.6 → 中键
</code></pre>
<h3>第2步:获取官方范例(最快方式)</h3>
<p>STC8H8K64U 实验箱有 <strong>现成的 HID 鼠标范例</strong>,可以直接用:</p>
<blockquote>
<p><strong>官方路径:</strong> 官网资料 → <strong>STC8H8K64U实验箱-V9.3程序包</strong> → 找到 <strong>&quot;63-基于HID协议的USB鼠标范例&quot;</strong></p>
</blockquote>
<p>也可以在 <strong>AiCube-ISP 下载软件</strong> → 选择 STC8H8K64U → 范例程序 → 找到该例程直接下载。</p>
<h3>第3步:两种实现方式</h3>
<hr />
<h2>🔵 方式一:使用 USB-HID 库(推荐,代码极简)</h2>
<p>STC8H 提供了封装好的 USB 库(手册第3章),支持 <strong>USB-HID 库函数</strong>,使用 <code>usb_init()</code> + <code>USB_SendData()</code> 即可。</p>
<p><strong>所需文件(通过 AiCube-ISP 下载):</strong></p>
<ul>
<li><code>stc8h.h</code> — 头文件</li>
<li><code>ai_usb.h</code> / <code>stc32_stc8_usb.h</code> — USB 库头文件</li>
<li>USB-HID 库文件(<code>.lib</code>)</li>
</ul>
<p><strong>完整示例代码:</strong></p>
<pre><code class="language-c">#include &quot;stc8h.h&quot;
#include &quot;ai_usb.h&quot;

// 按键定义
#define KEY_LEFT   P10
#define KEY_RIGHTP11
#define KEY_UP   P12
#define KEY_DOWN   P13
#define KEY_BTN_LP14
#define KEY_BTN_RP15
#define KEY_BTN_MP16

// 鼠标数据缓冲区(4字节)
u8 xdata MouseBuf;// [按键, X位移, Y位移, 滚轮]

void main()
{
    // 初始化I/O
    P0M0 = 0; P0M1 = 0;
    P1M0 = 0; P1M1 = 0;
    P2M0 = 0; P2M1 = 0;
    P3M0 = 0; P3M1 = 0;
    P4M0 = 0; P4M1 = 0;
    P5M0 = 0; P5M1 = 0;

    usb_init();   // USB初始化(包含48MHz时钟开启)
    EA = 1;         // 开总中断

    while(1)
    {
      // 等待USB枚举完成
      if(DeviceState != DEVSTATE_CONFIGURED) continue;
      
      // 读取按键 → 填写MouseBuf
      MouseBuf = 0;
      if(KEY_BTN_L) MouseBuf |= 0x01;   // 左键
      if(KEY_BTN_R) MouseBuf |= 0x02;   // 右键
      if(KEY_BTN_M) MouseBuf |= 0x04;   // 中键
      
      MouseBuf = 0;// X
      if(KEY_LEFT)MouseBuf = -5;
      if(KEY_RIGHT) MouseBuf =5;
      
      MouseBuf = 0;// Y
      if(KEY_UP)   MouseBuf = -5;// 负=上移
      if(KEY_DOWN) MouseBuf =5;
      
      MouseBuf = 0;// 滚轮
      
      // 将4字节鼠标数据发送到PC
      USB_SendData(MouseBuf, 4);
      
      // 注意:HID一次固定发64字节,库内部会补0
      // 发完后稍作延时,避免连续发太快
      delay_ms(10);
    }
}
</code></pre>
<blockquote>
<p>⚠️ <strong>注意:</strong> 使用 USB-HID 库时,<code>USB_SendData()</code> 每次发送固定 <strong>64字节</strong>(HID 报告最大长度),库内部会自动将你的 4 字节数据补 0 到 64 字节后发送。</p>
</blockquote>
<p><strong>库方式的优点:</strong></p>
<ul>
<li>只需调用 <code>usb_init()</code> 和 <code>USB_SendData()</code>,无需关心 USB 枚举细节</li>
<li>内置描述符自动配置</li>
<li>支持 printf_usb 调试输出</li>
</ul>
<hr />
<h2>🔵 方式二:寄存器操作(更底层,灵活修改描述符)</h2>
<p>数据手册 <strong>第28.5.1节《HID人机接口设备范例》</strong> 给出了完整的寄存器级框架,适合需要自定义 VID/PID/描述符的场景。</p>
<p><strong>核心区别(与方式一对比):</strong></p>
<table>
<thead>
<tr>
<th>项目</th>
<th>库方式</th>
<th>寄存器方式</th>
</tr>
</thead>
<tbody>
<tr>
<td>代码量</td>
<td>几十行</td>
<td>几百行</td>
</tr>
<tr>
<td>需自行写中断</td>
<td>❌ 不需要</td>
<td>✅ 需要写 USB 中断 (<code>interrupt 25</code>)</td>
</tr>
<tr>
<td>可定制描述符</td>
<td>有限</td>
<td>✅ 完全可控</td>
</tr>
<tr>
<td>官方参考</td>
<td>手册第3章</td>
<td>手册第28.5.1节 + 28.5.5节</td>
</tr>
</tbody>
</table>
<p><strong>关键修改点(在28.5.1节范例基础上改):</strong></p>
<p>① <strong>USB 初始化</strong>(STC8H 和 STC32G 不同!):</p>
<pre><code class="language-c">void UsbInit()
{
    P3M0 = 0x00;
    P3M1 = 0x03;      // P3.0/P3.1 设置为高阻(USB专用)

    IRC48MCR = 0x80;    // ⭐ 开启内部48MHz(STC8H用这个,不是PLLCR!)
    while (!(IRC48MCR &amp; 0x01));// 等待48MHz稳定

    USBCLK = 0x00;
    USBCON = 0x90;      // 使能USB

    // ... 后续寄存器配置同范例 ...
}
</code></pre>
<p>② <strong>HID Report Descriptor 改为鼠标协议</strong>(范例中默认是 Consumer Control,需改为 Mouse):</p>
<pre><code class="language-c">char code HIDREPORTDESC = {
    0x05, 0x01,         // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,         // USAGE (Mouse)
    0xa1, 0x01,         // COLLECTION (Application)
    0x09, 0x01,         //   USAGE (Pointer)
    0xa1, 0x00,         //   COLLECTION (Physical)
    // ---- 3个按键(绝对值) ----
    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)
    // ---- X/Y/Wheel(相对位移) ----
    0x05, 0x01,         //   USAGE_PAGE (Generic Desktop)
    0x09, 0x30,         //   USAGE (X)
    0x09, 0x31,         //   USAGE (Y)
    0x09, 0x38,         //   USAGE (Wheel)
    0x15, 0x81,         //   LOGICAL_MINIMUM (-127)
    0x25, 0x7f,         //   LOGICAL_MAXIMUM (127)
    0x75, 0x08,         //   REPORT_SIZE (8)
    0x95, 0x03,         //   REPORT_COUNT (3)
    0x81, 0x06,         //   INPUT (Data,Var,Rel)
    0xc0,               //   END_COLLECTION
    0xc0                // END_COLLECTION
};
</code></pre>
<p>③ <strong>在主循环或中断中发送鼠标数据</strong>(写端点1 FIFO):</p>
<pre><code class="language-c">BYTE MouseData;

// 填写数据
MouseData = 按键状态;
MouseData = X位移量;   // 有符号
MouseData = Y位移量;   // 有符号
MouseData = 0;

// 发送
WriteReg(INDEX, 1);
WriteFifo(FIFO1, MouseData, 4);
WriteReg(INCSR1, INIPRDY);   // 通知USB主机取数据
</code></pre>
<hr />
<h3>STC8H8K64U vs STC32G12K128 关键区别一览</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>STC8H8K64U</th>
<th>STC32G12K128</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>内核</strong></td>
<td>8051 (C51编译器)</td>
<td>C251 (C251编译器)</td>
</tr>
<tr>
<td><strong>头文件</strong></td>
<td><code>#include &quot;stc8h.h&quot;</code></td>
<td><code>#include &quot;stc32g.h&quot;</code></td>
</tr>
<tr>
<td><strong>XFR使能</strong></td>
<td>`P_SW2</td>
<td>= 0x80;`</td>
</tr>
<tr>
<td><strong>USB时钟初始化</strong></td>
<td><code>IRC48MCR = 0x80;</code> + 等待标志位</td>
<td><code>PLLCR</code> + <code>CLKSEL</code> 配置</td>
</tr>
<tr>
<td><strong>USB库头文件</strong></td>
<td><code>ai_usb.h</code> / <code>stc32_stc8_usb.h</code></td>
<td><code>usb.h</code> + <code>usb_req_class.h</code></td>
</tr>
<tr>
<td><strong>下载频率</strong></td>
<td>任意频率(USB用独立48MHz)</td>
<td>需设<strong>24MHz</strong>(USB时钟从系统时钟PLL得来)</td>
</tr>
<tr>
<td><strong>官方鼠标例程</strong></td>
<td><code>63-基于HID协议的USB鼠标范例</code></td>
<td><code>72-基于HID协议的USB鼠标范例</code></td>
</tr>
</tbody>
</table>
<hr />
<h3>下载设置</h3>
<p>在 <strong>AiCube-ISP</strong> 中选择:</p>
<table>
<thead>
<tr>
<th>项目</th>
<th>设置</th>
</tr>
</thead>
<tbody>
<tr>
<td>芯片型号</td>
<td><strong>STC8H8K64U</strong></td>
</tr>
<tr>
<td>IRC 频率</td>
<td>任意(如 11.0592MHz),USB 时钟是独立的 48MHz</td>
</tr>
<tr>
<td>下载方式</td>
<td>按住 P3.2 → 上电 → 松手 → 点击下载</td>
</tr>
</tbody>
</table>
<blockquote>
<p>💡 <strong>STC8H8K64U 的一大优势:</strong> USB 有独立的 <strong>48MHz 内部振荡器</strong>(IRC48M),所以系统主频可以随意设置(如 11.0592MHz 方便串口波特率),不影响 USB 工作,比 STC32G 更灵活。</p>
</blockquote>
<hr />
<p><strong>总结一句话:</strong> 去 AiCube-ISP 下载 <strong>&quot;63-基于HID协议的USB鼠标范例&quot;</strong>,这是 STC8H8K64U 实验箱的官方例程,改按键引脚即可用。如果希望代码更精简,用 <strong>USB-HID 库方式</strong>,<code>usb_init()</code> + <code>USB_SendData()</code> 两行核心函数就能跑起来。🎯</p>
<hr />
<p><a href="https://www.stcaimcu.com/plugin.php?id=twpx_xunsearch&amp;mod=forum&amp;q=STC8H8K64U%E5%A6%82%E4%BD%95%E5%81%9A%E4%B8%AAHID%E9%BC%A0%E6%A0%87&amp;f=_all&amp;m=yes&amp;syn=yes&amp;s=relevance&amp;fid=0">🔍 搜索 &quot;STC8H8K64U如何做个HID鼠标&quot;</a></p>
<p><strong>📌 相关论坛讨论</strong></p>
<ol>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=16791&amp;highlight=STC8H8K64U%E5%A6%82%E4%BD%95%E5%81%9A%E4%B8%AAHID%E9%BC%A0%E6%A0%87&amp;page=6&amp;extra=#pid185721">USB拓展库及使用示例 | 本贴 咨询 USB,基本帮您把USB程序开发完成</a></li>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=22536&amp;highlight=STC8H8K64U%E5%A6%82%E4%BD%95%E5%81%9A%E4%B8%AAHID%E9%BC%A0%E6%A0%87&amp;page=1&amp;extra=#pid208223">AI8H8K64U和32G64K关于USB键盘的问题</a></li>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=2416&amp;highlight=STC8H8K64U%E5%A6%82%E4%BD%95%E5%81%9A%E4%B8%AAHID%E9%BC%A0%E6%A0%87&amp;page=1&amp;extra=#pid16379">调试 STC8H8K64U的USB程序时,如何进行仿真?</a></li>
</ol>
页: [1]
查看完整版本: STC8H8K64U如何做个HID鼠标