FreeRTOS + UDP通讯实验

  1. UDP协议简介

UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是一种无连接、不可靠的协议,它只是简单地实现从一端主机到另一端主机的数据传输功能,这些数据通过IP层发送,在网络中传输,到达目标主机的顺序是无法预知的,因此需要应用程序对这些数据进行排序处理,这就带来了很大的不方便,此外,UDP协议更没有流量控制、拥塞控制等功能,在发送的一端,UDP只是把上层应用的数据封装到UDP报文中,在差错检测方面,仅仅是对数据进行了简单的校验,然后将其封装到IP数据报中发送出去。而在接收端,无论是否收到数据,它都不会产生一个应答发送给源主机,并且如果接收到数据发送校验错误,那么接收端就会丢弃该UDP报文,也不会告诉源主机,这样子传输的数据是无法保障其准确性的,如果想要其准确性,那么就需要应用程序来保障了。

UDP协议的特点:

  1. 无连接、不可靠。
  2. 尽可能提供交付数据服务,出现差错直接丢弃,无反馈。
  3. 面向报文,发送方的UDP拿到上层数据直接添加个UDP首部,然后进行校验后就递交给IP层。而接收的一方在接收到UDP报文后简单进行校验,然后直接去除,数据递交给上层应用。
  4. 支持一对一,一对多,多对一,多对多的交互通信。
  5. 速度快,UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是

一个无状态的传输协议,所以它在传递数据时非常快,即使在网络拥塞的时候UDP也不会降低发送的数据。

  1. UDP常用端口号

与TCP协议一样,UDP 报文协议根据对应的端口号传递到目标主机的应用线程,同样的,传输层到应用层的唯一标识是通过端口号决定的,两个线程之间进行通信必须用端口号进行识别,同样的使用“IP 地址+端口号”来区分主机不同的线程。

常用的端口号如下:

UDP报文

UDP报文也被称为用户数据报,与TCP协议一样,由报文首部与数据区域组成。在UDP协议中,它只是简单将应用层的数据进行封装(添加一个 UDP 报文首部),然后传递到IP层,再通过网卡发送出去,因此,UDP数据也是经过两次封装,具体见下图。

UDP 报文结构示意图具体见下图:

端口号的取值在0~65535 之间;16bit的总长度用于记录UDP报文的总长度,包括8字节的首部长度与数据区域。

  1. FreeRTOS的创建套接字函数

函数原型:

xSocket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );

创建并启动一个套接字。

参数描述:

xDomain:网络类型,创建UDP套接字时必须使用参数FREERTOS_AF_INET。

xType:套接字接口类型,参数只能为FREERTOS_SOCK_STREAM或FREERTOS_SOCK_DGRAM。使用FREERTOS_SOCK_STREAM参数创建一个TCP套接字接口,使用FREERTOS_SOCK_DGRAM参数创建一个UDP套接字接口。

xProtocol:套接字协议类型,参数只能为FREERTOS_IPPROTO_TCP或者FREERTOS_IPPROTO_UDP。使用FREERTOS_IPPROTO_TCP参数将套接字协议类型设置为TCP,使用FREERTOS_IPPROTO_UDP参数将套接字协议类型设置为UDP。

返回值:

如果套接字创建成功,返回套接字句柄。如果FreeRTOS堆栈不足,返回FreeRTOS_VALID_SOCKET。

  1. FreeRTOS的设置套接字选项函数

BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );

设置指定套接字的指定参数。

参数描述:

xSocket:目标套接字,该套接字必须由FreeRTOS_socket()创建。

lLevel:该参数未使用。

lOptionName:修改的目标选项。参数选择见下图。pvOptionValue:修改的目标选项的值。不同的目标选项,参数值的类型也不同。参见上图。

xOptionLength:该参数未使用。

返回值:

如果参数lOptionName的值不属于合法值,返回FreeRTOS_ENOPROTOOPT。如果参数lOptionName的值属于合法值,返回0。

  1. FreeRTOS的向套接字发送数据函数

函数原型:

int32_t FreeRTOS_sendto( xSocket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, uint32_t ulFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );

将数据发送到套接字。该套接字必须由FreeRTOS_socket()创建。

参数描述:

xSocket:目标套接字,该套接字必须由FreeRTOS_socket()创建。

*pvBuffer:指针,指向要发送的数据缓冲区。如果使用标准发送,将数据拷贝只到IP堆栈缓冲区。如果使用零拷贝发送,则pvBuffer指向以前从IP堆栈获得的缓冲区,该缓冲区已经包含正在发送的数据。IP堆栈将控制缓冲区,而不是将数据复制到缓冲区中。

xTotalDataLength:要发送数据的字节数。

ulFlags:发送方式选项,使用标准发送或者零拷贝发送。

pxDestinationAddress:指向FreeRTOS_sockaddr结构的指针,该结构包含目标IP地址和端口号(将数据发送到的套接字)。

xDestinationAddressLength:该参数为使用。

返回值:

