手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端STM32H7 内核是 Cortex M7 目前接触到与 M4 最大的区别就是 CACHE M7 有两个 CACHE DCACHE 和 ICACHE 因为这个 CACHE 踩了很多坑 本例程软硬件配置为 FreeRTOS LwIP LAN8720 在正点原子阿波罗开发板上测试 1 Cube 配置 RCC 都使用外部晶振 因为后面要用到 FreeRTOS cube 会建议使用 TIM1 作为 SYS 时钟源系统不考虑功

STM32H7内核是Cortex-M7,目前接触到与M4最大的区别就是CACHE,M7有两个CACHE,DCACHE和ICACHE。因为这个CACHE踩了很多坑。

本例程软硬件配置为:FreeRTOS+LwIP+LAN8720,在正点原子阿波罗开发板上测试

1. Cube配置

RCC都使用外部晶振,因为后面要用到FreeRTOS,cube会建议使用TIM1作为SYS时钟源

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端系统

不考虑功耗时钟频率直接拉到最高480MHz

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

ETH模块使能,配置为RMII模式,MAC地址随便填一个,这里能看到一个warning,说ETH模块只能运行在0x地址起始的RAM中,网上查了一下这个地址是AXI RAM,AXI是一种总线结构,这边先不用管,可以等进入工程后配置。然后就是确认ETH与物理层芯片相连的引脚是否正确,由于使用的是阿波罗开发板,原来默认的发送接口是B12、B13,需要改为G13、G14,最后使能ETH全局中断。这里会发现现在版本的Cube没有配置物理层芯片地址(PHY ADDR)的选项,不用担心,在程序中它会自己遍历0-31的物理地址,找到有应答的地址作为物理层芯片地址。除此之外,将ETH的GPIO口频率都设为最高。

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

启用FreeRTOS,可根据实际需求修改配置

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

启动LWIP发现是灰的,移到LWIP上会发现cortex-m7需要启用DCache才能使用LWIP

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

启用DCache后能正常启用LWIP

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

设置物理层芯片,这里只有LAN8742可以选,不过没关系,LAN8720也可以用,在通用设置里面可以选择启用哪些操作,这里使能了DNS

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

最后物理层芯片需要一个硬件复位信号引脚,由于阿波罗开发板中该引脚是由PCF8574芯片控制的,PCF8574芯片需要通过IIC控制,嫌麻烦就看了下正点原子给的原理图,直接把红框中的两个电阻焊掉用跳线连接LAN8720的复位引脚和H743的GPIO引脚,这个GPIO口随便选,这里用了A5。配置输出电平为High

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

网络部分的配置就这些,其他模块根据自己需求配置,比如串口、定时器等。这里使能了一个串口作为调试用,波特率直接给到了Bit/s,引脚改为A9A10

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

最后一步设置项目名称等,编译器使用了IAR8.3(编译比keil快很多),设置完了就生成代码

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

2. 工程配置

main.c中重定向printf用于打印消息,另外提供一个MPU配置函数

