Clion开发STM32之W5500系列(综合实验)

news2024/11/25 6:28:58

说明

  1. 此为w5500模块的综合实验测试模块,包含dhcp、dns、ntp
  2. 以上三个模块的驱动参考之前的文章,本篇不做说明.
  3. 使用的开发芯片 stm32f103vet6系列,外设接口使用的spi2

实验内容:

  1. 通过dhcp动态获取ip,
  2. 通过dns解析NTP服务域名的ip
  3. 通过NTP服务ip获取时间

w5500配置驱动

/*******************************************************************************
 *  Copyright (c) [scl]。保留所有权利。
 *     本文仅供个人学习和研究使用,禁止用于商业用途。
 ******************************************************************************/

#include "app_conf.h"
#include "w5500_config.h"


#if APP_CONFIG_W5500
#define  APP_CONFIG_W5500_DHCP      (1) /*W5500 应用层--DHCP*/
#define  APP_CONFIG_W5500_DNS       (1) /*W5500 应用层--DNS*/
#define  APP_CONFIG_W5500_NTP       (1) /*W5500 应用层--NTP*/

#define DBG_ENABLE
#define DBG_SECTION_NAME "w5500"
#define DBG_LEVEL W5500_DBG_LEVEL

#include "sys_dbg.h"
#include "w5500_dhcp.h"
#include "w5500_dns.h"
#include "w5500_ntp.h"

#define W5500_CS stm_port_define(B,12)
#define W5500_RST stm_port_define(C,7)


static SPI_HandleTypeDef *w5500_spi = NULL;

static void send_and_rec_bytes(uint8_t *in_dat, uint8_t *out_data, uint16_t len) {
    while (HAL_SPI_GetState(w5500_spi) != HAL_SPI_STATE_READY);
    HAL_SPI_TransmitReceive(w5500_spi, in_dat, out_data, len, 1000);
    while (HAL_SPI_GetState(w5500_spi) != HAL_SPI_STATE_READY);
}

static void send_only(uint8_t *in_data, uint16_t len) {
    HAL_SPI_Transmit(w5500_spi, in_data, len, 1000);
}

static void W5500_RST_HIGH(void) { stm_pin_high(W5500_RST); }

static void W5500_RST_LOW(void) { stm_pin_low(W5500_RST); }

static void W5500_CS_LOW(void) { stm_pin_low(W5500_CS); }

static void W5500_CS_HIGH(void) { stm_pin_high(W5500_CS); }

static bool w5500_dhcp_after_init(SOCKET s, uint8_t try_cnt, uint32_t wait_ms);

static bool w5500_dns_after_init(SOCKET s, uint8_t *domain, uint8_t try_cnt, uint32_t wait_ms);

static bool w5500_ntp_after_init(SOCKET s, uint8_t try_cnt, uint32_t wait_ms);

static void W5500_Driver_MspInit(void) {
    stm32_pin_mode(W5500_CS, pin_mode_output);  /*CS*/
    stm32_pin_mode(W5500_RST, pin_mode_output); /*RST*/
    stm_pin_low(W5500_RST);
    stm_pin_low(W5500_CS);
    /*初始化SPI外设*/
    /*W5500 支持 SPI 模式 0 及模式 3..MOSI 和 MISO 信号无论是接收或发送,均遵从从最高标志位(MSB)到最低标志位(LSB)的传输序列。*/
    bsp_SpiHandleInit(w5500_spi, SPI_BAUDRATEPRESCALER_2, spi_mode_3);
}

