873浏览
查看: 873|回复: 0

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

[复制链接]
前言
虽然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
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail