项目介绍
本项目完成任务一(智能家居):使用Wio Terminal(Seeed Studio)搭载的ATSAMD51P19 MCU最小系统为核心、外围电路模块包括LCD屏、3轴加速度计、microSD Card Slot、两个可编程按键、1个5-Way Switch组成的硬件电路,使用Arduino IDE开发环境,程序设计,制作了一个有线鼠标,连接到计算机可对光标进行操作。应用场景如下所示:
- 适用于演示、远程控制、体感鼠标等场合。
- 可扩展为体感游戏控制器或特殊人群辅助输入设备。
硬件介绍
主芯片ATSAMD51P19是Microchip公司生产的一款高性能微控制器,属于SAMD51系列,具有多种特性:
- 核心架构:采用Arm Cortex-M4F内核,支持DSP指令集,并集成了单精度浮点运算单元(FPU),这使其能够高效地处理复杂计算任务。
- 时钟速度:最高工作频率可达120 MHz,适合需要快速处理能力的应用。
- 存储器:集成高达512 KB的闪存和192 KB的SRAM,满足大多数嵌入式应用的存储需求。
- 外设接口:支持丰富的外设接口,包括I2C、SPI、UART、USB等,方便与其他设备连接。
- 低功耗模式:支持多种低功耗模式,适合对功耗敏感的应用场景。
- 模拟功能:内置多通道12位ADC和DAC模块,可以满足一定的模拟信号采集和输出需求。
- 拓展功能:支持SD/MMC、QSPI接口扩展,提供更多的存储和外设连接能力。
- 安全性:具备基本的安全功能,如安全启动、芯片识别、片上调试锁等。
三轴加速计LIS3DHTR是一款由意法半导体(STMicroelectronics)生产的三轴线性加速度传感器,具有以下主要特性:
- 多轴检测:支持三轴(X、Y、Z)的加速度检测,适合用于手势识别、自由落体检测等应用。
- 量程选项:提供多种量程选择,包括±2g、±4g、±8g和±16g,以适应不同的应用需求。
- 低功耗:设计为低功耗,非常适合电池供电的移动设备,在正常操作模式和低功耗模式下都有优秀的性能。
- 高分辨率:传感器具有高分辨率的输出,能够进行精确的加速度测量,可以达到12位的分辨率。
- 内置FIFO:内置一个FIFO缓冲区,可以减轻主处理器的负担,提高效率,降低功耗。
- 自由落体检测:具备自由落体检测功能,能够用于保护设备在跌落时主动采取措施。
- I²C/SPI接口:支持I²C和SPI数字接口,方便与微控制器进行通信。
- 嵌入式自检:包含自检功能,可以用于系统的自我测试和验证。
- 温度传感器:内置温度传感器,用于环境温度的监测和补偿。
- 耐用性和灵活性:具有较强的抗冲击能力和可编程中断功能,适应不同环境和应用的需求。
2.4''TFT LCD显示屏驱动芯片ILI9341是一款广泛使用的TFT LCD控制器芯片,主要应用于小尺寸彩色显示屏。以下是其主要特性:
- 显示分辨率:支持240x320像素的分辨率,这种分辨率常用于2.2至3.2英寸的屏幕。
- 颜色深度:支持262K和16.7M色彩显示(18位和24位色彩深度),可以提供丰富的色彩表现。
- 接口支持:
- 支持常见的并行接口,如8/9/16/18位的MCU接口。
- 支持串行外围接口(SPI),便于与微控制器通信。
- 内置GRAM:内置显存允许在显示上进行快速的图像操作。
- 偏置和供电电压:通常工作电压为2.5V至3.3V,适合低功耗应用。
- 时序控制器:具有复杂的时序控制功能,可以高度定制化显示方式和刷新速率。
- 命令和寄存器:提供丰富的命令和寄存器设置,允许用户对显示模式和操作进行细粒度控制。
- 触摸屏支持:虽然ILI9341本身不直接支持触摸功能,但常与外部触摸屏控制器配合使用。
- 可视角度和亮度:表现出良好的可视角度和亮度特性,适合各种环境光照条件。
方案框图和项目设计思路介绍
硬件方案框图如图1所示。

图1 硬件方案框图
加速度计(LIS3DHTR)用于检测设备在X、Y方向的加速度,实现鼠标指针的移动;TFT LCD(TFT_eSPI)用于显示UI界面(如图2所示),包括鼠标左右键、滚轮等提示;SD卡用于读取和显示启动logo图片;2来个用户可编程按键用于模拟鼠标左键、右键,5-way switch用于模拟滚轮操作。通过USB HID协议将设备模拟为鼠标。

图2 UI界面
软件流程图和关键代码介绍
软件流程图如图3所示。

