当前位置: 首页 > article >正文

STM32高级 以太网通讯案例1:网络搭建(register代码)

需求描述

驱动W5500芯片,设置好IP,测试网络是否连通。

思考:

驱动W5500芯片是通过spi协议,所以和spi相关的有四个引脚,MOSI(主出从入)MISO(主入从出)SCK(时钟线)CS(片选线)。RST(复位引脚,对于32来说是输出)INT(中断引脚对于32来说是输入)。

 W5500-RST:重置硬件,重置(Reset)低电平有效;该引脚需要保持低电平至少500us,才能重置W5500;(正常使用应该高电平,需要重置芯片的时候置为低电平不少500us)。连接的是PG7。

W5500-INT:中断输出(Interrupt output),低电平有效。低电平,W5500的中断生效;高电平,无中断。连接的是PG6。

W5500-CS片选引脚。连接的是PD3

W5500与STM32使用SPI协议进行通讯,连接的是STM32的SPI2外设。 

第一步:导入文件(官方库、SPI、自己驱动的主文件)

W5500有官方库:导入以太网文件夹下的W5500、socket.c、socket.h、wizchip_conf.c、wizchip_conf.h文件,        放入Interface下的Ethernet文件下。

SPI:spi.c和spi.h(之前的spi文件)        文件放入Handware(驱动层)下。

自己驱动的主文件:新建eth.c和eth.h        放入Interface下的Ethernet文件下。

第二步:配置spi.h文件

宏定义的高低引脚要换成PD3

第三步:配置wizchip_conf.h文件

75行----改变当前使用芯片信号

153行---选择VDM,选择可变长度模式

61行---引入spi.h

第四步:配置wizchip_conf.c文件

里面许多函数的空实现

名词:

        Cris:Critical region临界区-指的是共享的资源

        enter:进入

        exit:退出

        select:选择

83行:片选使能        CS_LOW

91行:取消片选        CS_HIGH

最后一行自定义函数,注册spi操作的回调函数,记得.h引入原型

void user_register_function(void)
{
   reg_wizchip_cris_cbfunc(wizchip_cris_enter,wizchip_cris_exit);

   reg_wizchip_cs_cbfunc(wizchip_cs_select,wizchip_cs_deselect);

   reg_wizchip_spi_cbfunc(wizchip_spi_readbyte,wizchip_spi_writebyte);
}

第五步:配置spi.c文件

按照上面思考的图片修改初始化函数中的各种引脚。

第六步:书写eth.h和eth.c文件

eth.h

#ifndef __ETH_H__
#define __ETH_H__

#include "w5500.h"

//初始化
void ETH_Init(void);

#endif /* __ETH_H__ */

eth.c

#include "eth.h"
#include "delay.h"

// 定义W5500的IP地址、MAC地址、子网掩码和网关地址
uint8_t ip[4] = {192,168,44,250};
uint8_t mac[6] = {78,11,22,33,44,55};
uint8_t submask[4] = {255,255,255,0};
uint8_t gateway[4] = {192,168,44,1};

// 复位W5500
static void ETH_Reset(void);
// 设置 MAC 地址
static void ETH_SetMac(void);
// 设置 IP 地址(包括网关和子网掩码)
static void ETH_SetIP(void);

// 初始化
void ETH_Init(void)
{
    // 0. SPI 初始化
    SPI_Init();

    // 1. 注册自定义回调函数
    user_register_function();

    // 2. 复位W5500
    ETH_Reset();

    // 3. 设置 MAC 地址
    ETH_SetMac();

    // 4. 设置 IP 地址(包括网关和子网掩码)
    ETH_SetIP();
}

// 复位W5500
static void ETH_Reset(void)
{
    // 1. 配置RST引脚-PG7
    // 1.1 开启时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPGEN;

    // 1.2 设置工作模式:通用推挽输出,MODE - 11,CNF - 00
    GPIOG->CRL |= GPIO_CRL_MODE7;
    GPIOG->CRL &= ~GPIO_CRL_CNF7;

    // 2. 拉低RST,保持500us以上
    GPIOG->ODR &= ~GPIO_ODR_ODR7;

    Delay_us(800);

    GPIOG->ODR |= GPIO_ODR_ODR7;

    printf("W5500 复位完成!\n");
}

