今天,正运动技术给大家分享一下运动控制卡之ECI3808如何使用C++编写控制器设置运动控制系统的安全处理。

一、ECI3808硬件介绍

1.功能介绍

ECI3808系列控制卡支持最多达12轴直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴、机械手指令等;采用优化的网络通讯协议可以实现实时的运动控制。

ECI3808系列运动控制卡支持以太网,RS232通讯接口和电脑相连,接收电脑的指令运行,可以通过CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。

ECI3808系列运动控制卡的应用程序可以使用VC,VB,VS,C++,C#等软件来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试和观察。

2.硬件接口

3.控制器基本信息

二、 C++进行运动控制开发

1.新建MFC项目并添加函数库

(1)在VS2015菜单“文件”→“新建”→“项目”,启动创建项目向导。

(2)选择开发语言为“VisualC++”和程序类型“MFC应用程序”。

(3)点击下一步即可。

(4)选择类型为“基于对话框”,下一步或者完成。

(5)找到厂家提供的光盘资料,路径如下(64位库为例)。

A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。

B.选择“函数库2.1”文件夹。

C.选择“Windows平台”文件夹。

D.根据需要选择对应的函数库这里选择64位库。

E.解压C++的压缩包,里面有C++对应的函数库。

F.函数库具体路径如下。

(6)将厂商提供的C++的库文件和相关头文件复制到新建的项目里面。

(7)在项目中添加静态库和相关头文件。

A.先右击项目文件,接着依次选择:“添加”→“现有项”。

B.在弹出的窗口中依次添加静态库和相关头文件。

(8)声明用到的头文件和定义控制器连接句柄。

至此项目新建完成,可进行MFC项目开发。

2.查看PC函数手册,熟悉相关函数接口。

(1)PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册V2.1.pdf”

(2)链接控制器,获取链接句柄。

ZAux_OpenEth()接口说明:

(3) 配置IO信号点对应函数接口如下。

→对接口的详细说明可查看PC函数手册。

以下为正负软件限位大小设置的接口,到达限制的位置时会强制停止下来不会继续运行以达到保护的目的,停止的加减速度以设置的FASTDEC快速减速速度为准(FASTDEC设置为0时以设置的DECEL为准)。


3.MFC开发控制器的安全设置

(1)例程界面如下。

(2)链接按钮的事件处理函数中调用链接控制器的接口函数ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器1监控控制器状态。

/网口链接控制器void CSingle_move_Dlg::OnOpen(){char   buffer[256]; int32 iresult;//如果已经链接,则先断开链接if(NULL != g_handle){ZAux_Close(g_handle);g_handle = NULL;}//从IP下拉框中选择获取IP地址GetDlgItemText(IDC_IPLIST,buffer,255);buffer[255] = '\0';//开始链接控制器iresult = ZAux_OpenEth(buffer, &g_handle);if(ERR_SUCCESS != iresult){g_handle = NULL;MessageBox(_T("链接失败"));SetWindowText("未链接");return;}//链接成功开启定时器1SetWindowText("已链接");SetTimer( 1, 100, NULL );  }

(3)通过定时器监控控制器状态。

void CSingle_homeDlg::OnTimer(UINT_PTR nIDEvent) {// TODO: Add your message handler code here and/or call defaultif(NULL == g_handle){MessageBox(_T("链接断开"));return ;}if(1 == nIDEvent){CString string;uint test;float position[4] = {0};int status[4] = {0}; int nAxisStatus[4] = {0};int nMaxSpeed[4] = { 0 };for (int i = 0;i< 4; i++){ZAux_Direct_GetDpos( g_handle,i,&position[i]);          //获取当前轴位置ZAux_Direct_GetIfIdle(g_handle,i,&status[i]);           //判断当前轴状态ZAux_Direct_GetAxisStatus(g_handle, i, &nAxisStatus[i]);ZAux_Direct_GetMaxSpeed(g_handle,i, &nMaxSpeed[i]);}if (status[0] == -1){if (nAxisStatus[0] == 0 || (nAxisStatus[0] & 0x000040) == 64){string.Format("X  停  止  %.2f   轴状态正常", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000010) == 16){string.Format("X  停  止  %.2f   轴正向硬限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000020) == 32){string.Format("X  停  止  %.2f   轴反向硬限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000200) == 512){string.Format("X  停  止  %.2f   轴正向软限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000400) == 1024){string.Format("X  停  止  %.2f   轴反向软限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x001000) == 4096){string.Format("X  停  止  %.2f   脉冲频率超过max_speed:%d 限制", position[0],nMaxSpeed[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}}else{if (nAxisStatus[0] == 0 || (nAxisStatus[0] & 0x000040) == 64){string.Format("X  运行中  %.2f   轴状态正常", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000010) == 16){string.Format("X  运行中  %.2f   轴正向硬限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000020) == 32){string.Format("X  运行中  %.2f   轴反向硬限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000200) == 512){string.Format("X  运行中  %.2f   轴正向软限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x000400) == 1024){string.Format("X  运行中  %.2f   轴反向软限位报警", position[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}if ((nAxisStatus[0] & 0x001000) == 4096){string.Format("X  运行中  %.2f   脉冲频率超过max_speed:%d 限制", position[0], nMaxSpeed[0]);GetDlgItem(IDC_STATE_X)->SetWindowText(string);}}if (status[1] == -1){if (nAxisStatus[1] == 0 || (nAxisStatus[1] & 0x000040) == 64){string.Format("Y  停  止  %.2f   轴状态正常", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000010) == 16){string.Format("Y  停  止  %.2f   轴正向硬限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000020) == 32){string.Format("Y  停  止  %.2f   轴反向硬限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000200) == 512){string.Format("Y  停  止  %.2f   轴正向软限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000400) == 1024){string.Format("Y  停  止  %.2f   轴反向软限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x001000) == 4096){string.Format("Y  停  止  %.2f   脉冲频率超过max_speed:%d 限制", position[1], nMaxSpeed[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}}else{if (nAxisStatus[1] == 0 || (nAxisStatus[1] & 0x000040) == 64){string.Format("Y  运行中  %.2f   轴状态正常", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000010) == 16){string.Format("Y  运行中  %.2f   轴正向硬限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000020) == 32){string.Format("Y  运行中  %.2f   轴反向硬限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000200) == 512){string.Format("Y  运行中  %.2f   轴正向软限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x000400) == 1024){string.Format("Y  运行中  %.2f   轴反向软限位报警", position[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}if ((nAxisStatus[1] & 0x001000) == 4096){string.Format("Y  运行中  %.2f   脉冲频率超过max_speed:%d 限制", position[1], nMaxSpeed[1]);GetDlgItem(IDC_STATE_Y)->SetWindowText(string);}}if (status[2] == -1){if (nAxisStatus[2] == 0 || (nAxisStatus[2] & 0x000040) == 64){string.Format("Z  停  止  %.2f   轴状态正常", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000010) == 16){string.Format("Z  停  止  %.2f   轴正向硬限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000020) == 32){string.Format("Z  停  止  %.2f   轴反向硬限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000200) == 512){string.Format("Z  停  止  %.2f   轴正向软限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000400) == 1024){string.Format("Z  停  止  %.2f   轴反向软限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x001000) == 4096){string.Format("Z  停  止  %.2f   脉冲频率超过max_speed:%d 限制", position[2], nMaxSpeed[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}}else{if (nAxisStatus[2] == 0 || (nAxisStatus[2] & 0x000040) == 64){string.Format("Z  运行中  %.2f   轴状态正常", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000010) == 16){string.Format("Z  运行中  %.2f   轴正向硬限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000020) == 32){string.Format("Z  运行中  %.2f   轴反向硬限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000200) == 512){string.Format("Z  运行中  %.2f   轴正向软限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x000400) == 1024){string.Format("Z  运行中  %.2f   轴反向软限位报警", position[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}if ((nAxisStatus[2] & 0x001000) == 4096){string.Format("Z  运行中  %.2f   脉冲频率超过max_speed:%d 限制", position[2], nMaxSpeed[2]);GetDlgItem(IDC_STATE_Z)->SetWindowText(string);}}     if (status[3] == -1){if (nAxisStatus[3] == 0 || (nAxisStatus[3] & 0x000040) == 64){string.Format("R  停  止  %.2f   轴状态正常", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000010) == 16){string.Format("R  停  止  %.2f   轴正向硬限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000020) == 32){string.Format("R  停  止  %.2f   轴反向硬限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000200) == 512){string.Format("R  停  止  %.2f   轴正向软限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000400) == 1024){string.Format("R  停  止  %.2f   轴反向软限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x001000) == 4096){string.Format("R  停  止  %.2f   脉冲频率超过max_speed:%d 限制", position[3], nMaxSpeed[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}}else{if (nAxisStatus[3] == 0 || (nAxisStatus[3] & 0x000040) == 64){string.Format("R  运行中  %.2f   轴状态正常", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000010) == 16){string.Format("R  运行中  %.2f   轴正向硬限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000020) == 32){string.Format("R  运行中  %.2f   轴反向硬限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000200) == 512){string.Format("R  运行中  %.2f   轴正向软限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x000400) == 1024){string.Format("R  运行中  %.2f   轴反向软限位报警", position[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}if ((nAxisStatus[3] & 0x001000) == 4096){string.Format("R  运行中  %.2f   脉冲频率超过max_speed:%d 限制", position[3], nMaxSpeed[3]);GetDlgItem(IDC_STATE_R)->SetWindowText(string);}}}CDialog::OnTimer(nIDEvent);}

(4)使用参数设置按钮的事件处理函数对参数进行初始化,并设置对应的安全限位设置。

void CSingle_homeDlg::OnHome()          //回零运动{// TODO: Add your control notification handler code here  UpdateData(true);//刷新参数int status = 0; ZAux_Direct_GetIfIdle(g_handle, m_nAxis,&status);           //判断当前轴状态if (status == 0) //已经在运动中return;  //设定轴类型 7-   脉冲轴类型 +  编码器Z信号    不用EZ回零也可以设置为1  ZAux_Direct_SetAtype(g_handle, m_nAxis, 7);//设定脉冲模式及逻辑方向(脉冲+方向)  ZAux_Direct_SetInvertStep(g_handle, m_nAxis, 0);//设置脉冲当量  1表示以一个脉冲为单位 ,设置为1MM的脉冲个数,这度量单位为MMZAux_Direct_SetUnits(g_handle, m_nAxis, m_units);  //设定速度,加减速ZAux_Direct_SetLspeed(g_handle, m_nAxis, m_lspeed);ZAux_Direct_SetSpeed(g_handle, m_nAxis, m_speed);ZAux_Direct_SetAccel(g_handle, m_nAxis, m_acc);ZAux_Direct_SetDecel(g_handle, m_nAxis, m_dec);ZAux_Direct_SetCreep(g_handle, m_nAxis, m_creep);ZAux_Direct_SetFastDec(g_handle, m_nAxis, m_FastDec);ZAux_Direct_SetRsLimit(g_handle, m_nAxis, m_RsLimit);ZAux_Direct_SetFsLimit(g_handle, m_nAxis, m_FwdLimit);ZAux_Direct_SetMaxSpeed(g_handle, m_nAxis, m_nMaxSpeed);//设定对应轴的原点输入口信号ZAux_Direct_SetDatumIn(g_handle, m_nAxis, m_datumin);//ZMC系列认为OFF时碰到了原点信号(常闭) ,如果是常开传感器则需要反转输入口,ECI系列的不需要反转ZAux_Direct_SetInvertIn(g_handle, m_datumin, 1);  //设定对应轴的正限位输入口信号ZAux_Direct_SetFwdIn(g_handle, m_nAxis, m_FwdIn);//ZMC系列认为OFF时碰到了原点信号(常闭) ,如果是常开传感器则需要反转输入口,ECI系列的不需要反转ZAux_Direct_SetInvertIn(g_handle, m_FwdIn, 1);//设定对应轴的负限位输入口信号ZAux_Direct_SetRevIn(g_handle, m_nAxis, m_RevIn);//ZMC系列认为OFF时碰到了原点信号(常闭) ,如果是常开传感器则需要反转输入口,ECI系列的不需要反转ZAux_Direct_SetInvertIn(g_handle, m_RevIn, 1);UpdateData(false);  }

(5)通过停止运动按钮的事件处理函数来停止当前的运动。

void CSingle_homeDlg::OnStop()          //停止运动{// TODO: Add your control notification handler code hereif(NULL == g_handle){MessageBox(_T("链接断开状态"));return ;}ZAux_Direct_Single_Cancel(g_handle,m_nAxis,2);        //}

(6)通过坐标清零按钮的事件处理函数来对当前轴的坐标进行对应清零。

void CSingle_homeDlg::OnZero()          //坐标清零{if(NULL == g_handle){MessageBox(_T("链接断开状态"));return ;}// TODO: Add your control notification handler code herefor (int i=0;i<4;i++) {ZAux_Direct_SetDpos(g_handle,i,0);        //设置零点} }

(7)通过轴持续运行按钮的拦截按钮响应时间来判断当前按钮状态是抬起还是按下触发对应轴的持续运动以及停止状态。

BOOL CSingle_homeDlg::PreTranslateMessage(MSG * pMsg){//正向持续运动if (pMsg->message == WM_LBUTTONDOWN){if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_FWD)->m_hWnd){//TODO:ZAux_Direct_Single_Vmove(g_handle, m_nAxis, 1);}}//松开停止运动else if (pMsg->message == WM_LBUTTONUP){if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_FWD)->m_hWnd){//TODO:ZAux_Direct_Single_Cancel(g_handle,m_nAxis,2);}}//负向持续运动if (pMsg->message == WM_LBUTTONDOWN){if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_RWD)->m_hWnd){// TODO: 在此添加控件通知处理程序代码ZAux_Direct_Single_Vmove(g_handle, m_nAxis, -1);//TODO:}}//松开停止else if (pMsg->message == WM_LBUTTONUP){if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_RWD)->m_hWnd){//TODO:ZAux_Direct_Single_Cancel(g_handle, m_nAxis, 2);}}return CDialog::PreTranslateMessage(pMsg);}

三、调试与监控

编译运行例程,同时通过ZDevelop软件连接控制器对控制器状态进行监控。

1.连接ZDevelop软件,并点击“视图”→“示波器”打开示波器对轴运动情况进行监控。

2.当运行过程中,脉冲当量乘以速度得到的脉冲频率大于设置的maxspeed最大脉冲频率时,将会对应报警1000h,显示在界面上。

→当超过软件限位限制时也会停止并对应报警。

3.ZDevelop软件调试视频

简单易用的运动控制卡(十二):运动控制系统的安全设置

本次,正运动技术简单易用的运动控制卡(十二):运动控制系统的安全设置,就分享到这里。

更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师。

本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。

简单易用的运动控制卡(十二):运动控制系统的安全设置相关推荐

  1. 简单易用的运动控制卡(十四):PWM、模拟量输出与运动控制的同步

    今天,正运动技术给大家分享一下运动控制卡之ECI3808如何使用C++编写控制器设置运动与PWM以及模拟量同步. 一.ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线 ...

  2. 简单易用的运动控制卡(十):连续插补和小线段前瞻

    今天,正运动技术给大家分享一下运动控制卡之ECI3808如何使用C++操作使用连续插补运动以及小线段前瞻. 一.ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线插补. ...

  3. 简单易用的运动控制卡(十一):运动的暂停恢复和速度倍率设置

    今天,正运动技术给大家分享一下运动控制卡之ECI3808如何使用C++操作使用连续插补运动以及小线段前瞻. 一.ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线插补. ...

  4. 简单易用的运动控制卡(五):IO配置与回零运动

    今天,正运动技术给大家分享一下运动控制卡之ECI3808如何使用C++编写控制器回零运动并对应配置IO. 一.ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线插补.任 ...

  5. 简单易用的运动控制卡(一):硬件接线和上位机开发

    今天,正运动小助手给大家分享一下运动控制卡之ECI3808的硬件接线和如何进行MFC的上位机开发. 一 .ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达 12 轴直线插补.任 ...

  6. 简单易用的运动控制卡(六):Basic文件下载和连续轨迹加工

    今天,正运动技术给大家分享一下运动控制卡之ECI3808的".bas"文件的下载和运行. 一.ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线插补 ...

  7. 简单易用的运动控制卡(三):轴参数配置和单轴运动控制

    今天,正运动小助手给大家分享一下运动控制卡之ECI3808的轴参数配置和单轴运动控制. 一. ECI3808硬件介绍 1.功能介绍 ECI3808系列控制卡支持最多达12轴直线插补.任意圆弧插补.空间 ...

  8. 一个简单的blog系统(十二) 增加友情链接页面

    一个简单的blog系统(十二) 增加友情链接页面 1.首先,我们打开header.ejs,在其中添加一行代码,并作出响应修改: <li><a href="/links&qu ...

  9. 史上最简单的 MySQL 教程(十二)「列属性 之 唯一键」

    史上最简单的 MySQL 教程(十二)「列属性 之 唯一键」 唯一键 唯一键:每张表往往有多个字段需要具有唯一性,数据不能重复,但是在每张表中,只能有一个主键,因此唯一键就是用来解决表中多个字段需要具 ...

最新文章

  1. vue更新data中的数据页面不渲染_vue更新obj类data的属性无效,页面data没刷新解决方法vue.set...
  2. 脚本中echo显示内容带颜色显示
  3. java轻量级IOC框架Guice
  4. R语言ineq算基尼系数_5 月编程语言排行榜:Java第一,R跌出Top20
  5. python xpath语法-Python xpath表达式如何实现数据处理
  6. boost::hana::transform用法的测试程序
  7. 机器学习第九篇:详解Adaboost算法
  8. telegraf输出MySQL_Grafana+influxdb+telegraf初探-快速监控主机与mysql
  9. php变量显示,php – 显示会话变量
  10. mysql5.6无法安装_windows下Mysql5.6的安装
  11. [转载] python标准库系列教程(三)——operator库详细教程
  12. MySQL中用生日计算年龄
  13. dnf连接服务器黑屏xp系统,windows xp进入桌面后黑屏的解决技巧
  14. python sdk是什么_SDK 和 API 的区别是什么?
  15. 关于数据分析师的4点思考
  16. 西普实验吧CTF-Hashkill
  17. 样本方差为什么要除n-1,而不是n
  18. Pycharm提示No Python interpreter selected怎么解决
  19. 微信小程序 - 获取用户当前位置信息(用于定位地址及获取地址等需求)
  20. 什么是MyBatis?怎么操作MyBatis?

热门文章

  1. 自编码器(Auto-encoder)的概念和应用
  2. 最全16套vue.js入门和项目实战+素材+源码
  3. OllyDbg插件编写
  4. U盘启动安装CentOS Linux系统
  5. 【Java】Date类型获取年月日时分秒的两种方法(12小时制、24小时制)
  6. 南京信息工程大学第十届程序设计大赛试题
  7. 计算机网络:移动IP
  8. Oracle 11g 中恢复管理器RMAN介绍
  9. 深度linux系统wifi信号变弱,在Deepin 20社区版下WiFi网速变慢的处理
  10. 软件设计模式——监听模式