1、UI软件逻辑开发痛点
串口屏相信各位开发者都不陌生了,它解决了大多数开发者在嵌入式UI应用方向的痛点,常见的痛点主要有以下几个方面:
1、市面上的UI框架层出不穷,不知道如何选择,常见的有UCGUI,EMWIN,MINIGUI,AWTK,QT
等等。
2、需要花时间去熟悉一个成熟的UI框架,并将它集成到自己的程序上去,例如emWin,随便找一个这方面的开发文档,动则上千页,让众多开发者闻风丧胆。
3、不使用GUI框架,下面的大数组,让你感受一下:
这还只是单色图,如果是选择16位真彩色呢?这个数组得有多大?不得自己加FLASH进行存储吗?
近年来,市面上出现了许多优秀的串口屏厂家,例如迪文、淘晶驰、大彩、中显、尚视界等等,串口屏的出现简直就是众多开发者和创业公司的福音呀!
从曾经的项目开发周期很长,缩短到了一周甚至是一两天,即可轻松完成项目研发,减少了企业硬件研发方面的费用支出,提高了软件开发效率,同时产品也能够快速更新迭代。
2、Yoxios是什么?
接下来介绍一款在我最近入手的全新的类串口屏,它的功能比传统串口屏要强大得多,为什么说它强大,因为它支持二次开发,随便一个模块,只要板子上有接口,都可以通过Yoxios HMI去操控它。当你使用Yoxios的时候,也顺便将Linux应用开发一起学习并且掌握了,不得不说这是一个利器,不单是开发简单,也能让一直从事单片机开发的小伙伴们轻轻松松入门Linux应用。
Yoxios官网:https://www.yoxios.com/main
话不多说,一分钟了解一下Yoxios:
Yoxios 提供了可供用户开发的硬件和软件接口,官网上也提供了完善的开发文档和不少样例,如果有兴趣可以去了解一下。
3、Yoxios实战之Yoxios+ESP8266控制小车
3.1 硬件配置
参考:http://bbs.yoxios.com/forum.php?mod=viewthread&tid=6&extra=page%3D1
ESP8266引脚和接线(官方论坛提供的接口)
X3开发板 | ESP8266模块 |
VCC3.3 | VCC |
GND | GND |
U2TX | RX |
U2RX | TX |
普通IO / 悬空 | RST |
SPICS | CH_PD/EN |
这里我做的唯一和论坛的区别是在硬件上将WIFI使能管脚(CH_PD/EN)直接接到3.3V,这样软件上不需要使能该管脚,上电即使能。
3.2 UI布局
3.3 代码逻辑
这个项目的核心代码主要是在jni/logic/mainlogic.cc这个文件下编写,参考官网及论坛demo后修改程序如下:
mainLogic.cc
#include <stdlib.h> #include <iostream> #include "string" #include "uart/ProtocolSender.h" #include "uart/UartContext.h" string sendMsg, showMsg; bool WifiConnet = false; struct { string name; string password; string IP; string port; } WifiConFig; /** * 串口数据回调接口 */ static void onProtocolDataUpdate(BYTE *key, int readNum) { // 串口数据回调接口 char* p = new char[readNum]; memcpy(p, key, readNum); p[readNum] = 0; if (strstr(p, "ready") != NULL) { showMsg = ""; mTextView3Ptr->setText(showMsg); return; } showMsg += p; mTextView3Ptr->setText(showMsg); } static void WifiReset() { string s = "AT+CWMODE=1\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); s = "AT+RST\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); mTextView3Ptr->setText("wifi 初始化"); } static void WifiConnect() { WifiConFig.name = "Smart_Car"; WifiConFig.password = "12345678"; string s = "AT+CWJAP=\"" + WifiConFig.name + "\",\"" + WifiConFig.password + "\"\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); mTextView3Ptr->setText("wifi 连接"); } static void WifiTCPConnect() { string s = "AT+CIPMUX=0\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); usleep(500000); s = "AT+CIPMODE=1\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); usleep(500000); //连接服务器 WifiConFig.IP = "192.168.4.1"; WifiConFig.port = "8080"; s = "AT+CIPSTART=\"TCP\",\"" + WifiConFig.IP + "\"," + WifiConFig.port + "\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); usleep(100000); //进入透传模式 s = "AT+CIPMODE=1\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); usleep(100000); //开始透传数据 s = "AT+CIPSEND\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); usleep(100000); mTextView3Ptr->setText("TCP 连接"); mTextView5Ptr->setText("Smart_Car 192.168.4.1 8080"); } /** * 定时器触发函数 * 不建议在此函数中写耗时操作,否则将影响UI刷新 * 参数:id * 当前所触发定时器的id,与注册时的id相同 * 返回值: true * 继续运行当前定时器 * false * 停止运行当前定时器 */ static bool onUI_Timer(int id) { //Tips:添加定时器响应的代码到这里,但是需要在本文件的 REGISTER_ACTIVITY_TIMER_TAB 数组中 注册 //id 是定时器设置时候的标签,这里不要写耗时的操作,否则影响UI刷新,ruturn:[true] 继续运行定时器;[false] 停止运行当前定时器 switch (id) { case 0: WifiConnect(); return false; break; case 1: WifiTCPConnect(); return false; break; default: break; } return true; } /** * 有新的触摸事件时触发 * 参数:ev * 新的触摸事件 * 返回值:true * 表示该触摸事件在此被拦截,系统不再将此触摸事件传递到控件上 * false * 触摸事件将继续传递到控件上 */ static bool onmainActivityTouchEvent(const MotionEvent &ev) { switch (ev.mActionStatus) { case MotionEvent::E_ACTION_DOWN: //触摸按下 LOGD("时刻 = %ld 坐标 x = %d, y = %d", ev.mEventTime, ev.mX, ev.mY); //前进 if (ev.mX > 180 && ev.mX < 290 && ev.mY > 70 && ev.mY < 106) { string s = "GO\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); } //后退 if(ev.mX > 180 && ev.mX < 290 && ev.mY > 180 && ev.mY < 208) { string s = "BACK\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); } //左 if(ev.mX > 65 && ev.mX < 131 && ev.mY > 128 && ev.mY < 165) { string s = "LEFT\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); } //右 if(ev.mX > 298 && ev.mX < 400 && ev.mY > 131 && ev.mY < 166) { string s = "RIGHT\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); } break; case MotionEvent::E_ACTION_MOVE: //触摸滑动 break; case MotionEvent::E_ACTION_UP://触摸抬起 LOGD("按键抬起"); string s = "STOP\r\n"; UARTCONTEXT->send((BYTE *)s.c_str(),s.length()); break; default: break; } return false; } //连接小车 static bool onButtonClick_Button5(ZKButton *pButton) { LOGD(" ButtonClick Button5 !!!\n"); WifiReset(); mActivityPtr->registerUserTimer(0, 3000); mActivityPtr->registerUserTimer(1, 8000); return false; }
其中小车部分控制逻辑参考:
圆曾经的小车梦,造一台智能小车(三)之小车前进后退左右转基本框架
3.4运行结果
4、Demo案例下载
公众号后台回复:yoxi
即可获取所有案例及参考demo的下载链接。