最近尝试使用从MATLAB端键入输入,将输入值传给DSP,DSP运算之后将结果传回MATLAB并显示。我所设置的PC的IP地址是192.168.2.101,DSP的IP地址是192.168.2.100,端口号是7。DSP作为server端,MATLAB作为client端。

  • MATLAB的TCP/IP通信实现

我所要实现的功能函数有三个输入:T、fa、i,一个输出:H,都是double型的数,也就是每个数的大小是8个字节。从MATLAB端键入的代码及注释如下:

clear all
t = tcpip('192.168.2.100',7, 'NetworkRole', 'client'); %前两个参数是远程主机(DSP)的ip地址和端口,最后一个参数要写MATLAB的NetworkRole
fclose(t); %关闭TCP/IP
t.inputbuffersize=1024; %设置输入缓冲区为1024b,缺省值为512b,根据自己传输的数据大小来调整,不要比传输的数据小
t.outputbuffersize=1024; %设置输出缓冲区为1024b
t.Timeout=30;%最长等待连接的时间
set(t,'ByteOrder','littleEndian'); %设置为小端模式,DSP和MATLAB的字节序应一致避免麻烦
buffer1=input('T='); %在MATLAB键入输入值
buffer2=input('fa=');
buffer3=input('i=');
fopen(t); %连接TCP/IP对象
tic %计时开始
fwrite(t, buffer1,'double'); %将buffer1里的数据以'double'的格式写入t
fwrite(t, buffer2,'double');
fwrite(t, buffer3,'double');
H=fread(t,1,'double'); %以'double'的格式从t里读出1个数据并写入H
toc %计时结束
format longE; %以LongE的格式显示
fprintf('H=%f\n',H); %在MATLAB平台上显示输出值
fclose(t); %关闭TCP/IP
delete(t); %删除TCP/IP    
  • DSP的TCP/IP通信实现

我采用的DSP是TI公司的TMS320C6657,CCS采用的是5.5版本,通信例程是在TI官方的helloworld例程的基础上改写的。在编写程序之前,首先要确定自己导入的helloworld例程的products被正确设置,我截取我的例程采用的products如下图:

主要是XDCtools、MCSDK、NDK、SYS/BIOS相互之间以及它们与CCS之间的版本要匹配,TI官网给出了相关的版本要求,如果不满足要求,就会出现编译错误。一开始我没有发现这个问题,版本都是随机下载选择的,出现了很多奇奇怪怪搜索不到的错误,卡了好多天,很难受,大家如果嫌麻烦直接按我这个图上的版本配置就好。

下一步就是对helloworld例程的理解与修改,我采用的是TCP而非UDP,另外我用的是固定IP方式,而非DHCP。helloworld的代码我们主要关注的就是两个,一个是helloWorld.c,这个几乎是TCP/IP通信的模板代码,不管是什么TCP/IP的例程中都会有一个文件与这个文件几乎完全相同,里面主要是EVM_init、StackTest、NetworkOpen、NetworkClose、NetworkIPAddr、 ServiceReport这几个函数。另一个是udpHello.c,这是收发数据的代码。helloworld中还有一个cfg文件,我对它的功能搞得不是很清楚,这个文件我没有动,也没有影响最终的功能的实现。如果有哪位朋友懂的话,希望可以一起讨论下。helloWorld.c的代码与及注释如下,其中中文字体是我改动的地方:

#include <stdio.h>
#include <math.h>  //这是我所实现的功能所要用到的库
#include <ti/ndk/inc/netmain.h>
/* BIOS6 include */
#include <ti/sysbios/BIOS.h>/* Platform utilities include */
#include "ti/platform/platform.h"
#include "ti/platform/resource_mgr.h"/* Platform Information - we will read it form the Platform Library */
platform_info  gPlatformInfo;//---------------------------------------------------------------------------
// Title String
//
char *VerStr = "\nTCP/IP Stack 'Hello World!' Application\n\n";// Our NETCTRL callback functions
static void   NetworkOpen();
static void   NetworkClose();
static void   NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd );// Fun reporting function
static void   ServiceReport( uint Item, uint Status, uint Report, HANDLE hCfgEntry );// External references
extern int dtask_udp_hello();//---------------------------------------------------------------------------
// Configuration
//
char *HostName    = "tidsp";
char *LocalIPAddr = "192.168.2.100";    //DSP的IP地址
char *LocalIPMask = "255.255.255.0";    // 掩码
char *GatewayIP   = "192.168.2.101";    // 网关
char *PCStaticIP   = "192.168.2.101";   // PC的IP地址
char *DomainName  = "demo.net";         // Not used when using DHCP
char *DNSServer   = "0.0.0.0";          // Used when set to anything but zero/**************************************************************************  @b EVM_init()* *  @n**  Initializes the platform hardware. This routine is configured to start in *   the evm.cfg configuration file. It is the first routine that BIOS*   calls and is executed before Main is called. If you are debugging within*  CCS the default option in your target configuration file may be to execute *  all code up until Main as the image loads. To debug this you should disable*  that option. **  @param[in]  None* *  @retval*      None************************************************************************/
void EVM_init() //对DSP开发板的初始化,若使用GEL文件则不需要这一步
{int i;platform_init_flags  sFlags;platform_init_config sConfig;/* Status of the call to initialize the platform */Int32 pform_status;/* Platform Information - we will read it form the Platform Library */platform_info       sPlatformInfo;/** You can choose what to initialize on the platform by setting the following* flags. We will initialize everything.*/memset( (void *) &sFlags,  0, sizeof(platform_init_flags));memset( (void *) &sConfig, 0, sizeof(platform_init_config));sFlags.pll = 0;sFlags.ddr = 0;sFlags.tcsl = 0;    /* Time stamp counter   */sFlags.phy  = 0; //实际上在使用以太网时这里应该设为1,但是我的库函数可能有一些问题,使用这个EVM_init函数对板子初始化,会出现无法link的情况,于是我把这里设为0,利用GEL文件初始化板子   sFlags.ecc = 0;sConfig.pllm = 0;pform_status = platform_init(&sFlags, &sConfig);/* If we initialized the platform okay */if (pform_status == Platform_EOK) {/* Get information about the platform so we can use it in various places */memset( (void *) &sPlatformInfo, 0, sizeof(platform_info));(void) platform_get_info(&sPlatformInfo);}else {/* Intiialization of the platform failed... die */printf("Platform failed to initialize. Error code %d \n", pform_status);printf("We will die in an infinite loop... \n");while (1) {(void) platform_led(1, PLATFORM_LED_ON, (LED_CLASS_E) PLATFORM_USER_LED_CLASS);(void) platform_delay(50000);(void) platform_led(1, PLATFORM_LED_OFF, (LED_CLASS_E) PLATFORM_USER_LED_CLASS);(void) platform_delay(50000);};}platform_write_configure(PLATFORM_WRITE_PRINTF);platform_uart_init();platform_uart_set_baudrate(19200);/* Check to see that we are running on the Master Core */if (platform_get_coreid() != 0) {/* We are not on the Master Core... die */printf("You must run this application on Core 0. \n");printf("We will die in an infinite loop... \n");while (1) {(void) platform_led(1, PLATFORM_LED_ON, (LED_CLASS_E) PLATFORM_USER_LED_CLASS);(void) platform_delay(50000);(void) platform_led(1, PLATFORM_LED_OFF, (LED_CLASS_E) PLATFORM_USER_LED_CLASS);(void) platform_delay(50000);};}/* Clear the state of the LEDs to OFF */for (i=0; i < sPlatformInfo.led[1].count; i++) {platform_led(i, PLATFORM_LED_OFF, (LED_CLASS_E) PLATFORM_USER_LED_CLASS);}return;
}//---------------------------------------------------------------------
// Main Entry Point
//---------------------------------------------------------------------
int main()
{/* Start the BIOS 6 Scheduler */BIOS_start ();
}//
// Main Thread
//
int StackTest()
{int             rc;int        i;HANDLE          hCfg;//// THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION before//  using the stack!!//rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );if( rc ){platform_write("NC_SystemOpen Failed (%d)\n",rc);for(;;);}// Print out our bannerplatform_write(VerStr);//// Create and build the system configuration from scratch.//// Create a new configurationhCfg = CfgNew();if( !hCfg ){platform_write("Unable to create configuration\n");goto main_exit;}//// THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!!///*   rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );if( rc ){printf("NC_SystemOpen Failed (%d)\n",rc);for(;;);}// Print out our bannerprintf(VerStr);//// Create and build the system configuration from scratch.//// Create a new configurationhCfg = CfgNew();if( !hCfg ){printf("Unable to create configuration\n");goto main_exit;}
*/// We better validate the length of the supplied namesif( strlen( DomainName ) >= CFG_DOMAIN_MAX ||strlen( HostName ) >= CFG_HOSTNAME_MAX ){printf("Names too long\n");goto main_exit;}// Add our global hostname to hCfg (to be claimed in all connected domains)CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,strlen(HostName), (UINT8 *)HostName, 0 );// If the IP address is specified, manually configure IP and Gateway// if (!platform_get_switch_state(1))if(1){CI_IPNET NA;CI_ROUTE RT;IPN      IPTmp;// Setup manual IP addressbzero( &NA, sizeof(NA) );NA.IPAddr  = inet_addr(LocalIPAddr);NA.IPMask  = inet_addr(LocalIPMask);strcpy( NA.Domain, DomainName );NA.NetType = 0;// Add the address to interface 1CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0,sizeof(CI_IPNET), (UINT8 *)&NA, 0 );// Add the default gateway. Since it is the default, the// destination address and mask are both zero (we go ahead// and show the assignment for clarity).bzero( &RT, sizeof(RT) );RT.IPDestAddr = inet_addr(PCStaticIP);  //这里官网给的是0,是不对的,应该按我这样写RT.IPDestMask = inet_addr(LocalIPMask); //这里官网给的是0,是不对的,应该按我这样写RT.IPGateAddr = inet_addr(GatewayIP);// Add the routeCfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );// Manually add the DNS server when specifiedIPTmp = inet_addr(DNSServer);if( IPTmp )CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );platform_write("EVM in StaticIP mode at %s\n",LocalIPAddr);platform_write("Set IP address of PC to %s\n", PCStaticIP);}// Else we specify DHCPelse{CI_SERVICE_DHCPC dhcpc;// Specify DHCP Service on IF-1bzero( &dhcpc, sizeof(dhcpc) );dhcpc.cisargs.Mode   = CIS_FLG_IFIDXVALID;dhcpc.cisargs.IfIdx  = 1;dhcpc.cisargs.pCbSrv = &ServiceReport;CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,sizeof(dhcpc), (UINT8 *)&dhcpc, 0 );}//// Configure IPStack/OS Options//// We don't want to see debug messages less than WARNINGSrc = DBG_WARN;CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );//// This code sets up the TCP and UDP buffer sizes// (Note 8192 is actually the default. This code is here to// illustrate how the buffer and limit sizes are configured.)//// TCP 发生 buffer 大小rc = 8192;CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF,CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );// TCP 接收 buffer 大小(复制模式)rc = 8192;CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXBUF,CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );// TCP 接收buffer 大小(非复制模式)rc = 8192;CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXLIMIT,CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );// UDP 接收buffer 大小rc = 8192;CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );//// Boot the system using this configuration//// We keep booting until the function returns 0. This allows// us to have a "reboot" command.//do{rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );} while( rc > 0 );// Delete ConfigurationCfgFree( hCfg );// Close the OS
main_exit:platform_write("Exiting the system\n");NC_SystemClose();return(0);
}//
// System Task Code [ Server Daemon Servers ]
//
static HANDLE hHello=0;//
// NetworkOpen
//
// This function is called after the configuration has booted
//
static void NetworkOpen()
{// Create our local server//hHello = DaemonNew( SOCK_DGRAM, 0, 7, dtask_udp_hello,//                  OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );hHello = DaemonNew( SOCK_STREAM, 0, 7, dtask_udp_hello,OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );  //因为我采用的是TCP而非UDP,所以这里改动了一下,被注释掉的代码是UDP//DaemonNew函数每个参数的具体含义参考NDK v2.21 API Reference Guide的5.4.1//DaemonNew是指创建一个Daemon Server,这个Server可以理解为官网编辑好的一个Server,它的具体代码我忘记在哪里了,但是我记得里面已经包含socket通信中Server所要实现的bind、listen、accept的功能,因此我们只需要编写收发数据以及自己要实现的功能的代码即可
}//
// NetworkClose
//
// This function is called when the network is shutting down,
// or when it no longer has any IP addresses assigned to it.
//
static void NetworkClose()
{DaemonFree( hHello );
}//
// NetworkIPAddr
//
// This function is called whenever an IP address binding is
// added or removed from the system.
//
static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
{IPN IPTmp;if( fAdd )printf("Network Added: ");elseprintf("Network Removed: ");// Print a messageIPTmp = ntohl( IPAddr );printf("If-%d:%d.%d.%d.%d\n", IfIdx,(UINT8)(IPTmp>>24)&0xFF, (UINT8)(IPTmp>>16)&0xFF,(UINT8)(IPTmp>>8)&0xFF, (UINT8)IPTmp&0xFF );
}//
// Service Status Reports
//
// Here's a quick example of using service status updates
//
static char *TaskName[]  = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };
static char *ReportStr[] = { "","Running","Updated","Complete","Fault" };
static char *StatusStr[] = { "Disabled","Waiting","IPTerm","Failed","Enabled" };
static void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
{printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",TaskName[Item-1], StatusStr[Status],ReportStr[Report/256], Report&0xFF );//// Example of adding to the DHCP configuration space//// When using the DHCP client, the client has full control over access// to the first 256 entries in the CFGTAG_SYSINFO space.//// Note that the DHCP client will erase all CFGTAG_SYSINFO tags except// CFGITEM_DHCP_HOSTNAME. If the application needs to keep manual// entries in the DHCP tag range, then the code to maintain them should// be placed here.//// Here, we want to manually add a DNS server to the configuration, but// we can only do it once DHCP has finished its programming.//if( Item == CFGITEM_SERVICE_DHCPCLIENT &&Status == CIS_SRV_STATUS_ENABLED &&(Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPADD) ||Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPRENEW)) ){IPN IPTmp;// Manually add the DNS server when specifiedIPTmp = inet_addr(DNSServer);if( IPTmp )CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );}
}

udpHello.c的代码及注释如下:

#include <ti/ndk/inc/netmain.h>
#include <stdio.h> //我的功能所用到的库
#include <math.h>  //我的功能所用到的库double t2h(double T, double fa, double i);
double t2h_Taylor(double T, double fa);
void t2h_Polynomial( double FARX, double TEX, double* CSEX, double* AKEX, double* CPEX, double* REX, double* PHI, double* HEX ); //这三个函数是我自己的功能函数,忽略即可//
// Returns "1" if socket 's' is still open, and "0" if its been closed
//
int dtask_udp_hello( SOCKET s, UINT32 unused ) //函数名还是udp,但是里面我已经改成tcp的了;用s表示socket对象
{struct sockaddr_in sin1;struct timeval     to;int                i0;HANDLE             hBuffer;(void)unused;unsigned char      pBuft[8],pBuffa[8],pBufi[8],pBufh[8]; //前三个数组是用来存放从MATLAB那读取的T、fa、i的值的,最后一个数组是存放运算结果H的//由于MATLAB端传过来的数据都是double型,也就是8个字节//因此这里用含8个unsigned char数据的数组来存放MATLAB传回来的数值double T,fa,i,H; //我的功能函数的输入值// Configure our socket timeout to be 30 seconds//设置socket等待连接的最长时间to.tv_sec  = 30;to.tv_usec = 0;setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof( to ) );setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof( to ) );for(;;){i0 = (int)recv(s, &pBuft, 8, 0);//把socket(即s)接收到的数据复制8个字节到pBuft数组中,i0的值是复制的字节数,显然应该为8//因为MATLAB和DSP都是小端字序,所以socket接收到的前8个字节显然是T的值//收发函数有很多,比如:recv、recvnc、recvfrom等等,它们的参数是不同的,在socket.h中可以看到//具体使用哪个收发函数看个人情况//在helloWorld.c中,DaemonNew函数的第一个参数,可以选择SOCK_STREAM、SOCK_STREAMNC或SOCK_DGRAM,我猜测三个选哪一个和这里的接收函数的选择要对应起来//比如前面选择SOCK_STREAMNC,这里就要用recvnc;前面选择SOCK_DGRAM,也就是UDP协议,这里就要用recvfrom或者recvncfrom//带nc的指non-copy模式,带from的需要指定socket address,因此UDP协议必须要用这种if(i0==8){memcpy(&T,pBuft,8);//虽然MATLAB发送的T是double型的,但在实际传输时,是以二进制数据流传输的//前面把接收到的数据放入了含8个unchar的数据的数组中,而我们需要的输入值T应该是double型的//此句的作用就是数据类型的转换,把unsigned char类型的数组转为一个double型的数i0 = (int)recv( s, &pBuffa, 8 ,0 );//将socket接收到的fa的值复制到pBuffa中if(i0==8){memcpy(&fa,pBuffa,8);i0 = (int)recv( s, &pBufi, 8 ,0 );//将socket接收到的i的值复制到pBufi中if(i0==8){memcpy(&i,pBufi,8);}else break;}else break;}else break;H=t2h(T,fa,i); memcpy(pBufh,&H,8);//我的功能函数send(s,&pBufh,8,0);//将pBufh的值复制到socket的发送buffer中,等待MATLAB的接收请求}return(1); //保持socket开启
}

