*这篇文章是作者的本科毕业设计,属于作者的原创文章,禁止随意转载,仅供大家学习参考。*

基于Arduino的避障小车现在已经有了很多的帖子和教程,但本篇文章为避障小车添加了更多的实用的功能,比如:拍照、人体感应、蜂鸣器响应、蓝牙控制、自动模式和手动模式之间的切换。这篇文章的避障小车使用的是超声波避障模块。

下面介绍一下这篇文章使用到的一些模块:

  • Arduino MEGA2560 开发板
  • MEGA2560传感器扩展板
  • L298N驱动板
  • 直流电机
  • HC-SR04超声波传感器
  • AM412人体红外传感器
  • 有源蜂鸣器模块
  • SG90舵机
  • VC0706串口相机
  • TF卡读写储存模块
  • HC-05蓝牙模块

下面介绍这篇文章中各个模块之间的接线关系

MEGA2560传感器扩展板直接插接在2560开发板上。2560的扩展板的每个数字接口和模拟接口旁边都有独立的VCC和GND接口,这也是为什么需要用到扩展板的原因之一。有关2560扩展板的详情请参考MEGA2560传感器扩展板

超声波传感器:我一共用了三个超声波传感器,分别放在小车前面的舵机云台上、小车左方、小车右方,舵机云台由舵机控制,可以让云台上的超声波传感器探测更大的角度。HC-SR04超声波传感器一共有4个引脚,分别是VCC、GND、Trig、Echo。HC-SR04超声波传感器的具体用法请参考SR04超声波模块,SR04超声波传感器在Arduino中有官方的库文件,只需要调用即可,不需要自己定义函数去计时换算成距离。超声波传感器的GND连Arduino的GND,VCC连VCC就不多说了(随便哪一个口的VCC、GND都可以接,推荐接用到的那个口的GND、VCC)。

SR04 Arduino
前Trig D4
前Echo D5
左Trig D9
左Echo D8
右Trig D16
右Echo D17

D是数字量接口,A是模拟量接口。大部分传感器或者模块都使用数字量接口,也有一部分传感器使用模拟量接口,这篇文章中模拟量接口只用到了一个,就是人体红外传感器使用的模拟量接口。

舵机:舵机控制的是小车前方的云台,云台上放了一个超声波传感器,通过开发板写角度,改变舵机的角度。SG90跟大部分舵机一样是三个接口,分别是S、VCC、GND,S是控制接口也称信号接口,大部分的传感器或者模块都是这三个接口。舵机使用方法非常简单,同样的拥有官方库文件,使用时只需要调用库函数就行了。例如:myservo.write(val);定义一个整型变量“val”通过改变val的值,再用这个函数,就可以改变舵机的角度。角度当然也可以一度一度地改变,只需要用一个循环语句,让舵机每变一度再延时几毫秒就可以了,这种一度一度地改变的方法更符合使用实际。

舵机 Arduino
S D2

舵机的三根线通常是是连在一起的杜邦线,一般认线的颜色就可以了,黄色的是信号线,红色的是VCC,黑色的是GND,竖着一排插在数字量接口那里,线的排列顺序刚好也和扩展板上接口的排列顺序一一对应。

人体红外传感器:AM412人体红外传感器是普通HC-SR501人体红外传感器的升级版,模块体积更小,但少了两个可调节电位器,正常使用来说,那两个可调节的电位器可以去掉。AM412人体红外传感器一共有三个引脚,OUT、VCC、GND。人体红外传感器的具体使用方法请参考人体红外传感器

人体红外传感器 Arduino
OUT A0

人体红外传感器是模拟信号,所以要连扩展板的模拟量接口。

蜂鸣器:蜂鸣器可以和人体红外传感器一起使用,当有人经过人体红外传感器时,蜂鸣器就会响应。蜂鸣器有三个引脚,S、VCC、GND。这里的蜂鸣器是低电平响应。

蜂鸣器 Arduino
S D14

