ETH+LAN8720A+STM32F4xx实现TCP通讯

通过CUBEMX配置,驱动LAN8720A芯片实现和电脑通过TCP通讯。

配置ETH

首先通过CUBEMX配置ETH的引脚,选择模式为RMII

根据原理图上的引脚进行对应的配置,还有一个是LAN8720A的复位引脚,我所使用的是PJ12

根据自己硬件连接去进行配置相应的引脚。

配置LWIP

关闭DHCP 根据自己电脑的ip地址和网关 进行手动配置静态ip,

这里PHY芯片选择LAN8742

这里选择freertosCMSIS_V1

然后生成代码

在lwip.c文件里在这里添加复位代码

在任务中初始化LWIP

然后编译烧录 此时应该是可以ping通状态

单片机作为服务器和客户端

新建一个.C文件 加入工程中,将以下代码复制进去

通过修改宏定义 TCP_MODE来切换服务器和客户端模式 TCP_MODE =2时为服务器模式 为3是客户端模式 自行修改相应的ip和端口号 去进行TCP连接。
 

 #include "tcpecho.h"
 #include "lwip/opt.h"
 #include "lwip/sys.h"
 #include "lwip/api.h"
 #include <lwip/sockets.h>

#define TCP_MODE 2		

 #if TCP_MODE ==2
 
/* socket_tcp_server.c */
#define SERVER_PORT 3333 // 端口号
#define BUFF_SIZE 1024
#define SERVER_IP "192.168.1.10"
static char ReadBuff[BUFF_SIZE];
uint8_t send_buf[]= "This is a TCP Client test...\n";

/* TCP服务器端(server)任务 */
void vTCPServer_Task(void *thread_param)
{ 
    int sfd, cfd;
    int read_len;                                // 读的数据长度
    struct sockaddr_in server_addr, client_addr; // 服务器和客户端的结构体
    socklen_t client_addr_len;
    // 创建socket
    sfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 socker连接 默认协议
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // 从本机获取
    // 绑定socket
    bind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); // 文件描述符 IP地址加端口号 addr长度 返回值
    // 监听socket
    listen(sfd, 5); // 文件描述符 握手队列总和
    // 等待客户端连接
    client_addr_len = sizeof(client_addr);
    cfd = accept(sfd, (struct sockaddr *)&client_addr, &client_addr_len); // 文件描述符 IP地址加端口号 返回值
//    printf("client is connect cfd = %d\r\n", cfd);
    while (1) // 等待客户端发送数据,然后进行大小写转换,再写回客户端
    {
				
        read_len = lwip_read(cfd, ReadBuff, BUFF_SIZE);
        for (int i = 0; i < read_len; i++)
        {
            ReadBuff[i] = toupper(ReadBuff[i]); // 小写转换为大写
        }
        lwip_write(cfd, ReadBuff, read_len);
    }
}

  void
 client_init(void)
 {
     sys_thread_new("server", vTCPServer_Task, NULL, 512, 4);
 }
   #endif
 #if TCP_MODE ==3
 /* socket_tcp_client.c */
#define CLIENT_PORT 3333 // 端口号
#define BUFF_SIZE 1024
#define CLIENT_IP "192.168.1.108"

static char ReadBuff[BUFF_SIZE];

/* TCP客户端端(client)任务 */
void vTCPClient_Task(void *thread_param)
{
    int cfd;
    int read_len;                   // 读的数据长度
    struct sockaddr_in client_addr; // 服务器结构体
    // 创建socket
    cfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 socker连接 默认协议
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(CLIENT_PORT);
    client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP); // 本机IPV4
	
    // 连接到服务器
    connect(cfd, (struct sockaddr *)&client_addr, sizeof(client_addr)); // 文件描述符 ip地址和端口号 大小
    while (1)
    {
        read_len = read(cfd, ReadBuff, BUFF_SIZE); // 等待服务器发送数据
        for (int i = 0; i < read_len; i++)
        {
            ReadBuff[i] = toupper(ReadBuff[i]); // 小写转换为大写
        }
        write(cfd, ReadBuff, read_len); // 再写回服务器
    }
}


  void
 client_init(void)
 {
     sys_thread_new("client", vTCPClient_Task, NULL, 512, 4);
 }

  #endif

 同时在.H文件里外部声明函数                   在主任务里运行函数即可

通过TCP与电脑连接上之后 发送小写字母回回复大写字母。

此时即完成了TCP通讯。

参考文档

bhttps://blog.csdn.net/qq_36347513/article/details/125931365

【STM32】HAL库-以太网外设-LAN8720A-LWIP-无操作系统_stm32 lan8720-CSDN博客

### STM32F4 使用 LAN8720 实现以太网接口配置教程 #### 准备工作 为了实现STM32F4LAN8720之间的网络通信,需准备必要的硬件和软件环境。确保拥有支持RMII模式的STM32F4开发板以及LAN8720A物理层芯片,并安装好STM32CubeMX、Keil MDK或其他IDE工具。 #### 配置STM32CubeMX 启动STM32CubeMX并创建新工程,选择对应的MCU型号后进入外设配置界面。激活ETH模块并将操作模式设定为“Ethernet Full-Duplex”,同时勾选RCC时钟设置里的MCO选项用于外部PHY供电[^1]。 #### 初始化代码修改 完成上述步骤生成初始化源文件之后,在`ethernetif.c`里找到`HAL_ETH_MspInit()`函数体内部加入如下语句来启用LAN8720A设备: ```c __IO uint32_t tickstart; tickstart = HAL_GetTick(); while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET){ if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE){ Error_Handler(); } } // Enable GPIOs clock __HAL_RCC_GPIOA_CLK_ENABLE(); // RMII_REF_CLK, RMII_MDIO, RMII_CRS_DV __HAL_RCC_GPIOB_CLK_ENABLE(); // RMII_TXD1 __HAL_RCC_GPIOC_CLK_ENABLE(); // RMII_RXD0, RMII_RXD1 __HAL_RCC_GPIOD_CLK_ENABLE(); // RMII_TX_EN, RMII_TXD0, LEDS __HAL_RCC_GPIOG_CLK_ENABLE(); // MDC /* Configure the Ethernet PHY interface (RMII mode)*/ GPIO_InitTypeDef GPIO_InitStruct; // PA1, PA2 and PA7 configuration as alternate function push-pull */ GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; /* RMII_REF_CLK, RMII_MDIO, RMII_CRS_DV */ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // PB13 Configuration as alternate function push-pull */ GPIO_InitStruct.Pin = GPIO_PIN_13; /* RMII_TXD1 */ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // PC1 and PC4 Configuration as alternate function push-pull */ GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4; /* RMII_RXD0, RMII_RXD1 */ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PD8, PD9, PD11 Configuration as alternate function push-pull */ GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_11; /* RMII_TX_EN, RMII_TXD0, RMII_MDC */ HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); ``` 以上代码片段负责配置与LAN8720相连的具体管脚属性及其复用功能[^2]。 #### 主程序逻辑编写 最后一步是在主循环内调用`MX_LWIP_Process()`方法处理来自LwIP协议栈的任务队列事件,从而维持正常的TCP/IP数据交换流程。这使得主机能够响应远程请求并向外界发送回应报文。 ```c int main(void) { ... while (1) { MX_LWIP_Process(); // Other tasks... osDelay(1); } } ``` 此部分实现了持续监听状态变化的功能,保证了系统的实时性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值