STM32F1网络编程-UDP通信(基于W5500网卡)

UDP通信(基于W5500网卡)

本次实例将实现UDP协议通信。在前面的文章中,已经实现对W5500的驱动移植、IP获取方式和简单的TCP客户端和TCP服务器实现,请参考:

UDP通信的主要步骤如下:

  • 1)查询socket状态。通过调用W5500驱动API的getSn_SR查询socket状态。(注意:W5500支持的socket编号为0~7)
  • 2)当socket状态为SOCK_UDP时,接收、处理远程主机数据,还可以将处理结果发送回远程主机
  • 3)当socket状态为SOCK_CLOSED时,创建本地UDP监听。

在STM32CubeIDE工程的Application目录下分别创建udp_demo.hudp_demo.c文件,其内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/\*
\* udp\_demo.h
\*
\* Created on: 2022年7月15日
\* Author: jenson
\*/

#ifndef UDP\_DEMO\_H\_
#define UDP\_DEMO\_H\_

void udp\_demo(void);

#endif /\* UDP\_DEMO\_H\_ \*/


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/\*
\* udp\_demo.c
\*
\* Created on: 2022年7月15日
\* Author: jenson
\*/

#include "app\_config.h"

#ifdef UDP\_DEMO

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "stm32f1xx\_hal.h"
#include "w5500.h"
#include "tcp\_server\_demo.h"

#define UDP\_DEMO\_BUFFER\_SIZE 2048
uint8\_t __udp_demo_buffer[UDP_DEMO_BUFFER_SIZE];

#define UDP\_LOCAL\_PORT 5100
#define UDP\_SOCK 0

void \_\_handle\_udp\_data(void) {
int32\_t ret;
uint16\_t size, sentsize;
uint8\_t udp_remote_ip[4];
uint16\_t udp_remote_port;
if ((size = getSn\_RX\_RSR(UDP_SOCK)) > 0) {
if (size > UDP_DEMO_BUFFER_SIZE)
size = UDP_DEMO_BUFFER_SIZE;
memset(__udp_demo_buffer, 0, UDP_DEMO_BUFFER_SIZE);
// 接收远程数据
ret = recvfrom(UDP_SOCK, __udp_demo_buffer, size, udp_remote_ip,
(uint16\_t\*) &udp_remote_port);
if (ret <= 0) {

printf("%d: recvfrom error. %ld\r\n", UDP_SOCK, ret);
return;
}
printf("udp recv from:%d.%d.%d.%d:%d\r\nlen=%d,%s\r\n",
udp_remote_ip[0], udp_remote_ip[1], udp_remote_ip[2],
udp_remote_ip[3], udp_remote_port, size, __udp_demo_buffer);
size = (uint16\_t) ret;
sentsize = 0;
while (sentsize != size) {
// 向远程发送数据
ret = sendto(UDP_SOCK, __udp_demo_buffer + sentsize,
size - sentsize, udp_remote_ip, udp_remote_port);
if (ret < 0) {
printf("%d: sendto error. %ld\r\n", UDP_SOCK, ret);
return;
}
sentsize += ret; // Don't care SOCKERR\_BUSY, because it is zero.
}
}
}

void udp\_demo(void) {
switch (getSn\_SR(UDP_SOCK)) {
case SOCK_UDP:
if (getSn\_IR(UDP_SOCK) & Sn_IR_RECV) {
setSn\_IR(UDP_SOCK, Sn_IR_RECV);
}
\_\_handle\_udp\_data();
break;
case SOCK_CLOSED:
// 本地监听
if (socket(UDP_SOCK, Sn_MR_UDP, UDP_LOCAL_PORT, 0) == UDP_SOCK) {
printf("opened udp lookback port = %d\r\n", UDP_LOCAL_PORT);
}
break;
}
}

#endif


最后,在main.c文件中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include <stdio.h>
#include "w5500\_port.h"
#include <string.h> // memcmp
#include "app\_config.h"
#ifdef UDP\_DEMO
#include "udp\_demo.h"
#endif
/\* USER CODE END Includes \*/

int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_USART1\_UART\_Init();
MX\_SPI1\_Init();
/\* USER CODE BEGIN 2 \*/
printf("-----STM32 W5500 Ethernet Demo-----\r\n");
w5500\_restart(); // hardware restart through RESET pin
wiznet\_register();
w5500\_network\_init\_static();
wiznet\_chip\_config();
/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/
//loopback\_tcpc(0, (uint8\_t\*) recv\_buff, destip, destport);
/\* USER CODE BEGIN 3 \*/
#ifdef UDP\_DEMO
udp\_demo();
#endif
}
/\* USER CODE END 3 \*/
}


文章来源: https://iotsmart.blog.csdn.net/article/details/125925570