在DSP代码完成后,将开发板上电并运行程序,电脑上可以先不用MATLAB,而是打开cmd,输入ping 192.168.2.100,能ping通的话就说明DSP这边的网络连接没有问题。

代码展示完后,我想总结一下我在运行DSP代码中遇到的一些问题:

  1. 在点击debug和load之后有一段等待时间,这时尽量不要切出CCS的页面否则在运行时容易出现错误。
  2. 如果在点击load之后没有点击resume,代码自己就处于runnning状态了,多次尝试都是这样,说明代码虽然编译通过但是仍有bug,自己好好再检查一下。
  3. unable to restore CPU specific source container(有点忘了是不是这个问题,只记得带CPU这个词)这个问题是由于当前project的CCS版本和你的CCS版本不兼容,方法是在Target Configurations窗口中找到这个project的.ccxml文件,右击然后选择Launch selected Configuration进入debug页面,找到所要运行的核,右击选择connect,成功后load即可。
  4. 将代码固化在板子上目前还有一些问题,前面也说了,我如果用EVM_init函数对板子初始化,就会出现无法板子连接网络的问题,可能是我的库文件还有一些问题,需要再琢磨一下,也希望有了解相关知识的朋友能够不吝赐教。
  • PC与DSP开发板的连接与设置

使用网线,一端插入开发板上的网口,另一端插入电脑。这时打开控制面板,查看适配器设置,会出现下图中的图标:

右键打开这个适配器的“属性”,双击下图中的红圈里的内容,然后将之前对PC的IP地址和掩码的设定填入图中右边相应的位置:

设置好之后给开发板上电,先运行DSP中的程序,再运行MATLAB中的程序,两个的先后顺序不要搞反了,然后就可以在MATLAB中看到正确的结果。

在网上找到的做相关应用的很少,因此这个项目很是折磨了我一番,我把我的项目经历记录一下分享出来,希望大家可以一起讨论,同时也算是我自己对项目的梳理与总结。如有不当之处,请各位指正!

MATLAB与DSP(C6657)的TCP/IP通信实现相关推荐

  1. 《Linux高性能服务器编程》学习总结(四)——TCP/IP通信案例:访问Internet上的Web服务器...

    第四章      TCP/IP通信案例:访问Internet上的Web服务器 HTTP协议是工作在应用层上的协议,其应用十分广泛,而在进行通信的过程中,经常使用HTTP代理服务器.HTTP代理服务器主 ...

  2. TCP/IP通信程序设计方式

    刚接触TCP/IP通信设计的人根据范例可以很快编出一个通信程序,据此一些人可能会认为TCP/IP编程很简单.其实不然,TCP/IP编程具有较为丰富的内容.其编程的丰富性主要体现在通信方式和报文格式的多 ...

  3. TCP/IP 通信示例

    TCP/IP 通信示例 Global String ReadData_P_All$, ReadData_P$(10), data$ ' Global Preserve Double x Global ...

  4. EPSON TCP/IP 通信

    EPSON SCARA机器人TCP/IP 通信时,涉及到的相关指令说明. 14.3 TCP/IP命令. OpenNet //打开TCP/IP端口. ChkNet //返回端口状态:等待读取的字节数或错 ...

  5. Linux内核协议栈分析之——tcp/ip通信并不神秘

    Jack:计算机如何进行通信? 我:我可以告诉你带Linux操作系统的计算机如何进行通信. Jack:带Linux操作系统的计算机?这和不带操作系统的计算机有区别吗? 我:有的. Jack:哦.那你说 ...

  6. 川崎机器人总线通信_川崎机器人TCP/IP通信方法及编程过程介绍

    川崎机器人的TCP/IP通信除了直接与川崎机器人通信外,有一种方式是通过PLC间接通信,附上我的另一篇文章,讲c#与三菱PLC通信的: 首先假设一个简单的应用情况,有一台带相机的川崎机器人,需要在机器 ...

  7. 51单片机 ENC28J60 TCP/IP通信

    51单片机 ENC28J60 TCP/IP通信 单片机:STC90C516RD+ ENC28J60模块:mini(3.3V供电) 设备:PC.开发板.两个网线.路由器 首先先介绍一下本文的移植针对于单 ...

  8. qt之TCP/IP通信客户端与服务器自动连接互相传输数据

    一.前言 在开发上位机软件,用的最多的通信就是网络通信,串口通信和USB通信,串口通信相对是最容易的,USB通信在前面的文章中也专门写了一个博客介绍USB HID通信方式,见链接:https://bl ...

  9. STM32通过广和通ADP-L610-Arduino进行TCP/IP通信

    STM32通过广和通L610进行TCP/IP通信 一. 写在前面   本次参加嵌入式大赛,使用了广和通的ADP-L610-Arduino板子进行通信.项目要求大概是本地上传数据到服务器,服务器接收后发 ...

