手把手教-单片机和w5500模块基于rt-thread中wiznet软件包的使用

news2024/11/17 17:28:37

一、开发环境

硬件:stm32f407野火开发板,w5500模块

软件:rt-thread操作系统,wiznet软件包,基于正点原子stm32f407的bsp包(需要根据实际修改系统时钟)

引脚连接方式:

d46c71ef8eb3e6fca1f7b5076bb62f01.png

单片机引脚:PB12,PB13,PB14,PB15,PC6,PB4

整个系统的连接方式:

开发板<---->路由器<---->电脑

二、软件包说明和适配

        WIZnet 软件包是 RT-Thread 基于 WIZnet 官网 ioLibrary_Driver 代码库的移植实现,目前只支持 W5500 设备。该软件包在原代码库功能的基础上,对接 RT-Thread SAL 套接字抽象层,实现对标准 BSD Socket APIs 的支持,完美的兼容多种软件包和网络功能实现,提高 WIZnet 设备兼容性。

目录结构:

f1ecb8f60322252fc5d523b83ea3e50e.png

依赖:

a27aadb60c73f86591a76e863f065837.png

添加软件包的步骤:

①使能spi2

1498058ee109f61626fffa654f80c02e.png

②添加wiznet软件包

45664079aa326b961931b899b5f9e431.png

引脚的值计算方式,例如:

PA3的值=16*0+3=3;

PB4的值=16*1+4=20;

PC6的值=16*2+6=38

③spi引脚初始化

0358d640b6608e655bf643f75b9938c6.png

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */


  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();


    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


    /* SPI1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  /* USER CODE BEGIN SPI1_MspInit 1 */


  /* USER CODE END SPI1_MspInit 1 */
  }
  else if(hspi->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspInit 0 */


  /* USER CODE END SPI2_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();


    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    //SPI2 GPIO Configuration


    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


  /* USER CODE BEGIN SPI2_MspInit 1 */


  /* USER CODE END SPI2_MspInit 1 */
  }


}

④修改头文件,将#include <sal_low_lvl.h> 改为#include <sal.h>。因为在软件包中未找到 sal_low_lvl.h 文件。(如果使用rt-thread studio开发工具时,不用修改,因为软件包中有sal_low_lvl.h 文件.....)

0cbb839a9402d955cc1a22f8d36c238e.png

⑤增加stm32f4头文件,初始化中注册spi20设备。

9fb536f6204ac4958bd6a087afe7181f.png

dadda7c1b3aa3081179ffab0d9837db8.png

三、socket代码

    ping 命令测试正常说明 WIZnet 设备网络连接成功,之后可以使用 SAL(套接字抽象层) 抽象出来的标准 BSD Socket APIs 进行网络开发(MQTT、HTTP、MbedTLS、NTP、Iperf 等),WIZnet 软件包支持的协议簇类型为:主协议簇为 AF_WIZ、次协议簇为 AF_INET。

测试代码-tcp client

#include <rtthread.h>
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
#include <netdb.h>
#include <string.h>
#include <finsh.h>
#define BUFSZ   1024
static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */
void tcpclient(int argc, char **argv)
{
    int ret;
    char *recv_data;
    struct hostent *host;
    int sock, bytes_received;
    struct sockaddr_in server_addr;
    const char *url;
    int port;
    if (argc < 3)
    {
        rt_kprintf("Usage: tcpclient URL PORT\n");
        rt_kprintf("Like: tcpclient 192.168.12.44 5000\n");
        return ;
    }
    url = argv[1];
    port = strtoul(argv[2], 0, 10);
    /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
    host = gethostbyname(url);
    /* 分配用于存放接收数据的缓冲 */
    recv_data = rt_malloc(BUFSZ);
    if (recv_data == RT_NULL)
    {
        rt_kprintf("No memory\n");
        return;
    }
    /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        /* 创建socket失败 */
        rt_kprintf("Socket error\n");
        /* 释放接收缓冲 */
        rt_free(recv_data);
        return;
    }
    /* 初始化预连接的服务端地址 */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    /* 连接到服务端 */
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
    {
        /* 连接失败 */
        rt_kprintf("Connect fail!\n");
        closesocket(sock);
        /*释放接收缓冲 */
        rt_free(recv_data);
        return;
    }
    while (1)
    {
        /* 从sock连接中接收最大BUFSZ - 1字节数据 */
        bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
        if (bytes_received < 0)
        {
            /* 接收失败,关闭这个连接 */
            closesocket(sock);
            rt_kprintf("\nreceived error,close the socket.\r\n");
            /* 释放接收缓冲 */
            rt_free(recv_data);
            break;
        }
        else if (bytes_received == 0)
        {
            /* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */
            closesocket(sock);
            rt_kprintf("\nreceived error,close the socket.\r\n");
            /* 释放接收缓冲 */
            rt_free(recv_data);
            break;
        }
        /* 有接收到数据,把末端清零 */
        recv_data[bytes_received] = '\0';
        if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0)
        {
            /* 如果是首字母是q或Q,关闭这个连接 */
            closesocket(sock);
            rt_kprintf("\n got a 'q' or 'Q',close the socket.\r\n");
            /* 释放接收缓冲 */
            rt_free(recv_data);
            break;
        }
        else
        {
            /* 在控制终端显示收到的数据 */
            rt_kprintf("\nReceived data = %s ", recv_data);
        }
        /* 发送数据到sock连接 */
        ret = send(sock, send_data, strlen(send_data), 0);
        if (ret < 0)
        {
            /* 接收失败,关闭这个连接 */
            closesocket(sock);
            rt_kprintf("\nsend error,close the socket.\r\n");
            rt_free(recv_data);
            break;
        }
        else if (ret == 0)
        {
            /* 打印send函数返回值为0的警告信息 */
            rt_kprintf("\n Send warning,send function return 0.\r\n");
        }
    }
    return;
}
MSH_CMD_EXPORT(tcpclient, a tcp client sample);