module_w5500_t w5500_conf = {
        .base_conf={
                .socket_num = 4,
                .rx_size={4, 4, 4, 4},
                .tx_size={4, 4, 4, 4},
        },
        .net_conf={
                .ip={192, 168, 199, 12},
                .gw={192, 168, 199, 1},
                .sub={255, 255, 255, 0},
        },
        .driver={
                .cs_high = W5500_CS_HIGH,
                .cs_low = W5500_CS_LOW,
                .rst_high= W5500_RST_HIGH,
                .rst_low=W5500_RST_LOW,
                .delay = HAL_Delay,
                .send_and_rec_bytes = send_and_rec_bytes,
                .send_only =send_only
        },
        .api = {
                .msp_init=W5500_Driver_MspInit,
        }
};
uint8_t ntp_domain[] = {"ntp.ntsc.ac.cn"}; /*ntp域名*/
static struct dns_conf net_dns_cnf = { /*dns服务配置*/
        .dns_server_ip={114, 114, 114, 114},
        .dns_port = 53,
        .delay_ms_cb = HAL_Delay
};
static struct ntp_conf net_ntp_conf = {
//        .ntp_server={114, 118, 7, 163},
        .ntp_port = 123,
        .delay_ms_cb = HAL_Delay
};


static void w5500_pre_init(void) {
    /*一般做数据加载,此时系统时钟使用的是内部时钟,如需要使用系统时钟的外设不在此进行初始化*/
    w5500_spi = conv_spi_handle_ptr(handle_get_by_id(spi2_id));
    /*初始化资源*/
    module_w5500_init(&w5500_conf);
    uint32_t uid0 = HAL_GetUIDw0();
    uint32_t uid1 = HAL_GetUIDw1();
    uint32_t uid2 = HAL_GetUIDw2();
    uint8_t mac[6] = {0, uid0 >> 8, uid1, uid1 >> 8, uid2, uid2 >> 8};
    memcpy(w5500_conf.net_conf.mac, mac, sizeof(mac));
#if APP_CONFIG_W5500_DHCP /*使用dhcp*/
    dhcp_config_registry(&w5500_conf);
    w5500_conf.net_conf_init = dhcp_init;/*使用dhcp init*/
#endif
}

static void w5500_init(void) {

    w5500_conf.api.msp_init();/*初始化*/
    w5500_conf.net_conf_init();

}