图3 软件流程图
关键代码介绍:
硬件初始化配置:依次将KEY_C、KEY_B、5S_UP、5S_DOWN管脚模式设置为输入;启动鼠标控制、启动加速度计,配置加速度计数据速率为25Hz,加速度2g,初始化SD卡,最后初始化TFT屏,显示活动logo图片。
void setup() {
// configure button and switch pins as inputs:
pinMode(WIO_5S_UP, INPUT);
pinMode(WIO_5S_DOWN, INPUT);
pinMode(WIO_KEY_C, INPUT);
pinMode(WIO_KEY_B, INPUT);
//start mouse control
Mouse.begin();
// Start accelerometer
lis.begin(Wire1);
//Configure accelerometer (1Hz up to 5kHz)
lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
lis.setFullScaleRange(LIS3DHTR_RANGE_2G);
//Initialise SD card
if(!SD.begin(SDCARD_SS_PIN, SDCARD_SPI))
{
while (1);
}
tft.begin();
tft.setRotation(3);
drawImage<uint16_t>("logo.bmp", 0, 0);
delay(3000);
}
绘制UI界面
// Drawing UI on TFT LCD
spr.createSprite(TFT_HEIGHT, TFT_WIDTH);
spr.fillSprite(TFT_WHITE);
//Draw header title
spr.fillRect(0,0, 320,50,TFT_BLUE);
spr.setTextSize(4);
spr.setTextColor(TFT_WHITE);
spr.drawString("AIR MOUSE", 50, 10);
//Draw for scroll
spr.setTextSize(3);
spr.setTextColor(TFT_BLACK);
spr.drawString("SCROLL", 110, 130);
spr.drawTriangle(160,70,120,120,200,120,TFT_BLUE);
spr.drawTriangle(160,210,120, 160,200,160,TFT_BLUE);
//Draw for left and right mouse buttons
spr.drawRect(0,50,100,190,TFT_DARKGREEN);
spr.drawString("LEFT", 15, 130);
spr.drawRect(220,50,100,190,TFT_DARKGREEN);
spr.drawString("RIGHT", 228,130);
// push to LCD
spr.pushSprite(0,0);
获取加速度计X、Y值,计算位移,控制鼠标移动。
float x_values = lis.getAccelerationX();
float y_values = lis.getAccelerationY();
//calculate the movement distance based on the acceleration values
int xDistance = (-y_values) * range;
int yDistance = (x_values) * range;
// mouse move
if (xDistance != 0 || yDistance != 0)
{
Mouse.move(xDistance, yDistance, 0);
}
鼠标按键、滚轮控制
// mouse button left click
if (digitalRead(WIO_KEY_C) == LOW)
{
if (!Mouse.isPressed(MOUSE_LEFT))
{
Mouse.click(MOUSE_LEFT);
}
spr.createSprite(TFT_HEIGHT,TFT_WIDTH);
spr.setTextSize(3);
spr.setTextColor(TFT_WHITE);
spr.fillRect(0,50, 100,190, TFT_DARKGREEN);
spr.drawString("LEFT", 15, 130);
spr.pushSprite(0,0);
spr.deleteSprite();
delay(100);
}
else
{
//if the left mouse button is pressed, then release it
if (Mouse.isPressed(MOUSE_LEFT))
{
Mouse.release(MOUSE_LEFT);
}
}
// mouse button right click
if (digitalRead(WIO_KEY_B) == LOW)
{
if (!Mouse.isPressed(MOUSE_RIGHT))
{
Mouse.click(MOUSE_RIGHT);
}
spr.createSprite(TFT_HEIGHT, TFT_WIDTH);
spr.setTextSize(3);
spr.setTextColor(TFT_WHITE);
spr.fillRect(200,50,100,190, TFT_DARKGREEN);
spr.drawString("RIGHT", 228,130);
spr.pushSprite(0,0);
spr.deleteSprite();
delay(100);
}
else
{
// if the mouse is pressed, then release it
if (Mouse.isPressed(MOUSE_RIGHT))
{
Mouse.release(MOUSE_RIGHT);
}
}
// mouse scroll up
if (digitalRead(WIO_5S_UP) == LOW)
{
Mouse.move(0,0,1);
spr.createSprite(TFT_HEIGHT,TFT_WIDTH);
spr.fillTriangle(160,70,120,120,200,120,TFT_BLUE);
spr.pushSprite(0,0);
spr.deleteSprite();
delay(50);
}
// mouse scroll down
if (digitalRead(WIO_5S_DOWN) == LOW)
{
Mouse.move(0,0,-1);
spr.createSprite(TFT_HEIGHT, TFT_WIDTH);
spr.fillTriangle(160,210,120,160,200,160,TFT_BLUE);
spr.pushSprite(0,0);
spr.deleteSprite();
delay(50);
}
功能展示图及说明
功能展示图如图4所示。KEY_C实现鼠标左键,KEY_B实现鼠标右键,5-way switch上下按键实现鼠标滚轮。屏幕水平向前倾斜鼠标向上移动,反之向下移动;屏幕水平向左倾斜实现鼠标左移,反之向右平移。

图4 功能展示图

图5 实物功能展示图
设计中遇到的难题和解决方法
在使用官方提供的脚本进行图像logo格式转换时,由于目录结构不对,导致图像转换失败。使用AI工具即可解决。
心得体会
Arduino资源资源丰富,使用Ardunio可快速实现原型设计与验证。门槛低,学习曲线平缓,对新手特别友好。Seeed文档资料非常全,助力学习好帮手。