目录
在W55RP20-EVB-PICO上设置UDP多播
组件
硬件组件
项目描述
UDP 多播是一种通信方法,它使用网络比单播或广播更高效地将单个数据包发送到多播组中的多个接收器。
-
主要特点:
-
将数据高效分发到多个接收器。
-
没有确认或重新传输(尽力而为)。
-
常见用例:
-
流媒体:实时视频或音频广播(例如 IPTV)。
-
游戏:实时多人游戏更新。
-
金融系统:市场数据分布。
-
物联网系统:设备同步或固件更新。
-
灾难警报系统:向多个设备发送紧急通知。
-
IPv4 组播地址范围 : 224.0.0.0 ~ 239.255.255.255 此范围是为多播通信保留的,可以划分如下:
-
224.0.0.0 ~ 224.0.0.255: 本地网络多播 仅限于同一子网,不遍历路由器。
-
239.0.0.0 ~ 239.255.255.255:组织特定的多播 在专用网络中使用,可以像单播地址一样进行配置。
设置
在这个 WCC 中,W55RP20-EVB-Pico 将充当 UDP 多播发送方,因此将进行多个Socket配置。
使用的接收器包括 W5500-EVB-Pico、W5100S-EVB-Pico、W5500-EVB-Pico2 和智能手机。
此外,由于多播将在本地网络中执行,因此 TTL 设置为 1,
setSn_TTL(SOCKET_ID, 1); // set TTL (1 : local)
地址配置为 224.0.0.1 范围。
static uint8_t multicast_ip[4] = {224, 0, 0, 6}; // multicast ip address
static uint16_t multicast_port = 29999; // multicast port
将配置的多播 IP 和端口设置为目标,如下所示。
setSn_DIPR(SOCKET_ID, multicast_ip); // destination IP setting
setSn_DPORT(SOCKET_ID, multicast_port); // destination port setting
组播与标准 ARP(地址解析协议)用法的不同之处在于,特定 IP 地址由多个接收方共享。由于组播 IP 地址直接转换为 MAC 地址,因此不需要 ARP。
因此,MAC 地址的转换方式如下:
uint8_t multicast_mac[6] = {
0x01, 0x00, 0x5e, // First 3 bytes of the multicast MAC address
multicast_ip[2] & 0x7f, // Last 23 bits of the IP address(first 7 bits of 224~239 : 1)
multicast_ip[3], // Last 2 bytes of the IP address
0x00 // Remaining byte is set to 0
};
并相应地进行配置。
// Set the MAC address (DHAR: Socket n Destination Hardware Address Register)
setSn_DHAR(SOCKET_ID, multicast_mac);
// Skip ARP (Address Resolution Protocol) and directly set the MAC address
setSn_CR(SOCKET_ID, Sn_CR_SEND_MAC);
发送方的执行界面如下。当在特定 GPIO 上检测到上升沿时,将发送消息。
UDP 多播接收器是参考下面的代码实现的,智能手机连接到同一个 Wi-Fi 网络,使用测试器应用程序进行测试。
以下屏幕显示了接收器的显示。
同时显示发送方和接收方的视频如下所示。
// UDP multicast sender
#include <stdio.h>
#include "port_common.h"
#include "wizchip_conf.h"
#include "w5x00_spi.h"
#include "w5x00_gpio_irq.h"
#include "socket.h"
#include "loopback.h"
#include "multicast.h"
#include "timer.h"
/* Clock */
#define PLL_SYS_KHZ (133 * 1000)
/* Buffer */
#define SOCKET_ID 1 // Socket number
#define ETHERNET_BUF_MAX_SIZE (1024 * 2) // Send and receive cache size
/* GPIO */
static void gpio_callback(void);
/* Timer */
static void repeating_timer_callback(void);
static time_t millis(void);
wiz_NetInfo net_info = {
.mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e}, // Define MAC variables
.ip = {192, 168, 11, 21}, // Define IP variables
.sn = {255, 255, 255, 0}, // Define subnet variables
.gw = {192, 168, 11, 1}, // Define gateway variables
.dns = {168, 126, 63, 1}, // Define DNS variables
.dhcp = NETINFO_STATIC}; // Define the DNCP mode
static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {
0,
};
uint8_t data[] = "Warning! GPIO14 state is HIGH!";
static uint8_t multicast_ip[4] = {224, 0, 0, 6}; // multicast ip address
static uint16_t multicast_port = 29999; // multicast port
int flag = 0;
volatile uint32_t prev_state = 0;
volatile uint32_t current_state = 0;
uint32_t start_ms = 0;
static volatile uint32_t g_msec_cnt = 0;
static void set_clock_khz(void);
int main()
{
uint16_t local_port = 5000;
uint8_t multicast_mac[6] = {
0x01, 0x00, 0x5e, // First 3 bytes of the multicast MAC address
multicast_ip[2] & 0x7f, // Last 23 bits of the IP address(first 7 bits of 224~239 : 1)
multicast_ip[3], // Last 2 bytes of the IP address
0x00 // Remaining byte is set to 0
};
gpio_init(14);
gpio_init(15);
gpio_set_dir(14, false);
gpio_set_dir(15, true);
gpio_put(15, 1);
set_clock_khz();
/*mcu init*/
stdio_init_all(); // Initialize the main control peripheral.
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize(); // spi initialization
wizchip_check();
wizchip_1ms_timer_initialize(repeating_timer_callback);
wizchip_gpio_interrupt_initialize(SOCKET_ID, gpio_callback);
network_initialize(net_info);
print_network_information(net_info); // Read back the configuration information and print it
setSn_DIPR(SOCKET_ID, multicast_ip); // Set destination IP
setSn_DPORT(SOCKET_ID, multicast_port); // Set destination port
setSn_DHAR(SOCKET_ID, multicast_mac); // Set the MAC address (DHAR: Socket n Destination Hardware Address Register)
setSn_CR(SOCKET_ID, Sn_CR_SEND_MAC); // Skip ARP (Address Resolution Protocol) and directly set the MAC address
setSn_TTL(SOCKET_ID, 1); // Set TTL (1 : local)
// Socket初始化
if (socket(SOCKET_ID, Sn_MR_UDP, local_port, SF_MULTI_ENABLE) != SOCKET_ID)
{
printf("Failed to open socket\n");
}
printf("Sends a message when GPIO14 detects a rising edge!\n");
while (1)
{ }
}
}
static void set_clock_khz(void)
{
// set a system clock frequency in khz
set_sys_clock_khz(PLL_SYS_KHZ, true);
// configure the specified clock
clock_configure(
clk_peri,
0, // No glitchless mux
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux
PLL_SYS_KHZ * 1000, // Input frequency
PLL_SYS_KHZ * 1000 // Output (must be same as no divider)
);
}
/* GPIO */
static void gpio_callback(void)
{
current_state = millis();
if((current_state - prev_state) > 500) {
sendto(SOCKET_ID, data, sizeof(data), multicast_ip, multicast_port);
printf("send!\n");
prev_state = current_state;
}
}
/* Timer */
static void repeating_timer_callback(void)
{
g_msec_cnt++;
}
static time_t millis(void)
{
return g_msec_cnt;
}