static void w5500_after_init(void) {
    uint8_t try_cnt;
    SOCKET sn = 1;/*使用的socket*/
#if APP_CONFIG_W5500_DHCP
    try_cnt = 10;
    if (!w5500_dhcp_after_init(sn, try_cnt, 500)) {
        LOG_D("w5500_dhcp_after_init try cnt over:%d", try_cnt);
        return;
    }
#endif
    uint8_t ip[4];
    w5500_reg_ip_read(ip);
    LOG_D("w5500_reg_ip_read:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
    w5500_reg_gw_read(ip);
    LOG_D("w5500_reg_gw_read:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
#if APP_CONFIG_W5500_DNS
    try_cnt = 5;
    dns_config_set(&net_dns_cnf);
    if (!w5500_dns_after_init(sn, ntp_domain, try_cnt, 500)) {
        LOG_D("w5500_dns_after_init try cnt over:%d", try_cnt);
        return;
    }

#endif

#if APP_CONFIG_W5500_NTP
    try_cnt = 5;
    ntp_config_set(&net_ntp_conf);
    if (!w5500_ntp_after_init(sn, try_cnt, 500)) {
        LOG_D("w5500_ntp_after_init try cnt over:%d", try_cnt);
        return;
    }
#endif
}

app_init_export(w5500_net_conf, w5500_pre_init, w5500_init, w5500_after_init);

#if APP_CONFIG_W5500_DHCP

static bool w5500_dhcp_after_init(SOCKET s, uint8_t try_cnt, uint32_t wait_ms) {
    for (uint8_t i = 0; i < try_cnt; ++i) {
        if (do_dhcp(s, wait_ms)) {
            return true;
        }
    }
    return false;
}

#endif
#if APP_CONFIG_W5500_DNS

static bool w5500_dns_after_init(SOCKET s, uint8_t *domain, uint8_t try_cnt, uint32_t wait_ms) {
    for (int i = 0; i < try_cnt; ++i) {
        if (do_dns(s, domain, net_ntp_conf.ntp_server, wait_ms)) {
            LOG_D("dns parse result ip:%d.%d.%d.%d",
                  net_ntp_conf.ntp_server[0], net_ntp_conf.ntp_server[1],
                  net_ntp_conf.ntp_server[2], net_ntp_conf.ntp_server[3]
            );
            return true;
        }
    }
    return false;
}

#endif

#if APP_CONFIG_W5500_NTP

static bool w5500_ntp_after_init(SOCKET s, uint8_t try_cnt, uint32_t wait_ms) {
    struct net_date_time *nt_tm = NULL;
    for (int i = 0; i < try_cnt; ++i) {
        nt_tm = ntp_date_time_get(s, wait_ms);
        if (nt_tm != NULL) {
            LOG_D("NTP TIME:%d-%02d-%02d %02d:%02d:%02d",
                  nt_tm->year, nt_tm->month, nt_tm->day,
                  nt_tm->hour, nt_tm->min, nt_tm->sec
            );
            HAL_TIM_Base_Start_IT(handle_get_by_id(tim6_id));
            return true;
        }
    }
    return false;
}

#endif
#endif





测试结果

在这里插入图片描述

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

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

相关文章

【oracle数据库】单行函数

Oracle数据库中的单行函数 1.字符函数2.数值函数3.转换函数4.判空函数5.条件取值 1.字符函数 --length()求字符串长度 select length(aslkd) from dual --substr(,起始点,截取长度) 起始点从1开始 截取字符串 select substr(asd,2,2) from dual --concat(,)字符串拼接 sele…

两个小封装电机驱动芯片:MLX813XX、A4950

一&#xff0e;MLX813XX MELEXIS的微型电机驱动MLX813XX系列芯片集成MCU、预驱动以及功率模块等能够满足10W以下的电机驱动。 相对于普通分离器件的解决方案&#xff0c;MLX813XX系列电机驱动芯片是一款高集成度的驱动控制芯片&#xff0c;可以满足汽车系统高品质和低成本的要…

[答疑]岛上没人穿鞋,卖鞋的愿景是什么

DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 Kris 2023-7-6 19:55 上次给我们批作业您举了个例子&#xff0c;说卖鞋给岛上没人穿鞋&#xff0c;觉得您的解读很新颖&#xff0c;不过当时没听太明白&#xff0c;翻您的书貌似没有这个内容。…

分布式存储在云环境下的应用和部署

随着互联网数据规模越来越大&#xff0c;并发请求越来越高&#xff0c;传统的关系数据库系统在性能、价格、可扩展性方面已经不能很好地满足需求。谷歌、亚马逊等互联公司率先在后台基础设施中引入超大规模分布式存储系统&#xff0c;用来解决海量数据的存储问题。与传统的集中…

自动化测试如何做?自动化测试疑难问题+解答,进阶高级测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 你们的自动化&…

QT的内存回收机制

QT的内存回收机制 QT中内存回收的本质 Qt中有内存回收机制, 但是不是所有被new出的对象被自动回收, 满足条件才可以回收 如果想要在Qt中实现内存的自动回收, 需要满足以下两个条件: 创建的对象必须是QObject类的子类(间接子类也可以)创建出的类对象, 必须要指定其父对象是谁,…

利用RLHF优化大模型:提升性能与应用能力

在数据科学不断发展的过程中&#xff0c;大模型在自然语言处理、图像识别、金融预测等各个领域的应用越来越广泛。然而&#xff0c;大模型的训练和优化也面临着越来越多的挑战&#xff0c;例如数据量过大、计算资源不足、超参数调整困难等。传统的机器学习算法往往难以处理这些…

(学习笔记-IP)IP基础知识

基本认识 IP在TCP/IP参考模型中处于第三层&#xff0c;也就是网络层。 网络层的主要作用是&#xff1a;实现主机与主机之间的通信&#xff0c;也叫点对点的通信。 网络层与数据链路层的关系&#xff1a; MAC的作用是实现直连的两个设备之间通信&#xff0c;而IP负责没有直连的…

dbeaver下载及安装

dbeaver下载及安装 dbeaver下载安装执行 【近期收到公司通知&#xff0c;需要卸载navicat&#xff0c;找其他免费开源数据库管理工具】 dbeaver下载 地址&#xff1a; https://dbeaver.io/download/迅雷下载会快很多 安装 一步一步安装就行了&#xff1a; 启动 执行

IDE /完整分析C4819编译错误的本质原因

文章目录 概述基本概念代码页标识符字符集和字符编码方案源字符集和执行字符集 编译器使用的字符集VS字符集配置 有何作用编译器 - 源字符集编译器 -执行字符集 Qt Creator下配置MSVC编译器参数动态库DLL字符集配置不同于可执行程序EXE总结 概述 本文将从根本原因上来分析和解…

安全是最珍贵的 ,不要让自己的自己的秘密成为“梨润”的来源!!!

近日&#xff0c;某高校毕业生在校期间窃取学校内网数据&#xff0c;收集全校学生个人隐私信息的新闻引发了人们对互联网生活中个人信息安全问题的再度关注。在大数据时代&#xff0c;算法分发带来了隐私侵犯&#xff0c;在享受消费生活等便捷权利的同时&#xff0c;似乎又有不…

顺序表(增删改查)

目录 1.线性表 2.顺序表 2.1静态顺序表 2.2动态顺序表 3.顺序表接口 4.顺序表实现 4.1初始化 4.2销毁 4.3打印 4.4尾插 4.5尾删 4.5.1尾删改进 4.6检查是否存满 4.7头插 4.8头删 4.9 1.线性表 线性表 &#xff08;inear ist)是n个具有相同特性的数据元素的有限序列。线…

【JavaEE】基于Servlet与MySQL实现一个简易网站

目录 前言 一、实现表白墙的前期准备工作 1、约定前后端交互的接口 1.1、接口一&#xff1a;页面获取当前所有的留言消息 1.2、接口二&#xff1a;提交新消息给服务器 二、前端和后端代码的实现 1、数据的永久化保存 2、小结 前言 之前小编在写前端页面的时候&#x…

大模型入坑指南 大厂vs初创公司

大模型竞争激烈&#xff0c;创业公司随时可能倒掉&#xff0c;造成项目烂尾&#xff0c;EB3.5已经跟国内其他模型拉开了差距… 人工智能是当前时代的重要热点之一&#xff0c;它正在改变着我们的生活和工作。在人工智能领域&#xff0c;有一种技术尤其引人注目&#xff0c;那就…

RocketMq 事务消息原理

Rocketmq 事务消息API使用 使用TransactionMQProducer类。 实现TransactionListener 接口覆盖其方法executeLocalTransaction和checkLocalTransaction 即可。 其中executeLocalTransaction 执行本地方法和checkLocalTransaction 事务状态回查。 玩法 简历一张本地事务表&…

Centos报错:[Errno 12] Cannot allocate memory

执行一个脚本刚开始正常&#xff0c;后面就报[Errno 12] Cannot allocate memory 如果内存不足&#xff0c;可能需要增加交换内存。或者可能根本没有启用交换。可以通过以下方式检查您的交换: sudo swapon -s如果它为空&#xff0c;则表示您没有启用任何交换。添加 1GB 交换…

构建自己的ChatGPT:从零开始构建个性化语言模型

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

FPGA XDMA 中断模式实现 PCIE3.0 QT上位机视频传输 提供工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案图像产生、发送、缓存XDMA简介XDMA中断模式图像读取、输出、显示QT上位机及其源码 5、vivado工程详解6、上板调试验证7、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI Express&#xff09;采…

【微服务系统设计】系统设计基础:速率限制器

什么是速率限制器&#xff1f; 速率限制是指防止操作的频率超过定义的限制。在大型系统中&#xff0c;速率限制通常用于保护底层服务和资源。速率限制一般在分布式系统中作为一种防御机制&#xff0c;使共享资源能够保持可用性。 速率限制通过限制在给定时间段内可以到达您的 A…

java学习路程之篇三、进阶知识、面向对象高级、接口新特性、代码块、内部类、Lambda表达式、窗体、组件、事件

文章目录 1、接口新特性2、代码块3、内部类4、Lambda表达式5、窗体、组件、事件 1、接口新特性 2、代码块 3、内部类 4、Lambda表达式 5、窗体、组件、事件