/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { //HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0xffff); while ((USART1->ISR & 0X40) == 0); USART1->TDR = (uint8_t) ch; return ch; } / * @brief Configure the MPU attributes * @param None * @retval None */ static void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct; /* Disable the MPU */ HAL_MPU_Disable(); /* Configure the MPU attributes as Device not cacheable for ETH DMA descriptors */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x; MPU_InitStruct.Size = MPU_REGION_SIZE_256B; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Configure the MPU attributes as Cacheable write through for LwIP RAM heap which contains the Tx buffers */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x; MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enable the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* USER CODE END 0 */

main()函数中调用MPU_config,并使能SRAM时钟

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在ethernetif.c文件的low_level_init函数中添加物理层重启语句

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在ethernetif.c文件的low_level_output函数中添加DCache语句

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在ethernetif.c文件的low_level_input函数中添加DCache语句

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在lwipopts.h文件末尾添加宏定义

#define LWIP_RAM_HEAP_POINTER    (0x)

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在中断文件stm32h7xx_it.c中先引入外部信号量,再在ETH中断中添加信号量释放函数

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

最后打开IAR的Project->Options->Linker->Config->Edit修改RAM起始地址

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

到这里就软件就配置完了,接下来是TCP客户端的实现

3. TCP客户端

创建TCP客户端的.c文件

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

加入代码

#include "lwip.h" #include "lwip/api.h" #include "stm32h7xx_hal.h" #include "cmsis_os.h" #include "socket.h" #include "dns.h" void DNS_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { uint32_t* ip = (uint32_t*)ipaddr; printf("DNS found: IP %d:%d:%d:%d\n",((*ip)&0xff),(((*ip)>>8)&0xff),(((*ip)>>16)&0xff),(((*ip)>>24)&0xff)); } void network_init(struct netconn *conn) { int sock = -1; conn = netconn_new(NETCONN_TCP); if (conn == NULL){ printf("Set new connection failed...\r\n"); return; } sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sock < 0){ printf("Get socket failed!... Try again...\r\n"); vTaskDelay(1000); } conn->socket = sock; } int network_connect(struct netconn *conn, char *hostname, int port) { int err; struct sockaddr_in sAddr; ip_addr_t addr; printf("Socket is:%d\r\n",conn->socket); err = dns_gethostbyname(hostname, &addr, DNS_found_cb, NULL); if(err != 0){ printf("DNS failed to get host by name : %d \n",err); return -1; } //addr.addr = htonl(addr.addr); sAddr.sin_addr.s_addr = *((in_addr_t*)(&addr)); sAddr.sin_family = AF_INET; sAddr.sin_port = htons(port); //netconn_bind(conn,IP_ADDR_ANY,port); err = lwip_connect(conn->socket, (struct sockaddr*)(&sAddr), sizeof(struct sockaddr)); if(err != 0){ printf("LwIP connect failed :%d \n", err); return -2; } return 0; } void tcp_client_task(void const * argument) { // struct netbuf *buf; // void *data; // u16_t len; err_t err; struct netconn conn; LWIP_UNUSED_ARG(argument); char ip4[] = "192.168.0.100"; uint16_t port = 30001; printf("Connecting to server: %s :%d ...\r\n",ip4,port); network_init(&conn); CONNECT: err = network_connect(&conn, ip4, port); if (err != ERR_OK){ printf("Connect to server failed:%d \tReconnecting...\r\n",err); vTaskDelay(3000); goto CONNECT; } printf("Connect to server successed!\r\n"); while(1) { vTaskDelay(2000); } } 

其中IP地址与端口需要根据自己服务器设置

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在main.c文件中添加TCP任务函数

extern void tcp_client_task(void const * argument);

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

定义全局变量的TCP任务句柄

osThreadId TCPTaskHandle;

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

在StartDefaultTask中添加TCP任务

osThreadDef(TCPClient, tcp_client_task, osPriorityNormal, 0, 2048); TCPTaskHandle = osThreadCreate(osThread(TCPClient), NULL);

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

如果需要debug可以打开lwip的debug功能,在debug.h中一下位置添加debug的宏定义

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

然后在opt.h文件中打开对应的Debug开关,如打开DHCP_DEBUG等等

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

大功告成,接下来就是烧录,并运行程序。观察串口打印的debug内容,可以看到lwip通过DHCP获得到了IP地址、网关及子网掩码

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

进入路由器配置页面,可以看到路由器中多了一个Uknown设备,地址为192.168.0.103

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

服务器端显示,有一个192.168.0.103的TCP客户端连接

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

ping也可以直接ping通

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端

 

4. 工程文件

STM32H743以太网通信TCP客户端实现

5. Reference

http://www.stmcu.org.cn/module/forum/thread-615089-1-3.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218942.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午11:07
下一篇 2026年3月17日 下午11:07


相关推荐

  • ftp客户端软件有哪些,有哪些ftp客户端软件值得推荐?

    ftp客户端软件有哪些,有哪些ftp客户端软件值得推荐?不知道大家对于 ftp 客户端软件的要求普遍是什么 但是我的要求是很简单的 主要就是好用 方便容易上手 使用起来很容易 不要太复杂的 其实我对于 ftp 软件的要求应该是大部分网站工作者的基本要求吧 下面是我使用过的比较推荐的 ftp 客户端软件 第一款 IIS7 服务器管理工具说实话 这个工具算是比较好的管理工具了 里面的功能除了批量管理 还有很多别的功能 主要也是功能也比较全面 相信大多数使用的网站工作人员都比较熟悉了 它里面还能够定时上传下载 定时备份和主动更新 把你花在更新上的经历都省了 IIS7 服务器管理

    2026年3月26日
    3
  • 10月国内开源大模型汇总[项目源码]

    10月国内开源大模型汇总[项目源码]

    2026年3月13日
    3
  • python字典详解_python需要学哪些

    python字典详解_python需要学哪些字典字典的key和value一一对应的,字典是可变的,也是有序的(python3.6版本开始字典有序),可迭代的增加元素当key不存在时,直接赋值a={"status"

    2022年8月6日
    10
  • idea 2021.03.02 激活码(最新序列号破解)

    idea 2021.03.02 激活码(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月18日
    444
  • PLSQL配置连接oracle

    PLSQL配置连接oracle安装前注意 先安装 oracle 客户端 再安装 PLSQL 不然会出现 ora12154 无法解析指定的错误告警 安装 oracle client1 点击 setup2 点击下一步 3 目录会自动填充好 点击下一步 4 这里安装类型选择安装用于开发应用程序 网络服务和基本客户机软件的工具 可根据个人情况选择 5 这里设置 Oracle Home 变量 点下一步即可 这里我自

    2026年3月19日
    2
  • tracker服务器地址_rack服务器

    tracker服务器地址_rack服务器tracker服务器内容精选换一换云审计服务支持删除已创建的追踪器。删除追踪器对已有的操作记录没有影响,当您重新开通云审计服务后,依旧可以查看已有的操作记录。DELETE/v1.0/{project_id}/tracker无无无请参见错误码。云审计服务目前仅支持删除已创建的数据类追踪器。删除追踪器对已有的操作记录没有影响,当您重新开通云审计服务后,依旧可以查看已有的操作记录。DELETE/…

    2022年10月1日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号