Matlab上位机开发

  • 1 了解上位机
    • 1.1 上位机的作用
    • 1.2 常用上位机开发方式
      • 1.2.1 Windows上位机(基于串口通信)
      • 1.2.2 Android上位机(基于网络通信)
    • 1.3 教程概况
      • 1.3.1 C#上位机开发教程
      • 1.3.2 IoT App开发
      • 1.3.3 Matlab上位机开发
  • 2 Hello,World
    • 2.1 启动GUIDE
    • 2.2 拖动控件,开始设计
      • 2.2.1 控件栏
      • 2.2.2 静态文本显示控件
      • 2.2.3 按钮控件
    • 2.3 回调函数,让界面动起来
    • 2.4 大功告成,试试效果
  • 3 波形显示(幅度和频率可调节)
    • 3.1 控件布局
      • 3.1.1 波形显示控件(axes)
      • 3.1.2 滑动条控件(slider)
      • 3.1.3 可编辑文本框(edit)
      • 3.1.4 按钮控件
      • 3.1.5 保存设计
    • 3.2 回调函数,让界面动起来
      • 3.2.1 滑动条和编辑框联动
      • 3.2.2 编写一个绘制波形的自定义函数
      • 3.2.3 点击按钮,显示波形
      • 3.2.4 添加频率滑动条调节波形功能
      • 3.2.5 添加幅度滑动条调节波形功能
      • 3.2.6 添加编辑框调节频率和幅度的功能
      • 3.3 演示效果
  • 4 Matlab获取自带摄像头或者USB摄像头数据
    • 4.1 两种获取摄像头的方式
    • 4.2 使用Image Acquisition Toolbox
      • 4.2.1 安装硬件支持包
      • 4.2.2 玩转摄像头
    • 4.3 使用USB Webcams包
      • 4.3.1 安装硬件支持包
      • 4.3.2 玩转摄像头
    • 4.4 在GUI中显示视频流并拍照
      • 4.4.1 拖动控件,设计界面
      • 4.4.2 实时显示摄像头画面
      • 4.4.3 关闭摄像头实时显示
      • 4.4.4. 拍照(抓取画面)
  • 5 Matlab串口通信
    • 5.1 Matlab串口通信
      • 5.1.1 创建串口对象
      • 5.1.2 打开串口
      • 5.1.3 写入数据
      • 5.1.4 读取数据
      • 5.1.5 关闭串口
    • 5.2 串口中断
      • 5.2.1 触发中断的条件
      • 5.2.2 串口中断处理回调函数

转载自:mculover666微信公众号
向前辈学习!

1 了解上位机

1.1 上位机的作用

在嵌入式项目开发中,无论是单片机项目、嵌入式Linux项目、FPGA项目,上位机始终是一个很重要的部分,主要用于:

  • 数据显示(波形、温度等)
  • 用户控制(LED,继电器等)
  • 文件传输(图像、音频等)

下位机(单片机)与 上位机之间进行数据通信有四种主要方式:

  1. 串口
    主要适用于下位机和上位机在一起的系统,使用USB转串口与PC相连,也可以使用无线透传串口模组,将串口信号转化为射频信号传输;
  2. USB
    速度相较于串口大幅提升,适合于工控设备传输文件(比如3D打印机、激光切割机等),但是对下位机要求较高,需要支持USB协议;
  3. 网络
    一方面适用于物联网项目,一方面适用于嵌入式Linux系统(已经移植支持了网络);
  4. 蓝牙
    不多用。

1.2 常用上位机开发方式

上位机软软件开发主要包括以下两种:

