ESP32-C6开发板评测_使用w5500连接网络

2024-04-194849
AI 快速预览详细 收起
本文介绍了如何使用ESP32-C6开发板和W5500模块实现稳定的有线网络连接。首先,详细说明了引脚设置,然后提供了完整的参考代码,包括Socket响应部分。通过这些步骤,用户可以轻松实现低延时和高稳定性的有线网络连接。
前言
虽然esp32支持无线联网,也可以同时使用espnow和wifi功能,但是切换这两种网络比较麻烦。使用有线网络也可以提供更低的网络延时,和更稳定的网络访问。这里我们使用常见的w5500模块作为扩展模块 ,如下图所示。
ESP32-C6开发板评测_使用w5500连接网络图1

该模块使用SPI接口,ESP32C6可以使用SPI2作为通信设备。


1.1 引脚设置
我们先在esp idf官方示范代码里,复制eth网络基本工程(目录是esp-idf/examples/ethernet/basic/)到一个目录里。
复制了工程之后,我们需要设置spi的引脚(使用idf.py menuconfig命令),将对应引脚设置成图示的内容。

ESP32-C6开发板评测_使用w5500连接网络图2

1.2 参考代码

我在官网Eth网络示范代码的基础上,添加了socket响应部分的代码,完整代码如下
  1. /* Ethernet Basic Example
  2.    This example code is in the Public Domain (or CC0 licensed, at your option.)
  3.    Unless required by applicable law or agreed to in writing, this
  4.    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5.    CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include "esp_eth.h"
  8. #include "esp_event.h"
  9. #include "esp_log.h"
  10. #include "esp_netif.h"
  11. #include "ethernet_init.h"
  12. #include "freertos/FreeRTOS.h"
  13. #include "freertos/task.h"
  14. #include "nvs_flash.h"
  15. #include "sdkconfig.h"
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "lwip/err.h"
  19. #include "lwip/sockets.h"
  20. #include "lwip/sys.h"
  21. #include <lwip/netdb.h>
  22. static const char *TAG = "eth_example";
  23. /** Event handler for Ethernet events */
  24. static void eth_event_handler(void *arg, esp_event_base_t event_base,
  25.                               int32_t event_id, void *event_data) {
  26.   uint8_t mac_addr[6] = {0};
  27.   /* we can get the ethernet driver handle from event data */
  28.   esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
  29.   switch (event_id) {
  30.   case ETHERNET_EVENT_CONNECTED:
  31.     esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
  32.     ESP_LOGI(TAG, "Ethernet Link Up");
  33.     ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0],
  34.              mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  35.     break;
  36.   case ETHERNET_EVENT_DISCONNECTED:
  37.     ESP_LOGI(TAG, "Ethernet Link Down");
  38.     break;
  39.   case ETHERNET_EVENT_START:
  40.     ESP_LOGI(TAG, "Ethernet Started");
  41.     break;
  42.   case ETHERNET_EVENT_STOP:
  43.     ESP_LOGI(TAG, "Ethernet Stopped");
  44.     break;
  45.   default:
  46.     break;
  47.   }
  48. }
  49. /** Event handler for IP_EVENT_ETH_GOT_IP */
  50. static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
  51.                                  int32_t event_id, void *event_data) {
  52.   ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
  53.   const esp_netif_ip_info_t *ip_info = &event->ip_info;
  54.   ESP_LOGI(TAG, "Ethernet Got IP Address");
  55.   ESP_LOGI(TAG, "~~~~~~~~~~~");
  56.   ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
  57.   ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
  58.   ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
  59.   ESP_LOGI(TAG, "~~~~~~~~~~~");
  60. }
  61. void w5500(void) {
  62.   // Initialize Ethernet driver
  63.   uint8_t eth_port_cnt = 0;
  64.   esp_eth_handle_t *eth_handles;
  65.   ESP_ERROR_CHECK(example_eth_init(ð_handles, ð_port_cnt));
  66.   // Create instance(s) of esp-netif for Ethernet(s)
  67.   if (eth_port_cnt == 1) {
  68.     // Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and
  69.     // you don't need to modify default esp-netif configuration parameters.
  70.     esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
  71.     esp_netif_t *eth_netif = esp_netif_new(&cfg);
  72.     // Attach Ethernet driver to TCP/IP stack
  73.     ESP_ERROR_CHECK(
  74.         esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
  75.   } else {
  76.     // Use ESP_NETIF_INHERENT_DEFAULT_ETH when multiple Ethernet interfaces are
  77.     // used and so you need to modify esp-netif configuration parameters for
  78.     // each interface (name, priority, etc.).
  79.     esp_netif_inherent_config_t esp_netif_config =
  80.         ESP_NETIF_INHERENT_DEFAULT_ETH();
  81.     esp_netif_config_t cfg_spi = {.base = &esp_netif_config,
  82.                                   .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH};
  83.     char if_key_str[10];
  84.     char if_desc_str[10];
  85.     char num_str[3];
  86.     for (int i = 0; i < eth_port_cnt; i++) {
  87.       itoa(i, num_str, 10);
  88.       strcat(strcpy(if_key_str, "ETH_"), num_str);
  89.       strcat(strcpy(if_desc_str, "eth"), num_str);
  90.       esp_netif_config.if_key = if_key_str;
  91.       esp_netif_config.if_desc = if_desc_str;
  92.       esp_netif_config.route_prio -= i * 5;
  93.       esp_netif_t *eth_netif = esp_netif_new(&cfg_spi);
  94.       // Attach Ethernet driver to TCP/IP stack
  95.       ESP_ERROR_CHECK(
  96.           esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i])));
  97.     }
  98.   }
  99.   // Register user defined event handers
  100.   ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID,
  101.                                              ð_event_handler, NULL));
  102.   ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP,
  103.                                              &got_ip_event_handler, NULL));
  104.   // Start Ethernet driver state machine
  105.   for (int i = 0; i < eth_port_cnt; i++) {
  106.     ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
  107.   }
  108. }
  109. #define PORT 3333
  110. #define KEEPALIVE_IDLE 5
  111. #define KEEPALIVE_INTERVAL 5
  112. #define KEEPALIVE_COUNT 3
  113. static void do_retransmit(const int sock) {
  114.   int len;
  115.   char rx_buffer[128];
  116.   do {
  117.     len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
  118.     if (len < 0) {
  119.       ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
  120.     } else if (len == 0) {
  121.       ESP_LOGW(TAG, "Connection closed");
  122.     } else {
  123.       rx_buffer[len] =
  124.           0; // Null-terminate whatever is received and treat it like a string
  125.       ESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer);
  126.       // send() can return less bytes than supplied length.
  127.       // Walk-around for robust implementation.
  128.       int to_write = len;
  129.       while (to_write > 0) {
  130.         int written = send(sock, rx_buffer + (len - to_write), to_write, 0);
  131.         if (written < 0) {
  132.           ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
  133.           // Failed to retransmit, giving up
  134.           return;
  135.         }
  136.         to_write -= written;
  137.       }
  138.     }
  139.   } while (len > 0);
  140. }
  141. static void tcp_server_task(void *pvParameters) {
  142.   char addr_str[128];
  143.   int addr_family = (int)pvParameters;
  144.   int ip_protocol = 0;
  145.   int keepAlive = 1;
  146.   int keepIdle = KEEPALIVE_IDLE;
  147.   int keepInterval = KEEPALIVE_INTERVAL;
  148.   int keepCount = KEEPALIVE_COUNT;
  149.   struct sockaddr_storage dest_addr;
  150.   if (addr_family == AF_INET) {
  151.     struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
  152.     dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
  153.     dest_addr_ip4->sin_family = AF_INET;
  154.     dest_addr_ip4->sin_port = htons(PORT);
  155.     ip_protocol = IPPROTO_IP;
  156.   }
  157.   int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
  158.   if (listen_sock < 0) {
  159.     ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
  160.     vTaskDelete(NULL);
  161.     return;
  162.   }
  163.   int opt = 1;
  164.   setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  165.   ESP_LOGI(TAG, "Socket created");
  166.   int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
  167.   if (err != 0) {
  168.     ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
  169.     ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
  170.     goto CLEAN_UP;
  171.   }
  172.   ESP_LOGI(TAG, "Socket bound, port %d", PORT);
  173.   err = listen(listen_sock, 1);
  174.   if (err != 0) {
  175.     ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
  176.     goto CLEAN_UP;
  177.   }
  178.   while (1) {
  179.     ESP_LOGI(TAG, "Socket listening");
  180.     struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
  181.     socklen_t addr_len = sizeof(source_addr);
  182.     int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
  183.     if (sock < 0) {
  184.       ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
  185.       break;
  186.     }
  187.     // Set tcp keepalive option
  188.     setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
  189.     setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
  190.     setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
  191.     setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
  192.     // Convert ip address to string
  193.     if (source_addr.ss_family == PF_INET) {
  194.       inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str,
  195.                   sizeof(addr_str) - 1);
  196.     }
  197.     ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
  198.     do_retransmit(sock);
  199.     shutdown(sock, 0);
  200.     close(sock);
  201.   }
  202. CLEAN_UP:
  203.   close(listen_sock);
  204.   vTaskDelete(NULL);
  205. }
  206. void app_main(void) {
  207.   ESP_ERROR_CHECK(nvs_flash_init());
  208.   ESP_ERROR_CHECK(esp_netif_init());
  209.   ESP_ERROR_CHECK(esp_event_loop_create_default());
  210.   w5500();
  211.   xTaskCreate(tcp_server_task, "tcp_server", 4096, (void *)AF_INET, 5, NULL);
  212. }
复制代码


1.3 编译调试
在命令行运行idf.py flash monitor,可以看到终端有以下的输出

ESP32-C6开发板评测_使用w5500连接网络图3

可以看到,已经正确获取到了动态IP地址,接下来在另一个命令行输入,然后随意输入一些内容,可以看到esp32也将对应内容发送了回来。
  1. nc 192.168.50.248 3333
复制代码
ESP32-C6开发板评测_使用w5500连接网络图4

ESP32-C6开发板评测_使用w5500连接网络图5

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -