一、平台介绍
作为一个嵌入式系统的学习平台,首先要基于核心芯片的核心板的特点以及嵌入式系统的关键知识点来定义这款学习平台:
-
采用树莓派Pico核心芯片RP2040:
-
双核Arm Cortex M0+内核,可以运行到133MHz
- 264KB内存
-
性能强大、高度灵活的可编程IO可用于高速数字接口
-
片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度
-
支持MicroPython、C、C++编程
-
-
板上功能:
-
240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789
-
四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制
-
板上外扩2MB Flash,预刷MicroPython的UF2固件
-
一个红外接收管 + 一个红外发射管
- 一个三轴姿态传感器MMA7660
-
一个蜂鸣器
-
双排16Pin连接器,有SPI、I2C以及2路模拟信号输入
-
可以使用MicroPython、C、C++编程
- USB Type C连接器用于供电、程序下载
-
因为其树莓派基金会的背书,RP2040在短时间内获得了极高的关注,社区十分活跃,获得了Arduino,microPython等平台的官方支持,同时官方也提供了C/C++ SDK的支持,并提供了官方寄存器手册,适合单片机学习者各个阶段的学习。
二、实现功能
本设计在PlatformIO框架下,基于arduino进行开发,实现了用摇杆和陀螺仪控制电脑鼠标,并在设置页面设计了简单的GUI按钮控件,实现对飞鼠的功能进行调节。
三、程序介绍
本项目的程序是基于Arduino框架实现的,因为microPython和SDK在开发阶段都遇到了不能接受的问题(microPython的主要问题在找不到便利的ide进行开发,在编码过程多次遇到不能方便获得所需要方法的问题,在体验过后,选择放弃,SDK则是在驱动屏幕时,一直无法点亮屏幕,在群里交流后发现需要飞线连接屏幕的CS引脚,因为在家没有合适的工具作罢),最终选择了Arduino进行开发。
1、初始化函数
初始化函数中,对屏幕,IO,加速度计和串口进行了初始化。同时采集了摇杆X和Y轴的基数,用来实现鼠标的摇杆控制。
void setup(void)
{
tft.init();
tft.setRotation(3);
pinMode(BTN_A, INPUT_PULLUP);
pinMode(BTN_B, INPUT_PULLUP);
pinMode(BTN_START, INPUT_PULLUP);
pinMode(BTN_SELECT, INPUT_PULLUP);
pinMode(JOY_X, INPUT);
pinMode(JOY_Y, INPUT);
accelemeter.init();
Serial.begin(115200);
for (uint8_t i = 0; i < 10; i++)
{
joy_base_x += analogRead(JOY_X);
joy_base_y += analogRead(JOY_Y);
}
joy_base_x = joy_base_x / 10;
joy_base_y = joy_base_y / 10;
tft.fillScreen(TFT_GREY);
tft.setTextSize(2);
tft.fillCircle(Circle_X, Circle_Y, 80, TFT_BLACK);
tft.drawCircle(Circle_X, Circle_Y, 80, TFT_YELLOW);
tft.fillCircle(Circle_X, Circle_Y, 7, TFT_GREEN);
tft.fillRect(0, 200, 240, 40, TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK); // Adding a background colour erases previous text automatically
tft.drawString("MODE", 10, 215);
tft.drawString("Rocker", 90, 215);
}
2、陀螺仪错误消除
在读取MM7660陀螺仪时,偶尔出现异常抖动的情况,通过将数据发动到电脑上,进行分析发现,在读取过程中,经常出现y轴与z轴数据读取错误出现,在检查了库没发现错误后,选择根据数据特征编写了一个纠正代码。
在发现y轴出现迅速下降和z轴同时出现迅速上升时,将跳动位置抛弃,即可解决问题。
if (((acc_y_old - acc_y) > 18) && ((acc_z - acc_z_old) > 18))
{
acc_y = 0;
acc_z = 0;
} //实验发现在读取MMA7660时有一定概率将y轴和z轴读取反,使用代码消除抖动点
3、鼠标控制代码
鼠标控制整体使用的是arduino中提供的USB-HID库进行,使用了USBMouse库,用其中的方法进行鼠标的控制,使用其中的move方法控制鼠标移动,使用click方法控制按键,使用scroll方法滑动滚轮。
在鼠标控制过程中为了防止0位时,鼠标抖动,设置了一定的死区,只有在控制量超过死区,才进行相应的控制。将读取到的ad值乘以了一个速度系数,实现了移动速度的调整。
void RockerControl()
{
if ((joy_x_ad > MouseNeutralZone) | (joy_y_ad > MouseNeutralZone) | (joy_x_ad < -MouseNeutralZone) | (joy_y_ad < -MouseNeutralZone))
{
Mouse.move(-joy_x_ad * mouseSpeed, joy_y_ad * mouseSpeed);
}
if ((joy_x_ad != joy_x_ad_old) | (joy_y_ad != joy_y_ad_old))
{
tft.fillCircle(Circle_X, Circle_Y, 79, TFT_BLACK);
tft.fillCircle(Circle_X - joy_x_ad * 3, Circle_Y + joy_y_ad * 3, 7, TFT_GREEN);
}
clickControl();
}
4、本地图形化界面的按钮绘制
对按钮模块进行封装,其中封装了按钮控制,需要想其中传入按钮上的位置,尺寸和显示的字符,按钮的平时颜色和激活后的颜色,以及传入的按钮动作函数。在按下按钮后,按钮被激活,按钮变为激活后的颜色,并调用函数。
void buttonDraw(int32_t x, int32_t y, int32_t w, int32_t h, const char *string, uint32_t colorNomor, uint32_t colorActive, void (*fp)(void))
{
if ((digitalRead(BTN_A) == 0))
{
if ((MouseX > x) && (MouseX < (x + w)))
if ((MouseY > y) && (MouseY < (y + h))) //在按下按钮后,判断鼠标指针的位置是否在按钮范围内
{
tft.fillRect(x, y, w, h, colorActive);
while ((digitalRead(BTN_A) == 0))
;
fp(); //调用传入的函数,进行相应的操作
}
}
else if ((MouseX != MouseX_old) | (MouseY != MouseY_old) | modeChanged)//避免频闪,只在出现鼠标位置运动的情况下重绘页面
{
tft.fillRect(x, y, w, h, colorNomor);
tft.setTextSize(1);
tft.setTextColor(TFT_BLUE, colorNomor);
tft.drawString(string, x + (w / 2) - (tft.textWidth(string)) / 2, y + (h / 2) - 5);
}
}
5、所使用的arduino库及调整方式
TFT_eSPI库:
在platformio.ini文件中的lib_deps =添加bodmer/TFT_eSPI@^2.4.36,在添加库函数后,在TFT_eSPI库中找到User_Setup.h,取消49行的注释#define ST7789_DRIVER,
在80,83取消注释选择分辨率为240x240
注释掉其他的引脚定义,在最后添加如下代码
四、实物展示
五、总结
通过本平台体验了多种当今流行的单片机开发模式,感受到不同开发形式之间的区别,同时了解了USB-HID的原理和结构,对将来更深层次的开发积累了经验
由于想尝试自己实现一些GUI界面,没有使用现有的GUI库,但实现效果差强人意,希望以后可以实现更精致漂亮的GUI界面。