// 设置 MAC 地址
static void ETH_SetMac(void)
{
    printf("开始设置 MAC 地址:\n");
    setSHAR(mac);
    printf("MAC 地址设置完成: %X-%X-%X-%X-%X-%X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

// 设置 IP 地址(包括网关和子网掩码)
static void ETH_SetIP(void)
{
    printf("开始设置 IP 地址:\n");

    // 设置IP
    setSIPR(ip);
    // 设置子网掩码
    setSUBR(submask);
    // 设置网关地址
    setGAR(gateway);

    printf("IP 地址设置完成: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
}

spi.h

#ifndef __SPI_H__
#define __SPI_H__

#include "stm32f10x.h"

#define CS_HIGH (GPIOD->ODR |= GPIO_ODR_ODR3)
#define CS_LOW (GPIOD->ODR &= ~ GPIO_ODR_ODR3)

void SPI_Init(void);

void SPI_Start(void);

void SPI_Stop(void);

uint8_t SPI_SwapByte(uint8_t byte);

#endif /* __SPI_H__ */

spi.c

#include "spi.h"

void SPI_Init(void){
    // 1. GPIOB
    // 1.1 先放时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    // 1.2 PA5 时钟 复用推挽
    GPIOB->CRH &= ~GPIO_CRH_CNF13;
    GPIOB->CRH |= GPIO_CRH_CNF13_1;
    GPIOB->CRH |= GPIO_CRH_MODE13;
    // 1.3 PA6 输入信号 浮空输入
    GPIOB->CRH &= ~GPIO_CRH_CNF14_1;
    GPIOB->CRH |= GPIO_CRH_CNF14_0;
    GPIOB->CRH &= ~GPIO_CRH_MODE14;
    // 1.4 PA7 数据输出 复用推挽
    GPIOB->CRH &= ~GPIO_CRH_CNF15_0;
    GPIOB->CRH |= GPIO_CRH_CNF15_1;
    GPIOB->CRH |= GPIO_CRH_MODE15;

    // 2. GPIOC
    // 2.1 放GPIOD的时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPDEN;
    CS_HIGH;
    // 2.2. PC13 片选使能信号 通用推挽
    GPIOD->CRL &= ~GPIO_CRL_CNF3;
    GPIOD->CRL |= GPIO_CRL_MODE3;


    //配置硬件SPI
    //0.1放时钟
    RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
    //0.2 设置DFF位来定义8位或者16位数据格式 当前8位
    SPI2->CR1 &= ~SPI_CR1_DFF;
    //0.3 设置高位优先
    SPI2->CR1 &= ~SPI_CR1_LSBFIRST;
    //0.4 工作模式为主模式
    SPI2->CR1 |= SPI_CR1_MSTR;
    //0.5 波特率的配置 APB2 72M 如果是 000 就是2分频 36M
    SPI2->CR1 &= ~SPI_CR1_BR;
    //0.6 mode0 模式
    SPI2->CR1 &= ~SPI_CR1_CPOL;
    SPI2->CR1 &= ~SPI_CR1_CPHA;
    //0.7 SSOE 配0 这样的话 会关闭SS引脚的输出 同时 会被迫进入
    //多主模式(NSS 会变成一个输入引脚)
    SPI2->CR2 &= ~SPI_CR2_SSOE;
    //0.8 NSS 进入软件模式
    //          SSM 配1 那就是NSS信号 由SSI位来决定
    SPI2->CR1 |= SPI_CR1_SSM;
    //          SSI 配1 再多主模式里 一直处于可通讯状态
    SPI2->CR1 |= SPI_CR1_SSI; 
    // 使能位
    SPI2->CR1 |= SPI_CR1_SPE;
}

void SPI_Start(void){
    CS_LOW; 
}

void SPI_Stop(void){
    CS_HIGH;
}

uint8_t SPI_SwapByte(uint8_t byte){
    while (!(SPI2->SR & SPI_SR_TXE))
    {
    }
    SPI2->DR = byte;
    while (!(SPI2->SR & SPI_SR_RXNE))
    {
    }
    uint8_t receive_byte = SPI2->DR;
    return receive_byte;
}

main.c

#include "usart1.h"
#include "eth.h"

int main(void)
{
	// 1. 初始化
	Usart1_Init();

	printf("尚硅谷以太网实验:测试网络搭建\n");

	ETH_Init();

	printf("\n以太网初始化完成!\n");

	while (1)
	{
	}
}


http://www.kler.cn/a/458430.html

相关文章:

  • Spring Boot介绍、入门案例、环境准备、POM文件解读
  • 【Spark】架构与核心组件:大数据时代的必备技能(下)
  • SpringBoot使用TraceId日志链路追踪
  • ts总结一下
  • JVM对象内存分配
  • [算法] [leetcode-70] 爬楼梯
  • leetcode 面试经典 150 题:删除有序数组中的重复项
  • 基于SSM的“一汽租车辆共享平台”的设计与实现(源码+数据库+文档+PPT)
  • vue-复制剪贴板
  • pytorch整体环境打包安装到另一台电脑上
  • 高级技巧-使用Mysql 实现根据条件过滤整个分组数据
  • 正则化强度的倒数C——让模型学习更准确
  • Bash 脚本教程
  • 【Python】什么是元组(Tuple)?
  • TCP/IP原理
  • OpenCV-Python实战(4)——图像处理基础知识
  • 数据资产运营平台如何搭建?数据要素资产运营平台解决方案 解读
  • C++软件设计模式之代理(Proxy)模式
  • pikachu靶场搭建详细步骤
  • 爬虫入门一 基础知识 以及request
  • 【HF设计模式】04-工厂模式
  • 【论文笔记】Top-nσ: Not All Logits Are You Need
  • 游戏引擎学习第65天
  • “校园疫情防控的技术支持”:疫情管控系统的实现与评估
  • WPF系列四:图形控件Rectangle
  • 【代码分析】Unet-Pytorch