了解更多开源请访问:开源基础软件社区https://ost.51cto.com基于TCP遥控小车开发本文主要介绍如何使用TCP控制hi3861中的小车。在使用TCP控制小车之前,需要先连接wifi。TCP传输控制协议是一种提供可靠数据传输的协议。它是一种连接的、顺序数据传输的、面向字节流的、可靠稳定的协议。TCP通信设备分为客户端和服务器。本文中服务器建立在windows上,hi3861作为客户端,两者连接手机的wifi进行TCP通信(必须在同一个网络)。下面主要介绍如何以hi3861为客户端建立tcp连接。客户端代码介绍客户端在连接TCP前必须保证连接wifi,而hi3861连接wifi需要几十亿的时间,所以建议连接wifi后sleep()几秒,这样hi3861可以连接wifi。首先创建一个Socket对象,并创建一个客户端socket对象。socket()这次只需要注意参数1和参数2,参数1表示ipv4,参数2表示使用面向连接的套接字(TCP)。返回值:如果创建失败,返回-1。intsocks;socks=socket(AF_INET,SOCK_STREAM,0);创建一个sockaddr_in结构体对象,存放服务器地址的参数,并初始化对象的成员。结构sockaddr_insock_addr={0};sock_addr.sin_family=AF_INET;//ipv4sock_addr.sin_port=PP_HTONS(8888);//IP端口sock_addr.sin_addr.s_addr=inet_addr("192.168.xx.xx");//ip地址connect()连接函数,它的作用是用一个连接协议完成一个连接过程。上面两步创建的结构体对象会在这一步用到,这也是TCP连接中最关键的一步。返回值:连接成功则返回0,失败则返回-1。参数1:指定发送数据的socket。参数二:指定服务器地址,使用sockaddr_in结构对象。参数3:参数2结构connect(socks,(structsockaddr*)&sock_addr,sizeof(sock_addr))的长度;以上步骤就完成了hi3861客户端和服务端的连接,接下来我们就可以愉快的和服务通信了,基于无线连接的收发数据,我们可以做出各种有趣好玩的东西。API接口。发送数据:函数:lwip_write(ints,constvoid*dataptr,size_tsize);参数1:socket对象,参数2:发送数据,参数3:数据长度。例子:staticconstchar*buf="你好!我是HI3861TCP客户端!!!!!!";lwip_write(袜子,buf,strlen(buf));接收数据:函数:lwip_read(intfildes,void*buf,size_tnbyte);参数1:socket对象,参数2:接收数据,参数3:数据长度。示例:charrecv_buf[64];(void)memset_s(recv_buf,sizeof(recv_buf),0,sizeof(recv_buf));lwip_read(socks,recv_buf,sizeof(recv_buf)-1);超时机制:在TCP连接中,recv等函数默认为阻塞模式,即没有数据传输时会停留在函数中。有时候我们不想一直停留在这个函数中,所以需要一个超时机制setsockopt(),即使过了一定时间,如果没有数据,函数也会退出。函数:intsetsockopt(ints,intlevel,intoptname,void*optval,socklen_t*optlen)。参数一:指向一个打开的套接字描述符。参数二:指定optioncode的类型|选项代码类型|意思||----|----||SOL_SOCKET|基本套接字||IPPROTO_IP|IPv4套接字||IPPROTO_IPV6|IPv6套接字||IPPROTO_TCP|TCP套接字|。参数3:选项名称SO_RCVTIMEO:设置接收超时时间。参数四:选项值。参数五:参数的长度例子:structtimevalrecev_timeout;recev_timeout.tv_sec=5;recev_timeout.tv_usec=0;/*5S超时*/ret_a=setsockopt(socks,SOL_SOCKET,SO_RCVTIMEO,recev_timeout,sizeof(recev_timeout));这个函数还有很多其他的用法,本文就不过多介绍了,如果需要了解更多可以百度一下。关键代码头文件和一些宏定义://tcp#include#include"lwip/sockets.h"charrecv_buf[64];//io#include"iot_gpio.h"#include#include#defineGPIO00#defineGPIO11#defineGPIO99#defineGPIO1010main函数中的代码://连接wifi后/**********************************************/睡眠(5);结构sockaddr_insock_addr={0};诠释;sock_addr.sin_family=AF_INET;sock_addr.sin_port=PP_HTONS(_PROT_);sock_addr.sin_addr.s_addr=inet_addr(IP_argv[0]);s=socket(AF_INET,SOCK_STREAM,0);如果(s<0){printf(“套接字假\n”);}intret_a;ret_a=connect(s,(structsockaddr*)&sock_addr,sizeof(sock_addr));if(ret_a!=0){printf("connectfalse\n");}my_car_init();//初始化小车电机IO口while(1){(void)memset_s(recv_buf,sizeof(recv_buf),0,sizeof(recv_buf));ret_a=lwip_read(s,recv_buf,sizeof(recv_buf)-1);//等待接收服务器发送数据printf("服务器:%d!\n",recv_buf[0]);//判断接收到的数据是什么键,49对应前进键,50对应后退键,51左键,52右键if(recv_buf[0]==49){car??_forward();printf("car_forward!\n");}elseif(recv_buf[0]==50){car??_stop();printf("车停了!");}elseif(recv_buf[0]==51){car??_left();}elseif(recv_buf[0]==52){car??_right();}}小车控制代码:#defineGPIO00#defineGPIO11#defineGPIO99#defineGPIO1010voidmy_car_init(void){//IO口初始化IoTGpioInit(GPIO0);IoTGpioInit(GPIO1);IoTGpioInit(GPIO10);IoTGpioInit(GPIO9);//IO口复用hi_io_set_func(GPIO0,HI_IO_FUNC_GPIO_0_GPIO);//在hi_io.h中有定义hi_io_set_func(GPIO1,HI_IO_FUNC_GPIO_1_GPIO);hi_io_set_func(GPIO10,HI_IO_FUNC_GPIO_10_GPIO);hi_io_set_func(GPIO9,HI_IO_FUNC_GPIO_9_GPIO);//IO口功能设置,输入或输出IoTGpioSet1Dirp(outp,GPIO0)r(GPIO1,1);IoTGpioSetDir(GPIO10,1);IoTGpioSetDir(GPIO9,1);//IO口输出电压IoTGpioSetOutputVal(GPIO0,IOT_GPIO_VALUE1);//VALUE1为高电平,VALUE0为低电平IoTGpioSetOutputVal(GPIO1,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO9,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO10,IOT_GPIO_VALUE1);}voidcar_stop(void){IoTGpioSetOutputVal(GPIO0,IOT_GPIO_VALUE1);//左轮IoTGpioSetOutputVal(GPIO1,IOT_GPIO_VALUE1);//左轮IoTGpioSetOutputVal(GPIO9,IOT_GPIO_VALUE1);//右轮IoTGpioSetOutputVal(GPIO10,IOT_GPIO_VALUE1);//右轮}voidcar_forward(void){IoTGpioSetOutputVal(GPIO0,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO1,IOT_GPIO_VALUE0);IoTGpioSetOutputVal(GPIO9,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO10,IOT_GPIO_VALUE0);}voidcar_left(void){IoTGpioSetOutputVal(GPIO0,IOT_GPIO_VALUE0);IoTGpioSetOutputVal(GPIO1,IOT_GPIO_VALUE0);IoTGpioSetOutputVal(GPIO9,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO10,IOT_GPIO_VALUE0);}voidcar_right(void){IoTGpioSetOutputVal(GPIO0,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO1,IOT_GPIO_VALUE0);IoTGpioSetOutputVal(GPIO9,IOT_GPIO_VALUE1);IoTGpioSetOutputVal(GPIO10,IOT_GPIO_VALUE1);}win10中的服务端:编译gcc-oserverserver.c-lwsock32运行软件./serverIP地址端口。#include#include#include#include#includeintkey;intstartup(int_port,constchar*_ip){WSADATAws;WSAStartup(MAKEWORD(2,2),&ws);intsock=socket(AF_INET,SOCK_STREAM,0);如果(袜子<0){错误(“套接字”);退出(1);}结构sockaddr_in本地;local.sin_family=AF_INET;local.sin_port=htons(_port);local.sin_addr.s_addr=inet_addr(_ip);intlen=sizeof(local);if(bind(sock,(structsockaddr*)&local,len)<0)//绑定{perror("bind");退出(2);}if(listen(sock,5)<0)//允许的最大连接数为5,listen{perror("listen");退出(3);}returnsock;}intmain(intargc,constchar*argv[]){intlisten_sock=startup(atoi(argv[2]),argv[1]);//初始化//用来接收客户端的socket地址结构structsockaddr_inremote;intlen=sizeof(structsockaddr_in);而(1){intsock=accept(listen_sock,(structsockaddr*)&remote,&len);//连接if(sock<0){perror("accept");继续;}printf("获取客户端,ip:%s,端口:%d\n",inet_ntoa(remote.sin_addr),ntohs(remote.sin_port));while(1){key=_getch();if(key>31&&key<127)/*如果不是特殊键*/{printf("%c键被按下\n",key);继续;}键=_getch();如果(key==72){发送(sock,"1",2,0);printf("按%c向上键\n",key);}elseif(key==80){send(sock,"2",2,0);printf("按下%c键\n",key);}elseif(key==75){send(sock,"3",2,0);printf("按下%c左键\n",key);}否则如果(键==77){发送(袜子,“4”,2,0);printf("按下%c右键\n",key);}}}return0;}印象想了解更多开源,请访问:开源基础软件社区https://ost.51cto.com