蓝牙模块:蓝牙模块是与手机相连接的,手机上下载好相应的APP后(我使用的APP是“蓝牙串口”),可以发送数据给蓝牙模块,开发板接收到蓝牙模块的串口数据后执行相应的命令。蓝牙模块买到手后需要经过调试才能正常使用,一般使用USB转串口模块,将蓝牙模块插在USB转串口上,或者用开发板直接连蓝牙调试,这里调试一般为AT指令调试(使用开发板直连蓝牙模块调试时,不能将蓝牙接在D0和D1引脚上,其它数字引脚都可以,只需在程序中声明就行,因为D0、D1是开发板默认的与电脑USB的串口通讯接口,与电脑连接时不能被占用,否则电脑不能通过USB与开发板之间进行读写)。调试的主要内容是:①更改蓝牙模块的蓝牙名称和连接密码。②将蓝牙设置成从机模式(蓝牙分主机模式和从机模式,主机模式蓝牙开机自动扫描连接上次连接成功的手机或其他设备,从机模式开机后等待被连接)。③设置蓝牙波特率为9600(我习惯波特率都用9600)。

蓝牙模块具体的操作办法请参考HC-05蓝牙模块
在这篇文章中,我将手机发送给蓝牙的数据定义为整型变量,也就是数字的形式,比如改变手动自动模式或者执行前进命令都是不同的数字,这样在编程的时候比较方便。
HC-05蓝牙模块有很多个引脚,但是一般用到的就4个,分别是:RXD、TXD、VCC、GND,一个接收数据,一个发送数据,一个接电源、一个接地。当蓝牙模块调试好后,与开发板之间的连接方法如下表所示,但为了不占用与电脑之间的硬串口,每次开发板与电脑相连时,需要把蓝牙RXD、TXD的两根线拔掉(或者你直接定义另外两个数字量引脚也可以,这里用的是通用的蓝牙引脚D0、D1)。

HC-05蓝牙 Arduino
TXD D0
RXD D1

串口相机:这篇文章使用的是VC0706串口相机,之所以使用这个相机是因为网络上有这个相机的第三方库文件,使用起来比较方便。但有个问题是,网络上下载的库文件中的例程,不能直接使用,直接使用的话会出现拍的照片只有一半或一少半显示出来,能完全显示出照片的教程在VC0706使用教程
这个教程中是将VC0706弄成了一个延时摄影(延时摄影是自动每隔几秒拍照一张,再后期通过电脑合成视频,视频看上去就是加快了速度)的工具,如果只需要VC0706执行拍一张照,可以将程序中的循环语句删掉,或者使用我后面文章中的程序。串口相机买来后基本不需要调试可以直接使用,网络上找到的相关资料都是收费的,所以我也就没调试。VC0706串口相机也有很多的引脚,但是有用的也只有TX、RX、VCC、GND。

VC0706 Arduino
TX D10
RX D13

SD卡模块:SD卡模块也就是TF读写储存模块是用来储存串口相机拍摄的照片的。SD卡模块上插入一个SD卡,接在开发板上就可以直接使用了。


SD卡模块使用到的引脚有:CS(有的也称SS,这是SD卡的片选引脚,也就是开发板选择把数据存在这张卡里)、MOSI、MISO、SCK、VCC、GND。SD卡模块比较特殊在UNO和MEGA2560开发板上都有固定的引脚(且两个板子默认的引脚都不同),当然也可以自己定义引脚,这里我比较倾向于使用默认的引脚。SD卡模块在UNO上使用的教程请参考SD卡模块UNO
下表是SD卡模块在MEGA2560开发板上的引脚接线。

SD卡模块 Arduino
CS/SS D53
MOSI D51
MISO D50
SCK D52

驱动模块:驱动模块我选用的是L298N双桥驱动板,带动直流电机。


左边轮子的直流电机连接L298N的OUT1、OUT2。
右边轮子的直流电机连接L298N的OUT3、OUT4。
其中L298N和开发板相连的几个引脚当中,ENA和ENB必须要连有PWM功能的数字量引脚,因为直流电机调速要用到PWM脉宽调制。
在驱动板内部,OUT1是与IN1相连的、OUT2与IN2相连,以此类推。ENA是左边电机的调速引脚,ENB是右边电机的调速引脚。

