STM32通过广和通ADP-L610-Arduino进行TCP/IP通信
原帖链接:
https://blog.csdn.net/qq_16175499/article/details/117852854?utm_source=app&app_version=4.9.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
一、 写在前面
本次参加嵌入式大赛,使用了广和通的ADP-L610-Arduino板子进行通信。项目要求大概是本地上传数据到服务器,服务器接收后发送给客户端,实现数据的传输。在这个项目中需要用到两个客户端,所以需要实现服务端的多线程操作。多线程我具体还没整明白,这篇文章介绍的还是单线程。TCP/IP通信协议的可靠性、可操作性、安全性等几个特征,正好是我这次项目所需要的。前前后后整了两天,写下这篇博客,分享下经验的同时也为自己写下备忘录。
二、材料准备
STM32开发板
ADP-L610-Arduino板子
公网IP
【注意】:实际上不限于STM32开发板,只要能进行串口通信的板子就行。运营商通常不会提供静态公网IP,所以需要我们购买一个服务器,下面会提供阿里云ECS云服务器的简单使用方法。
三、CS架构TCP/IP通信
Socket在应用层和传输层之间的一个抽象层,它把 TCP/IP 层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。Socket 起源于 UNIX,在 UNIX 一切皆文件的思想下,进程间通信就被冠名为文件描述符。Socket 保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是服务器与客户端之间的通信。两端都建立了一个 Socket 对象,然后通过 Socket 对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。
本示例代码的头文件是linux平台的,可以让服务端循环等待客户端连接,但目前仅支持单线程连接,多线程连接等我用上了会更新。
1.服务端server.c
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#define PORT 8088
#define BACKLOG 1
int main(){
int sockfd,new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size;
int client;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1){
printf("socket failed:%d",errno);
return -1;
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(PORT);
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0){
printf("bind error");
return -1;
}
listen(sockfd,BACKLOG);
char recvbuf[100];
char sendbuf[]="[\tServer]:server is recieved!";
while(1){
printf("[\tServer]:waitting for connecting\n");
client = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
if(client < 0){
printf("[\tClient]:connect fail!\n");
continue;
}
else{
printf("[\tServer]:**********************************\n");
printf("[\tServer]:connect success!port:%d\n",PORT);
}
printf("[\tServer]:waitting for messege....\n");
while(1){
int DataNum = recv(client,recvbuf,100,0);
recvbuf[DataNum]='\0';
if(strcmp(recvbuf,"exit") == 0) break;
if(strcmp(recvbuf,"systemexit") == 0) return 0;
printf("[\tRecv]:%s\n",recvbuf);
send(client,sendbuf,strlen(sendbuf),0);
}
printf("[\tClient]:client exit\n\n\n");
}
close(sockfd);
return 0;
}
2.客户端
通过ADP-L610-Arduino的TCP服务来连接。
四、服务器环境搭建
1.进入阿里云官网,点击产品->热门产品->云服务器ECS,随便买一个服务器。
2.进入控制台里的安全组
3.点击创建规则,自定义端口的值需要与服务端server.c中的端口号宏定义相同。
4.通过FileZilla将服务器程序server.c发送到服务器上,并在服务器上运行该程序。
四、开发板配置
1.将MCU和ADP-L610-Arduino的串口收发连接上。给两个开发版供电。
2.使用STM32CubeMX配置连接好的针脚。本示例中,USART1是与L610连接的串口,USART3是stlink的串口。二者的配置参数相同。
3.导出工程文件后,通过keil进行编辑。
3.1进入usart.c中,添加以下代码。
#include <stdio.h>
int fputc(int ch,FILE *f)
{
uint8_t temp=ch;
HAL_UART_Transmit(&huart1,&temp,1,2);
return temp;
}
3.2在main.c中添加以下代码。
void Creat_TCP(void)
{
HAL_Delay(3000);
printf("AT+MIPOPEN=1,,\"公网ip\",8088,0\r\n");
HAL_Delay(3000);
}
void Send_Data(char *bufferdata)
{
HAL_Delay(2000);
printf("AT+MIPSEND=1,13\r\n");
printf( "%s",bufferdata);
HAL_Delay(2000);
}
int i;
Creat_TCP();
for(i=0;i<5;i++){
Send_Data(senddata);
HAL_Delay(1000);
}
4.将程序烧写进MCU并运行即可完成功能。
五、注意事项
我是根据官方说明文档整理出来的,把一些对开发板启动后的初始化、检测都去除了,可以说非常精简,但是简单的同时也可能会出现错误。这个代码没有打印log信息的功能,因此运行程序时如果出错就挺麻烦。建议用到TCP的朋友还是好好写一个打印log的功能吧,可以用USART3做。
这个示例只是大致讲了下L610连接TCP服务器的步骤,我也是废了一定的功夫才整好的,如果有帮到你的话,请点个赞哟。