如果正常发送返回发送字节数,如果发送失败返回0。

  1. FreeRTOS的从套接字接收数据函数

函数原型:

int32_t FreeRTOS_recvfrom( xSocket_t xSocket, void *pvBuffer, size_t xBufferLength, uint32_t ulFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );

从套接字接收数据。该套接字必须由FreeRTOS_socket()创建。

参数描述:

xSocket:目标套接字,该套接字必须由FreeRTOS_socket()创建。

*pvBuffer:指针,指向储存接收数据的缓冲区。如果使用标准接收,将数据拷贝到接收缓冲区。如果使用零拷贝接收,那么*pvBuffer将被设置指向已经保存接收数据的缓冲区。PvBuffer用于从FreeRTOS_recvfrom()中传递对接收数据的引用,而不复制任何数据。

xBufferLength:接收缓冲区的字节大小。如果使用零拷贝,该参数无效。

ulFlags:接收方式选项,使用标准发送或者零拷贝发送。

pxSourceAddress:指向FreeRTOS_sockaddr结构的指针,该结构将被设置,以包含刚接收数据的套接字的IP地址和端口号。

pxSourceAddressLength:该参数未使用。

返回值:

如果接收超时返回FreeRTOS_EWOULDBLOCK,如果套接字没有绑定端口返回FreeRTOS_EINVAL,如果正常接收返回接收到的字节数。

部分代码、详细代码请参考附加资源。

#include "UDP_Demo.h"

#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_UDP_IP.h"

// 定义目标端口号
#define echoECHO_PORT	(6902)

struct freertos_sockaddr xEchoServerAddress;
Socket_t xSocket_UDP;
static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 2000 );

// 创建UDP套接字
void UDP_Creat(void)
{
	// 将目标端口和IP地址填入结构体
	xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
	xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,configECHO_SERVER_ADDR1,configECHO_SERVER_ADDR2,configECHO_SERVER_ADDR3 );
	
	// 创建UDP套接字
	xSocket_UDP = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	configASSERT( xSocket_UDP != FREERTOS_INVALID_SOCKET );

	// 设置接收超时时间
	FreeRTOS_setsockopt( xSocket_UDP, NULL, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, NULL );
}

// UDP发送函数
void UDP_Send(uint8_t *pSendBuff,uint32_t lBuffLen)
{
	// 调用套接字发送函数,将数据发送到套接字
	FreeRTOS_sendto(xSocket_UDP,pSendBuff,lBuffLen,0,&xEchoServerAddress,NULL);
}

// UDP接收函数
void UDP_Recive(uint8_t * buffer,uint32_t lBuffLen)
{
	// 调用套接字接收函数,从套接字接受数据
	FreeRTOS_recvfrom(xSocket_UDP,buffer,lBuffLen,0,&xEchoServerAddress,NULL);
}

uint8_t senddata[]=" Please send a message, the length is less than 90!";
uint8_t recivedata[100];

// UDP实验任务
void Task_UDPTest(void *pvParameters)   
{
	uint8_t num = 0;
	UDP_Creat();
	while(1)
	{
		if(num == 0) UDP_Send(senddata,sizeof (senddata));
		
		UDP_Recive(recivedata,sizeof(recivedata));
		if(recivedata[0] != 0)
		{
			num = 1;
			UDP_Send(recivedata,sizeof (recivedata));
			memset( ( void * ) recivedata, 0x00, sizeof( recivedata ) );
		}
		vTaskDelay(50 / portTICK_RATE_MS );
	}
}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32是一系列由意法半导体(STMicroelectronics)推出的32位微控制器。FreeRTOS是一个开源的实时操作系统,用于嵌入式系统的开发。UDP(User Datagram Protocol)是一种面向无连接的传输协议,适用于需要快速传输数据但不需要数据可靠性的应用。 在STM32上使用FreeRTOS可以提供实时性能和多任务处理的能力。对于使用UDP进行通信的应用,可以通过FreeRTOS的任务管理功能来创建和管理多个任务。每个任务可以独立运行,相互之间不会干扰。 使用FreeRTOSUDP功能,可以通过创建一个UDP任务来进行UDP通信。任务可以使用UDP协议传输数据,发送和接收UDP数据包。创建UDP任务需要使用FreeRTOS提供的网络堆栈和套接字API。 首先,在STM32上配置和初始化网络堆栈,包括初始化和配置网卡、IP地址、端口等。然后,创建一个UDP任务,该任务负责发送和接收UDP数据包。可以使用FreeRTOS的套接字API来发送和接收UDP数据包。 发送UDP数据包可以使用UDP的发送函数,将数据发送到目标地址和端口。接收UDP数据包可以使用UDP的接收函数,将接收到的数据包存储在缓冲区中。 使用FreeRTOSUDP功能可以方便地实现嵌入式系统中的UDP通信。通过使用任务管理功能,可以实现多任务处理,提高系统的实时性能。同时,使用UDP协议可以快速传输数据,适用于需要快速响应和实时性的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值