L298N Arduino
ENA D12(PWM)
IN1 D32
IN2 D33
IN3 D34
IN4 D35
ENB D11(PWM)

另外驱动板因为电流很大,需要独立提供电源,我用了12V的电源供电,且驱动板的电源不能和开发板的电源引脚相连,但可以共地。

我将蓝牙的串口数据定义为整型变量,当手机发送0时,小车停止;当手机发送1时,小车前进;当手机发送2时,小车倒退;当手机发送3时,小车拍照;当小车发送6时,小车的蜂鸣器响应;当手机发送4时,小车切换成手动模式(小车开机默认为手动模式);当手机发送5时,小车切换成自动模式。自动模式下,小车将执行自动避障程序,直到接收到蓝牙的停止命令。

下图是小车完整的程序框图:


如下图是小车自动模式下的程序框图:


下面是这篇文章的完整程序,程序段中已经注明了注释,若还有不懂的也可以回复问我,我随缘解答。

#include <SoftwareSerial.h>//调用软串口库函数
#include <Adafruit_VC0706.h>//调用VC0706相机库函数
#include <SD.h>//调用SD卡库函数
#include <Servo.h>//调用舵机库函数
#include <SR04.h>//调用超声波传感器库函数(函数调用完成)
#include <SPI.h>SoftwareSerial BT(0, 1);//定义蓝牙的TX和RX引脚(蓝牙模块)#define chipSelect 53//定义SD卡的片选引脚(摄像头、SD卡模块)
SoftwareSerial cameraconnection = SoftwareSerial(10,13);
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);//(摄像头、SD卡模块初始化前的操作)#define Buzzerpin 14//定义蜂鸣器的引脚
#define PIR_sensor A0//定义人体红外传感器的引脚(红外、蜂鸣器模块)#define TRIG_PIN 5//定义前方超声波传感器控制端
#define ECHO_PIN 4//定义前方超声波传感器接收端
#define TRIGright_PIN 16//定义右方超声波传感器控制端
#define ECHOright_PIN 17//定义右方超声波传感器接收端
#define TRIGleft_PIN 9//定义左方超声波传感器控制端
#define ECHOleft_PIN 8//定义左方超声波传感器接收端
#define motor1pin1 32//定义IN1引脚
#define motor1pin2 33//定义IN2引脚
#define motor1pwm 12//定义ENA引脚
#define motor2pin1 34//定义IN3引脚
#define motor2pin2 35//定义IN4引脚
#define motor2pwm 11//定义ENB引脚(避障、驱动模块)(各模块引脚定义完成)Servo myservo;//创建一个舵机控制对象
int djangle=90;//用该变量储存舵机角度位置
SR04 sr04=SR04(ECHO_PIN,TRIG_PIN);//定义前方超声波传感器
SR04 sr04r=SR04(ECHOright_PIN,TRIGright_PIN);//定义右方超声波传感器
SR04 sr04l=SR04(ECHOleft_PIN,TRIGleft_PIN);//定义左方超声波传感器
long forward;//储存舵机在90°时障碍物的距离
long leftfw;//储存舵机在135°(左前方)时障碍物的距离
long rightfw;//储存舵机在45°(右前方)时障碍物的距离
long left;//储存左方超声波传感器数值
long right;//储存右方超声波传感器数值
int l;//定义左电机速度变量
int r;//定义右电机速度变量
int n;//计数
int m;//计数
void motor(int motorpin1,int motorpin2,int motorpwm,int val)//定义一个电机转动函数
{
pinMode(motorpin1,OUTPUT);//输出第一个引脚
pinMode(motorpin2,OUTPUT);//输出第二个引脚
digitalWrite(motorpin1,1);//将第一个引脚抬高
digitalWrite(motorpin2,0);//将第二个引脚置低
analogWrite(motorpwm,val);//给EN引脚设定模拟值,设定转速
}//(避障、驱动模块初始化前的操作)int rentiv=0;//定义人体红外传感器获取到的电位值(红外、蜂鸣器模块初始化前的操作)(初始化前的操作完成)int opmode;//储存小车运行模式(手动和自动):4手动、5自动
int cmd;//储存小车在手动模式下的运行指令:0停止、1前进、2倒退、3拍照、6响铃
int blcmd;//暂存蓝牙指令void setup()
{opmode=4;//设置为手动模式Serial.begin(9600);//设置串口通讯波特率(软串口)BT.begin(9600);//设置蓝牙串口波特率(蓝牙模块)myservo.attach(2);//定义舵机的信号引脚myservo.write(djangle);//初始化舵机角度(避障、驱动模块)pinMode(PIR_sensor,INPUT);//将A0引脚置为输入pinMode(Buzzerpin,OUTPUT);//将14引脚置为输出(红外、蜂鸣器模块)digitalWrite(Buzzerpin,HIGH);delay(10000);//延迟10秒等待蓝牙启动并连上手机Serial.println("已成功连接上小车");//连上蓝牙后通知手机pinMode(53, OUTPUT);if (!SD.begin(chipSelect)){Serial.println("SD卡异常");return;}if (cam.begin()){Serial.println("相机已准备好");}else{Serial.println("相机异常");return;}cam.setImageSize(VC0706_640x480);Serial.println("照片尺寸为640x480");Serial.println("现在是手动模式");//向手机输出“现在是手动模式”
}//(各模块初始化完成)void loop()
{while(Serial.available()){blcmd=Serial.read();if(blcmd=='0'){Serial.println("接收到停止命令");cmd=blcmd;}if(blcmd=='1'){Serial.println("接收到前进命令");cmd=blcmd;}if(blcmd=='2'){Serial.println("接收到倒退命令");cmd=blcmd;}if(blcmd=='3'){Serial.println("接收到拍照命令");cmd=blcmd;}if(blcmd=='4'){Serial.println("切换成手动模式");opmode=blcmd;}if(blcmd=='5'){Serial.println("切换成自动模式");opmode=blcmd;cmd=10;}if(blcmd=='6'){Serial.println("接收到响铃命令");cmd=blcmd;}}if((cmd=='0')&&(opmode=='4')){l=0;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);Serial.println("小车已停止");}if((cmd=='0')&&(opmode=='5')){l=0;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);Serial.println("小车已停止");}if((cmd=='1')&&(opmode=='4')){l=120;r=120;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);Serial.println("小车正在前进");}if((cmd=='2')&&(opmode=='4')){l=100;r=100;motor(motor1pin2,motor1pin1,motor1pwm,l);motor(motor2pin2,motor2pin1,motor2pwm,r);Serial.println("小车正在倒退");}if((cmd=='3')&&(opmode=='4')){l=0;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);cmd=10;Serial.println("小车正在拍照");delay(20);if (! cam.takePicture()) Serial.println("拍照失败!");else Serial.println("拍照完成!");char filename[13];strcpy(filename, "IMAGE000.JPG");for (int i = 0; i < 1000; i++){filename[5] = '0' + i/100;filename[6] = '0' + (i%100)/10;filename[7] = '0' + (i%100)%10;if (! SD.exists(filename)){break;}}File imgFile = SD.open(filename, FILE_WRITE);uint16_t jpglen = cam.frameLength();Serial.print(jpglen, DEC);Serial.println(" byte image");Serial.print("储存照片到");Serial.print(filename);while (jpglen > 0){uint8_t *buffer;uint8_t bytesToRead = min(32, jpglen);buffer = cam.readPicture(bytesToRead);imgFile.write(buffer, bytesToRead);jpglen -= bytesToRead;}imgFile.close();Serial.println("...完成!");cam.begin();}if((cmd=='6')&&(opmode=='4')){l=0;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);Serial.println("小车正在响铃");digitalWrite(Buzzerpin,LOW);//发声音delay(1000);digitalWrite(Buzzerpin,HIGH);//不发声音delay(1000);}if(opmode=='5'){rentiv=analogRead(PIR_sensor);//读取A0口的电压值并赋值到rentivSerial.println(rentiv);//串口发送rentiv的值if(rentiv>600){Serial.println("there is somebody!");digitalWrite(Buzzerpin,LOW);//发声音delay(1000);digitalWrite(Buzzerpin,HIGH);//不发声音delay(1000);Serial.println("正在拍照...");delay(20);if (! cam.takePicture()) Serial.println("拍照失败!");else Serial.println("拍照完成!");char filename[13];strcpy(filename, "IMAGE000.JPG");for (int i = 0; i < 1000; i++){filename[5] = '0' + i/100;filename[6] = '0' + (i%100)/10;filename[7] = '0' + (i%100)%10;if (! SD.exists(filename)){break;}}File imgFile = SD.open(filename, FILE_WRITE);uint16_t jpglen = cam.frameLength();Serial.print(jpglen, DEC);Serial.println(" byte image");Serial.print("储存照片到");Serial.print(filename);while (jpglen > 0){uint8_t *buffer;uint8_t bytesToRead = min(32, jpglen);buffer = cam.readPicture(bytesToRead);imgFile.write(buffer, bytesToRead);jpglen -= bytesToRead;}imgFile.close();Serial.println("...储存完成!");cam.begin();rentiv=0;}forward=sr04.Distance();//获取前方障碍物距离left=sr04l.Distance();//获取左方障碍物距离right=sr04r.Distance();//获取右方障碍物距离if(forward>30)//当前方障碍物距离大于30cm时{if((left>25)&&(right>25))//当左、右方障碍物距离大于25cm时{l=120;r=120;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//直行delay(800);}if((left>25)&&(right<25))//左边比右边宽敞{l=90;r=120;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//左转delay(800);}if((left<25)&&(right>25))//右边比左边宽敞{l=120;r=90;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//右转delay(800);}if((left<25)&&(right<25))//当左、右障碍物距离小于25cm时{if(left>right)//如果左边比右边宽敞{l=70;r=80;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//左转delay(800);}else//如果右边比左边宽敞{l=80;r=70;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//右转delay(800);}}}if((forward<30)&&(forward>15))//当前方障碍物距离在15cm到30cm{l=0;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//让小车停下来djangle=135;myservo.write(djangle);//让舵机转到135°delay(250);for(n=0;n<2;n++){leftfw=sr04.Distance();//左前方获取数据delay(100);}djangle=45;myservo.write(djangle);//让舵机转到45°delay(400);for(n=0;n<2;n++){right=sr04.Distance();//右前方获取数据delay(100);}djangle=90;myservo.write(djangle);//舵机归中delay(250);if(leftfw>rightfw)//如果左前方比右前方宽敞{l=0;r=80;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//左转delay(500);}else//右边比左边宽敞{l=80;r=0;motor(motor1pin1,motor1pin2,motor1pwm,l);motor(motor2pin1,motor2pin2,motor2pwm,r);//右转delay(500);}}if(forward<15){l=100;r=100;motor(motor1pin2,motor1pin1,motor1pwm,l);motor(motor2pin2,motor2pin1,motor2pwm,r);//倒车delay(500);}}
}