最新文章

  1. xml转json和实体类的两种方式
  2. 高德地图自定义点标记大小_Vue:如何在地图上添加自定义覆盖物(点)
  3. 什么是GDT,LDT,GDTR及LDTR?
  4. IOS 实现TXT文本自动识别编码的方法
  5. 有一列数列,1,11,21,1211,111221,.........,
  6. 2017百度之星复赛:1006. Valley Numer(数位DP)
  7. 大数据开发笔记(六):Flume基础学习
  8. Ubuntu安装JDK1.8
  9. kafka-client 版本兼容问题
  10. java bitset_Java1.8-BitSet源码分析
  11. 编写函数void reverse(string s),用递归算法使字符串s倒叙
  12. 什么是IPFS?(三)
  13. Linux中reboot和shutdown的异同
  14. 写给大家看的CSS书,写给大家看的设计书
  15. 不一样的课程表,不一样的Excle--用Excle进行设计(12):网状结构
  16. 足坛十大恶汉:张玉宁黑社会风波 辽猛将踢爆眼
  17. Web前端面试指导(四十四):什么是响应式开发?
  18. cucumber介绍及简单使用
  19. 初中信息技术计算机课件,初中信息技术说课课件
  20. Windows 10 如何安装adb工具并配置变量环境

热门文章

  1. 【转载】com.mysql.jdbc.Driver 与 org.gjt.mm.mysql.Driver的区别
  2. Java 操作 word 文档 (二)初识 WordprocessingML 标签
  3. 联通服务器光信号亮红灯移动,联通los红灯闪啥意思(图文)
  4. 我的Java学习之路(三)-- 自动饮料售卖机控制台程序
  5. 加权均值滤波matlab,模糊加权均值滤波器
  6. 自学Java day12 使用jvav实现链表 从jvav到架构师
  7. OpenFOAM+petsc
  8. SAAS 技术栈回顾
  9. Quartus联合modelsim的ip核仿真——以FIFO为例——(报错问题解决)
  10. amd用不了android studio,解决AMD无法使用Android studio问题