1.2.1 Windows上位机(基于串口通信)

  1. WinForm或者WPF(C#)
    在Windows上,最早用VB语言开发,后来由于C++的发展,采用MFC开发,再后来微软发布了基于.NET框架的面向对象语言C#,更加稳定安全,再配合微软强大的VS进行开发,效率奇高;

c#和Java的语法类似,WPF相较于WinFormden优势在于,可以使用xml语言编写更加炫酷的界面;

  1. Qt(C++)
    一方面可以跨平台运行,另一方面,对于嵌入式Linux中已经熟练掌握Qt开发的开发者,使用Qt再来开发上位机非常方便;

  2. Labview
    有着更加丰富好看的数据显示控件和逼真的交互控件,并且可以图形化开发;

  3. Matlab
    多适合于需要上位机进行信号处理的项目,比如本身掌握Matlab中基本信号处理的科研人员,只需要使用下位机(Arduino)来读取ADC的数据并发送到PC进行处理,还可以进行图像处理,语音信号处理等;

1.2.2 Android上位机(基于网络通信)

  1. 使用Java或者kotlin编写(APP)
    利用Android Studio开发,多适用于物联网项目的数据显示和控制;

  2. 使用XML+CSS+JavaScript编写(小程序)
    微信提供了开发工具,多适用于物联网项目的数据显示和控制,相对APP比较轻量级,并且开发方式和网页开发类似。

1.3 教程概况

目前作者已经出的教程有:

1.3.1 C#上位机开发教程


地址:https://blog.csdn.net/mculover666/category_8632945.html

1.3.2 IoT App开发

这个系列教程由作者和B站up主“阿正啷个哩个啷”联合出品,有文字教程和视频教程,非常简单粗暴,没有Java基础也能开发:

  • 文字教程:

    地址:https://blog.csdn.net/mculover666/category_9780817.html

  • bilibili视频教程:
    地址:https://space.bilibili.com/265908761/video

1.3.3 Matlab上位机开发

从本篇文章开发,我将带领大家一起掌握如何通过 Matlab 开发上位机,目前计划的有以下这些,敬请期待:

  • Matlab上位机开发(二)Hello,World
  • Matlab上位机开发(三)波形显示(幅度和频率可调节)
  • Matlab上位机开发(四)Matlab调用自带摄像头或者USB摄像头并显示
  • Matlab上位机开发(五)Mtalab串口通信
    希望本系列教程可以给你带来帮助~

注:Matlab2018可以在作者提供的不限速下载站下载,点击阅读原文即可跳转。

2 Hello,World

2.1 启动GUIDE

在Matlab命令行输入guide启动Matlab的图形界面设计工具,选择创建一个空白的GUI:

创建之后界面如图:

2.2 拖动控件,开始设计

2.2.1 控件栏

控件栏中提供了13个控件,分别为:

  • 按钮
  • 滑动条
  • 单选按钮
  • 复选按钮
  • 可编辑文本
  • 静态文本
  • 弹出式菜单
  • 列表框
  • 切换按钮
  • 坐标轴
  • 面板
  • 按钮组

2.2.2 静态文本显示控件

首先从左边控件栏拖动到设计画布中:

然后双击画布中的控件,即可打开该控件的属性设置页面:

属性非常多,可以根据自己的需要进行设置,这里我调整字体大小(fontsize)为28,字体内容(string)为“HelloWorld”:

这些属性切换到分类模式下就很好理解了:

一些顾名思义的属性不再赘述,只讲述一些matlab中特有的:

① 控件风格和外观
CData:在控件上显示的图像;
② 控件回调函数的执行控制
BusyAction:处理回调函数的中断,有两种选项:即Cancel:取消中断事件,queue:排队(默认设置);
Interruptible:指定当前的回调函数在执行时是否允许中断,去执行其他的函数;
③ 控件对象创建和删除控制
CreateFcn:在对象产生过程中执行的回调函数;
DeleteFcn:删除对象过程中执行的回调函数;
④ 控件标识信息
Tag:控件的标识信息,可以自定义;

2.2.3 按钮控件

同样,拖动一个按钮控件到画布中,并修改其属性:

2.3 回调函数,让界面动起来

Matlab中控件(比如按钮),和用户交互的机制是设置回调函数,什么是回调函数呢?

当用户在点击按钮之后,程序中需要调用来处理该按钮点击事件的函数,称为该按钮的回调函数!

设置一个控件的回调函数非常简单,只需要右击该按钮即可查看其所有的回调函数:

这里点击Callback即可跳转到该函数:

其中hObject为发生事件的源控件,eventdata为事件数据结构,handles为传入的对象句柄,在该回调函数中添加下面的这行代码,来修改静态文本显示控件的属性值:

set(handles.text3,'String','按钮按下啦~');

第一个参数根据传入的对象句柄和控件的唯一标识来寻找控件,第二个参数为要改哪个属性,第三个参数为改变的属性值,举一反三,其它的操作也是一样。

2.4 大功告成,试试效果

点击运行或者按F5,程序启动后如图:

点击按钮后,程序变为:

3 波形显示(幅度和频率可调节)

3.1 控件布局

打开Matlab,在命令行输入guide启动GUI设计工具,拖动控件开始设计:

3.1.1 波形显示控件(axes)

波形显示控件可以用于绘制各种波形,拖动控件到画布中即可,然后根据需要调整控件大小:

3.1.2 滑动条控件(slider)

滑动条可以用于滑动调节波形的频率和幅度,并拖动两个静态文件控件用于说明:
双击频率的滑动条,设置其最大值和最小值,以及默认值:

同样,设置幅度的属性值:

3.1.3 可编辑文本框(edit)

可编辑文本框有两个功能:

  • 用于直接设置波形的频率和幅度;
  • 用于显示滑动条设置的频率值和幅度值;

拖动两个编辑框并在属性中设置其默认值:

3.1.4 按钮控件

按钮控件用于启动波形显示:

3.1.5 保存设计

设计完成之后,点击保存按钮或者按Ctrl+S保存设计:

3.2 回调函数,让界面动起来

3.2.1 滑动条和编辑框联动

首先编辑滑动条的回调函数,实现拖动滑动条,编辑框可以显示对应的值:

v1 = get(handles.slider1, 'Value');
s1 = sprintf("%f", v1);
set(handles.edit1, 'String', s1);


点击运行,查看效果:

同样,编写另一个滑动条的回调函数:

v2 = get(handles.slider2,'Value');
s2 = sprintf("%f", v2);
set(handles.edit2, 'String', s2);

实现的效果如下:

再来编写频率文本编辑框的回调函数,当输入一个值的时候,滑动条的值跟着变化:

s1=get(handles.edit1,'String');
v1=str2double(s1);
set(handles.slider1,'Value',v1);

同样,再来编写幅度文本框的回调函数:

s2=get(handles.edit2,'String');
v2=str2double(s2);
set(handles.slider2,'Value',v2);

3.2.2 编写一个绘制波形的自定义函数

点击按钮、调节滑动条,都需要重新绘制波形,所以先编写一个自定义函数,供其它函数调用:

function draw_wave(handles)
global Fs
global A
Fs = 44100;
dt=1.0/Fs;
T =2;
N=T/dt;
t=linspace(0,T,N);
s1=get(handles.edit1,'String');
F=str2double(s1);
s1=get(handles.edit2,'String');
A=str2double(s1);
x =A*sin(2*pi*F*t);
plot(handles.axes1,t,x,'b','LineWidth',1.5);
axis(handles.axes1,[0, 0.01, -2500,2500]);
grid(handles.axes1);

3.2.3 点击按钮,显示波形

编写按钮的回调函数,在回调函数里调用之前编写的自定义函数显示波形:

draw_wave(handles);

运行效果如下:

3.2.4 添加频率滑动条调节波形功能

继续编辑滑动条的回调函数,添加波形显示功能:

频率调节滑动条完整的回调函数如下:

v1 = get(handles.slider1, 'Value');
s1 = sprintf("%f", v1);
set(handles.edit1, 'String', s1);
global Fs
Fs = v1;
draw_wave(handles);

运行效果如下:

3.2.5 添加幅度滑动条调节波形功能

继续编辑滑动条的回调函数,添加波形显示功能:

幅度调节滑动条完整的回调函数如下:

v2 = get(handles.slider2,'Value');
s2 = sprintf("%f", v2);
set(handles.edit2, 'String', s2);
global A
A = v2;
draw_wave(handles);

运行效果如下:

3.2.6 添加编辑框调节频率和幅度的功能

同样,在频率编辑框的回调函数中添加代码,完整的回调函数如下:

s1=get(handles.edit1,'String');
v1=str2double(s1);
set(handles.slider1,'Value',v1);
global Fs
Fs = v1;
draw_wave(handles);

在幅度编辑框的回调函数添加同样的功能,完整的回调函数如下:

s2=get(handles.edit2,'String');
v2=str2double(s2);
set(handles.slider2,'Value',v2);
global A
A = v2;
draw_wave(handles);

运行即可看到效果,请参考下一节的完整演示效果。

3.3 演示效果

整个程序的完整演示效果如下:

4 Matlab获取自带摄像头或者USB摄像头数据

4.1 两种获取摄像头的方式

Matlab自身不支持直接读取摄像头数据,需要安装硬件支持包才可以获取,目前常用的有两个包:

第一个是 MATLAB Support Package for USB Webcams,这个包可以获取任何USB摄像头的图像(UVC),也可以获取电脑自带摄像头的数据,兼容 R2014a 到 R2020a 的版本。

第二个是Image Acquisition Toolbox Support Package for OS Generic Video Interface,更加通用,它也兼容 R2014a 到 R2020a 的版本。(推荐)

4.2 使用Image Acquisition Toolbox

4.2.1 安装硬件支持包

首先执行这条命令打开摄像头,测试是否可以调用videoinput函数:

video_source = videoinput('winvideo',1)

如果出现图中的错误,那么恭喜你,需要手动安装硬件支持包了。

点击获取附加功能中的获取硬件支持包:

按照图中所示找到该支持包:

安装支持包:


这个安装之前需要登录Matlab账号,安装过程也比较慢。

4.2.2 玩转摄像头

① 查看电脑上已经安装的图像适配器 Matlab的图像获取工具箱(第一步安装的硬件支持包)中提供了函数,可以获取查询当前PC上已经连接的摄像头信息,函数如下:

imaqhwinfo()


其中InstalledAdaptors的值给出了当前电脑上已经安装的摄像头适配器个数,这里我的电脑上只有一个:winvideo
② 查看摄像头设备具体参数
使用该命令查看上一步获取到的图像适配器的具体参数:

win_info = iimaqhwinfo('winvideo')


可以看到其中给出了该图像适配器具体的一些参数,特别需要注意的是,该函数返回了连接在当前图像适配器winvideo上的所有摄像头的设备ID和设备信息!

当前我的电脑上一共有两个摄像头,一个是笔记本电脑内置的摄像头,另一个是我连接的USB 2.0 摄像头,接下来以USB摄像头为例,说明如何查看摄像头的设备ID和具体信息:

在工作区找到保存信息的变量win_info,双击查看其值:

可以看到,两个摄像头的设备ID分别为1和2,一般来说,电脑内置的摄像头的ID为1。
同样,双击win_info.DeviceInfo变量,可以查看摄像头的具体参数:

这里摄像头支持的格式有40多种,不方便查看,我们可以在命令行查看:

win_info.DeviceInfo.SupportedFormats


③ 创建视频输入对象

使用如下的命令来创建一个视频输入对象:

video_obj = videoinput(adaptorname,deviceID,format)

该函数的三个参数说明如下:

  • adaptorname:适配器名称(必须)
  • deviceID:设备ID号(必须)
  • format:视频采集格式(不填写则使用默认)
    如下,我要创建USB摄像头的视频输入对象:
video_obj = videoinput('winvideo',2)


④ 预览视频对象
使用如下命令即可预览视频对象,该函数会自动打开一个窗口,播放摄像头画面:

preview(video_obj)

4.3 使用USB Webcams包

4.3.1 安装硬件支持包

点击获取附加功能中的获取硬件支持包:

按照图中所示找到该支持包:

安装支持包:

这个包不需要授权,只需要安装之前登录Matlab账号即可,安装过程非常快。

4.3.2 玩转摄像头

① 查看当前摄像头设备列表

webcamlist


需要注意,使用webcam的时候,下标从1开始,1对应USB Camera,2对应Integrated Camera。

② 获取视频对象 一行代码即可获取,非常舒服,比如获取外接USB摄像头的输入对象:

cam1 = webcam(1)


同样可以获取电脑自带摄像头的输入对象:

cam1 = webcam(2)


③ 预览视频对象
使用如下命令即可预览视频对象,该函数会自动打开一个窗口,播放摄像头画面:

④ 查看摄像头支持的分辨率并修改:

<刚刚获取的设备对象>.AvailableResolutions


然后根据修改为需要的分辨率:

<刚刚获取的设备对象>.Resolution = <指定的分辨率>


再次preview之后即可看到分辨率改变。

⑤ 用完之后清除对象

clear <刚刚获取的对象>

4.4 在GUI中显示视频流并拍照

在Gui界面中显示视频流尽量使用Image Acquisition Toolbox。

4.4.1 拖动控件,设计界面

在命令行输入guide启动设计界面,新建一个设计文件。

设计的界面如下:

4.4.2 实时显示摄像头画面

点击开启按钮后,在第一个坐标区实时显示摄像头画面,回调函数代码如下:
首先创建一个全局的视频输入对象:

global video_obj;
video_obj = videoinput('winvideo', 2, 'YUY2_640x480');

然后设置图像格式为RGB:

set(video_obj,'ReturnedColorSpace','rgb');

获取视频输入对象的信息,用于在坐标区显示:

videoRes = get(video_obj, 'VideoResolution');
nBands = get(video_obj, 'NumberOfBands');

转换,将视频输入对象与坐标区控件关联起来:

hImage = image(zeros(videoRes(2), videoRes(1), nBands),'parent',handles.axes1);

开始显示:

preview(video_obj,hImage);
start(video_obj);

完整的代码如下:

global video_obj;
video_obj = videoinput('winvideo', 2, 'YUY2_640x480');
set(video_obj,'ReturnedColorSpace','rgb');
videoRes = get(video_obj, 'VideoResolution');
nBands = get(video_obj, 'NumberOfBands');
hImage = image(zeros(videoRes(2), videoRes(1), nBands),'parent',handles.axes1);
preview(video_obj,hImage);
start(video_obj);

接下来启动后,点击开启按钮,就可以在第一个坐标区看到摄像头实时画面了。

4.4.3 关闭摄像头实时显示

点击关闭按钮后,关闭在第一个坐标区实时显示的摄像头画面,回调函数代码如下:

global video_obj;
stop(video_obj);
closepreview(video_obj);
delete(video_obj);

接下来启动后,点击关闭按钮,就可以关闭在第一个坐标区看到摄像头实时画面了。

4.4.4. 拍照(抓取画面)

点击拍照按钮,即可抓取当前视频流的画面,显示在第二个坐标区控件,回调函数代码如下:

global video_obj
mypic = getsnapshot(video_obj);
axes(handles.axes2);
imshow(mypic);

如果需要对抓取的图片进行处理,则将图片变量mypic设为全局变量!

启动后即可看到效果。

5 Matlab串口通信

5.1 Matlab串口通信

Matlab提供了串口通信的功能,串口通信的流程如下:

5.1.1 创建串口对象

创建一个串口对象的API如下:

scom = serial('<串口号>');

串口号为COM8的形式,这个API有个缺点:不能自动检测目前电脑中存在中的串口。

创建之后设置该串口对象的属性:

  • InputBufferSize:输入缓冲区大小(单位字节)
  • OutputBufferSize:输出缓冲区大小(单位字节)
  • ReadAsyncMode:数据读取模式
  • BaudRate:波特率
  • Parity:校验位
  • StopBits:停止位
  • DataBits :数据位
  • Terminator:触发中断的字符(一般是换行符)
  • FlowControl:流控
  • timeout:一次操作超时时间
  • BytesAvailableFcnMode:设置数据读入格式
  • BytesAvailableFcnCount:触发中断的数据数量
  • BytesAvailableFcn:串口接收中断回调函数
    常用设置如下:
scom.InputBufferSize = 512;
scom.OutputBufferSize = 512;
scom.ReadAsyncMode = 'continuous';
scom.BaudRate = 115200;
scom.Parity = 'none';
scom.StopBits = 1;
scom.DataBits = 8;
scom.Terminator = 'CR';
scom.FlowControl = 'none';
scom.timeout = 1;
scom.BytesAvailableFcnMode = 'byte';
scom.BytesAvailableFcnCount = 1024;
scom.BytesAvailableFcn = @callback;

5.1.2 打开串口

打开串口的API为:

fopen(scom);

打开串口可能会发生异常,所以此函数建议放在try..catch..end中执行:

tryfopen(scom);
catch<捕获到异常时需要打印或者显示的信息>
end

5.1.3 写入数据

向串口写入数据的API有两个:

fwrite(scom,A); % 以二进制形式向串口对象写入数据A
fprintf(scom,str); %以字符(ASCII码)形式向串口写数据str(字符或字符串)

如果BytesAvailableFcnMode设置的为byte,则使用 fwrite

5.1.4 读取数据

从串口读取数据的API也有两个:

A = fread(scom,size); %从串口对象中读取size字节长短的二进制数据,以数组形式存于A
str = fscanf(scom); %从串口对象中读取字符或字符串(ASCII码)形式数据,以字符数组形式存于str

如果BytesAvailableFcnMode设置的为byte,则使用 fread

5.1.5 关闭串口

在不使用串口或者关闭界面之前,必须要关闭串口,否则下次将无法打开该串口:

close(scom)

5.2 串口中断

上面讲述了使用fread手动读取数据的方式,但是实际应用中,需要使用串口中断自动接收并处理数据。

5.2.1 触发中断的条件

触发串口Bytes available事件有两种条件:

  • 当接收到的字符数达到指定的数目时(BytesAvailableFcnCount 属性);
  • 当接收到指定字符时(Terminator 属性);

5.2.2 串口中断处理回调函数

在上一节设置属性的最后有这样一行代码:

scom.BytesAvailableFcn = @callback;

这行代码就是设置串口中断处理回调函数,如果是纯m文件可以这样设置,但是在GUI界面中还要传入handles调用控件,如下:

scom.BytesAvailableFcn = {@calllback,handles};

这里我设置的函数名为callbcak,回调函数自己实现即可:

function callback(s,event,handles)

Matlab上位机开发相关推荐

  1. Matlab上位机开发(一) —— 了解上位机

    1. 上位机的作用 在嵌入式项目开发中,无论是单片机项目.嵌入式Linux项目.FPGA项目,上位机始终是一个很重要的部分,主要用于: 数据显示(波形.温度等) 用户控制(LED,继电器等) 文件传输 ...

  2. Matlab上位机开发(五)Matlab串口通信

    1. Matlab串口通信 Matlab提供了串口通信的功能,串口通信的流程如下: 1.1. 创建串口对象 创建一个串口对象的API如下: scom = serial('<串口号>'); ...

  3. matlab上位机串口通信,MATLAB GUIDE 上位机串口通信开发 绘制图形

    本人因项目需求,需要开发这个串口通信上位机界面,用于实时绘制串口发送过来的数据.本人之前基本没使用过MATLAB,也就知道个zeros(100)这种在命令行窗口中输入的函数.至于MATLAB能开发图形 ...

  4. 以下是一些常用的上位机开发工具:

    上位机的开发工具很多,具体选择哪种开发工具需要根据具体的需求和开发经验来选择.以下是一些常用的上位机开发工具: Visual Studio:Visual Studio 是一款由微软公司开发的集成开发环 ...

  5. 1.3-原来这才是大家常用的上位机开发平台

    一.有哪些上位机开发平台(优缺点和使用场景) 由于上位机概念的广泛性,所以上位机开发平台可以是任何开发平台.这里介绍几个常用的经典的上位机开发平台及其特性. VB(Visual Basic) 开发语言 ...

  6. 上位机开发 常用的平台及语言

    首先看一下!全球范围内,编程语言流行度! 排名 编程语言 流行度 1 Java 16.896% 2 C 15.773% 3 Python 9.704% 4 C++ 5.574% 5 C# 5.349% ...

  7. 485通信原理_上位机开发之单片机通信实践

    经常会有一些学员会问到上位机与单片机之间通信的问题,而我们经常会讲上位机与PLC之间通信,那么其实对上位机开发来说,不管是和PLC通信,还是和单片机通信,通信原理都是一样的.PLC的本质就是单片机,在 ...

  8. java开发plc上位机软件开发_上位机开发之西门子PLC-S7通信实践

    写在前面: 就目前而言,在中国的工控市场上,西门子仍然占了很大的份额,因此对于上位机开发而言,经常会存在需要与西门子PLC进行通信的情况.然后对于西门子PLC来说,通信方式有很多,下面简单列举一下: ...

  9. pythonqt4上位机开发_「新阁教育」自由口通信上位机实战案例

    1.引言 组态软件作为一种通用软件,体系结构较为庞大.功能软件包多.价格也比较昂贵,而且对于一些复杂的业务逻辑或自定义的协议,实现起来比较麻烦.近几年,C#/.NET上位机开发应用越来越广泛,相对于传 ...

最新文章

  1. formZ Pro 9(3D绘图软件)中文版
  2. “天昌”的挽歌——逝去的背影(一)
  3. Python学习---django知识补充之CBV
  4. MergeSort 归并排序
  5. mysql数据库 day01
  6. ACM PKU 1019 Number Sequence http://acm.pku.edu.cn/JudgeOnline/problem?id=1019
  7. java bufferedreader读大文件会内存溢出吗_深度分析:java中的字符流与字节流,以及缓存流,一次性帮你全掌握...
  8. java中打印当前时间_在java中打印当前日期
  9. 自定义NodeJS-C++ Addons使用说明
  10. java struts2 验证码,struts2中验证码的生成和使用
  11. Navicat安装教程
  12. TBSchedule初识
  13. 定罪了!“女版乔布斯”有可能入狱20年
  14. 微信真机调试遇到“errno“:600001,“errMsg“:“request:fail -200:net::ERR_CERT_COMMON_NAME_INVALID
  15. 迭代器模式之看芒果台还是央视nie?
  16. 复合文档学习(六) - 目录Directory
  17. WEB--3D立体魔方小游戏 (附源码)
  18. Java——接口与实现类
  19. 排列组合中关于捆绑法、插空法、插隔板法
  20. Python更新PIP至最新版本

热门文章

  1. 奇怪的比赛(某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪: 每位选手需要回答10个问题(其编号为1到10),越后面越有难度。答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答)
  2. [kuangbin带你飞]专题十一 网络流\N HDU 3081 Marriage Match II
  3. 搬砖:100道c语言面试题
  4. 帕累托分布Pareto distribution
  5. 【设计模式】(7)--最常用模式之外观模式
  6. 这时候买阿里,买的是估值潜力
  7. php 图片压缩 保留exif,保留图片原有的EXIF
  8. virtualbox的下载和centos8的安装
  9. 2018年2月DappRadar以太坊10大DApp应用
  10. nginx软重启nginx平滑重启