基于Arduino的智能避障小车相关推荐

  1. 基于arduino单片机智能避障小车

    基于arduino单片机智能避障小车 思路简介 本文简要介绍了基于arduino单片机智能小车可以通过手机端蓝牙助手对其进行遥控操作'可以切换手动操作和自动避障两个模式,避障基于蝙蝠超声波测距的原理, ...

  2. 51单片机小车的立项书_毕业论文:基于51单片机智能避障小车的设计报告(范文1)...

    <毕业论文:基于51单片机智能避障小车的设计报告.doc>由会员分享,可免费在线阅读全文,更多与<毕业论文:基于51单片机智能避障小车的设计报告>相关文档资源请在帮帮文库(ww ...

  3. 智能避障小车学习笔记(基于Wemos的避障小车)

    智能避障小车 一.开发环境及硬件 ArduiNo平台 网盘地址:https://pan.baidu.com/s/1w3MHxkCUBOlbqKRxRhlwbQ 提取码:o6gk 硬件 WeMos D1 ...

  4. 51单片机趣玩制作—智能避障小车_V1.0

    文章目录 一.智能避障小车(V1.0) (一)准备阶段 1.制作思路 2.制作原则 3.硬件系统 (1)动力模块 (2)避障模块 (3)其它 4.软件系统 (1)动力模块 (2)避障模块 (3)模块合 ...

  5. 关于ros仿真智能避障小车

    ros仿真智能避障小车 软件:gazebo rviz https://www.bilibili.com/video/BV1Eg4y1q7Am?from=search&seid=12536238 ...

  6. (4WD+2路红外线)arduino UNO四驱arduino超声波+红外线避障小车

    有兴趣可以点击**我的店铺**看看小车硬件.提供安装说明.此图片仅供参考,图中是2驱超声波避障+循迹双模式小车.程序与本文有相同之处. .................... 四驱arduino超声 ...

  7. 基于STM32三路超声波避障小车

    基于STM32的避障小车 最近几天的学习了STM32输入捕获输入捕获的相关知识,为了巩固自己学习的知识特意制作一辆有三个超声波组成的4轮避障小车来加深对输入捕获的理解. 1.输入捕获简介 输入捕获模式 ...

  8. arduino超声波自动避障小车制作过程

    超声波自动避障小车 #include <Servo.h> #define Trig 2 //引脚控制超声波发出声波 #define Echo 3 //引脚反应接收到返回声波 #define ...

  9. 项目:基于wemos的WiFi避障小车

    一.项目介绍:通过wemos D1控制小车的行进轨迹及避障功能. 二.项目原理:该模块主要实现避障的功能,超声波发出波遇到前面的障碍物后会返回,通过这段时间来判断距离前面障碍物的距离,距离通过串口传给 ...

  10. 【毕业设计】基于单片机的智能避障超声波跟随小车 - 物联网 嵌入式

    文章目录 0 前言 1 项目背景 2 实现效果 3 设计原理 HC-SR04超声波模块 5 部分代码 6 最后 0 前言

最新文章

  1. TypeError: can only concatenate str (not “float“) to str
  2. MySQL优化篇:explain性能分析
  3. SQL Server 2012 数据库镜像配置完整篇
  4. mybaits二:通过接口类,查询数据
  5. 查看journalnode节点状态信息_OpenStack Cinder服务状态排错
  6. 50张非常精美的Apple主题桌面壁纸(上篇)
  7. LeetCode 1561. 你可以获得的最大硬币数目
  8. hibernate开发优缺点
  9. python创建数组与列表_python基础(三):数组和列表
  10. android开发自动提示框,Android 多种简单的弹出框样式设置代码
  11. android10无法获取ssid,解决Android 8.0和9.0无法获取SSID (unknow ssid)
  12. linux 增加maven内存,Ubuntu Linux系统下Apache Maven的安装和配置
  13. 项目Alpha冲刺Day3
  14. 图片相似度计算-模板匹配
  15. 压力测试软件 loadr,初学abench压力测试 - 玄大冰 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  16. day05【JQuery框架】HTML引入Jquery、jQuery与JS区别、基本选择器、层级关系选择器、属性选择器、过滤选择器、 对象遍历、Jquery的DOM操作【重点】、Jquery事件绑定
  17. Python 制作按键触发Windows通知的脚本
  18. 可视化损失函数空间三维图
  19. JMF下载安装与支持格式
  20. 此起彼伏的云计算峰会 我们到底听到了什么

热门文章

  1. 易语言游戏辅助开发(第一课)
  2. 15款超实用学习APP安利
  3. csv 计算机系统化验证,计算机化系统CSV验证问答.doc
  4. Yandex安装第三方crx插件的方法
  5. 乐视电视安装鸿蒙系统,乐视电视更新后无法识别apk文件怎么办?方法教程
  6. 如何批量将 Word 文档转为 XPS 格式
  7. 中国移动边缘计算技术体系与实践
  8. linux桌面共享编程,Remmina:一个Linux下功能丰富的远程桌面共享工具
  9. STM32串口通讯——中断方式
  10. Filenet路线更新及新版官网上线公告 ​