四、结果测试

12bf2d574c10203f135df45a34a9ef95.png

043a2b17c29d5e8d198b3679257776c7.png

欢迎关注个人公众号:嵌入式学习与实践

参考:

api手册:https://www.rt-thread.org/document/api/index.html

https://gitee.com/RT-Thread-Mirror/wiznet

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/727296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

镀金积分球——激光红外功率测量

中波红外激光作为干扰光源&#xff0c;可对红外导引头及红外观瞄设备实施压制式干扰&#xff0c;激光器远场功率密度分布是评价其作战效能的重要指标。通用的激光功率测量设备多基于近场&#xff0c;并且因接收口径有限&#xff0c;只能检测到很小特定区域内的激光功率&#xf…

专心当个工程师,也挺好~

正文 大家好&#xff0c;我是bug菌~ 今天主要是分享一些职场上的小小领悟吧&#xff1a; 1 双向思维 一个人有他的缺点&#xff0c;也必定存在其优点&#xff0c;不要动不动就局限的认为这个人这也不行&#xff0c;那也不行&#xff0c;再说当初你咋就把他招进来了呢&#xff1…

【Redis 】Redis 的脑裂现象和解决方案

文章目录 Redis 中的脑裂是什么&#xff1f;脑裂有什么影响&#xff1f;数据丢失一定是发生了脑裂吗&#xff1f;如何解决脑裂问题&#xff1f; Redis 中的脑裂是什么&#xff1f; 从名字分析&#xff0c;脑裂现象就是大脑裂开了&#xff0c;一个人如果有两个大脑&#xff0c;…

Golang每日一练(leetDay0116) 路径交叉、回文对

目录 335. 路径交叉 Self-crossing &#x1f31f;&#x1f31f;&#x1f31f; 336. 回文对 Palindrome Pairs &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/…

【PCIE】链路训练的TS训练序列解释

TS码流解释 TS1和TS2有序集合是PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;协议中使用的一种特殊数据包格式。这些有序集合用于在PCIe链路的训练阶段进行通信和控制。 TS1&#xff08;Training Sequence 1&#xff09;有序集合&#xff1a;TS1有…

Django实现简单的音乐播放器 2

在《Django实现简单的音乐播放器 1》前期准备的基础上开始开发。 效果&#xff1a; 目录 项目视图 创建视图方法 路由加载视图 加载模板 创建首页html文件 加载静态资源文件 加载静态文件 使用方法 启动服务器 加载数据表 创建表模型 生成表迁移 执行创建表 插入…

CRM中的多业务场景管理是什么?有哪些功能?

为了适应不同的客户需求和市场变化&#xff0c;很多企业开展了多个业务场景&#xff08;产品线、销售渠道等&#xff09;。这些多业务场景给企业的客户管理带来了很大的挑战&#xff0c;如何有效地管理多种业务是企业急需解决的问题。下面说说&#xff0c;多业务场景下的CRM管理…

在Window仿Linux终端命令学习Python

在Window仿Linux终端命令学习Python Echox 命令 -- 主要带颜色输出ls 命令findx 命令~~待续~~ python3 Echox 命令 – 主要带颜色输出 查看 python输出颜色&#xff08;终端控制台&#xff09; ls 命令 1、getopt 模块参数解析 &#xff1a; Python 命令行参数 2、os.getcwd…

怎么免费视频压缩器?这 9 个最佳免费视频压缩器教你轻松学会!

视频有多种格式、不同的大小和不同的压缩级别。但是&#xff0c;您可以使用最好的视频压缩器来&#xff1a; 减小文件大小提高压缩质量更好地服务您的观众 我们将列出九个领先的视频压缩软件精选&#xff0c;您今天可以免费使用它们来增强您的视频。 9 个顶级免费视频压缩软件…

7 字符和字符串的“+”操作

7.1 字符的“”操作 char类型的数据参与加法运算。如下&#xff1a; char a A; int b 10 ; int c a b ; System.out.println(c); 结果如下&#xff1a; 接收结果使用的是int数据类型&#xff0c;按照相加时哪个数据类型大&#xff0c;结果就是哪个数据类型的规则&#xff…

CMake 使用教程 (四)

1.0 日志 在 CMake 中可以用用户显示一条消息&#xff0c;该命令的名字为 message&#xff1a; message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)(无) &#xff1a;重要消息STATUS &#xff1a;非重要消息WARNING&#…

51从零开始学Java之详解Java中的包装类

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在上一篇文章中&#xff0c;壹哥给大家介绍了Java中的Object类&#xff0c;它属于我们开发时的常用类…

2023(WAIC)智能驾驶科技峰会丨拓数派大模型下的数据计算系统,助力汽车智能化产业数据增值

2023 智能驾驶科技峰会在上海圆满落幕&#xff0c;本次大会由世界人工智能大会&#xff08;WAIC&#xff09;组委会办公室指导&#xff0c;浦东新区人民政府支持&#xff0c;浦东新区科技和经济委员会、中国 &#xff08;上海&#xff09;自由贸易试验区管理委员会金桥管理局主…

【SAP-ABAP】RPR_ABAP_SOURCE_SCAN 搜索带特定字符串的程序

昨日问了懒神&#xff0c;才知道还有这功能&#xff0c;真好用 业务背景&#xff1a;需要查找系统中有哪些程序带了特定的字符串&#xff08;一般类似于某些条件写死了&#xff09; 程序&#xff1a;RPR_ABAP_SOURCE_SCAN 程序&#xff1a;RS_ABAP_SOURCE_SCAN SE38执行程序…

Blazor前后端框架Known功能介绍:系统安装激活及自定义

本章介绍系统安装与激活及其自定义功能。 概述 框架内置简单的系统安装功能。录入企业编码、名称、系统名称、产品密钥、管理员密码信息完成安装。可自定义高级安装功能&#xff0c;如安装数据库等您产品所需的安装信息。框架默认无需注册产品密钥&#xff0c;若产品需要安装…

【腾讯云IM】即时通讯的登录,登出,用户列表,私聊,图片发送

uniapp即时通讯 1&#xff0c;初始化&#xff08;刚开始就紧跟着文档走&#xff09;2&#xff0c;App.vue中项目引入腾讯云&#xff0c;&#xff08;附上账号在其他地方登陆的监听&#xff09;3&#xff0c;登录前必需3.1&#xff0c;获取登录id3.2&#xff0c;生成userSig&…

K8s 内存泄漏处理方法

问题描述&#xff1a; 1. 安装go环境 2. 下载地址: https://golang.google.cn/dl/[rootk8s-master home]# rm -rf /usr/local/go && tar -C /usr/local/ -zxvf go1.17.3.linux-amd64.tar.gz3. 永久配置go 环境[rootk8s-master home]# vim /etc/profile export GOPATH…

win10、mac如何使用desktop中的docker

1、安装相应系统的docker&#xff0c;安装完什么都不需要修改。 2、需要安装mysql的话首先使用命令行 3、需要把mysql等其他软件端口映射出来使用的命令 4、搞定&#xff1b;点击关闭和启动 可以安装很多软件哦&#xff0c;非常方便两条命令搞定&#xff0c;mysql、redis、mogo…

建筑物防雷工程的设计与施工

本文会介绍建筑物防雷工程的设计与施工的基本原理、方法和要求&#xff0c;以及一些典型的案例分析。建筑物防雷工程是为了保护建筑物及其内部设备、人员和财产免受雷电危害而采取的一系列技术措施。建筑物防雷工程应遵循《建筑物防雷设计规范》GB 50057-2010和《建筑物防雷工程…