第05章 网关项目
约 1481 字大约 5 分钟
2026-01-17
5.1 公共层
同定位器项目
5.2 LoRa 模块
5.2.1 原理图


5.2.2 CubeMX 配置


5.2.3 代码
同定位器中的 Lora 模块代码
main.c (演示)
int main(void)
{
/* 代码省略 */
/* USER CODE BEGIN 2 */
DEBUG_PRINTLN("定位器网关项目...");
// 初始化LLCC68
Int_LLCC68_Init();
DEBUG_PRINTLN("准备接收Lora数据...");
// 定义Lora接收缓冲区
uint8_t lora_rx_buf[256];
// 定义变量,保存接收到数据长度
uint16_t lora_rx_len = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 如果LLCC68接收到数据
Int_LLCC68_Receive(lora_rx_buf, &lora_rx_len);
if (lora_rx_len > 0)
{
// 打印机接收到的数据
DEBUG_PRINTLN("接收到数据:%s", lora_rx_buf);
DEBUG_PRINTLN("数据长度:%d \n\n", lora_rx_len);
}
}
/* USER CODE END 3 */
}5.3 以太网模块
5.3.1 原理图


5.3.2 CubeMX 配置
SPI 设置

GPIO 设置:

5.3.3 W5500 概述
W5500 是一款由韩国wiznet发布的全硬件嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。W5500 集成了 TCP/IP 协议栈,10/100M 以太网数据链路层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。
① 结构和特点

② 特点:

③ 引用场景:

③ 相关引脚

④ SPI 接口



⑤ 通用寄存器

⑥ socket 寄存器
状态寄存器中的部分标志位:

5.3.4 移植 W5500 官方驱动
① 移植官方库文件
官方库地址:https://github.com/Wiznet/ioLibrary_Driver/tree/master

官方驱动库结构:

Interface 中创建 Eth 目录,然后复制我们需要的文件:

② 修改 wizchip_conf.h
找到宏定义 _WIZCHIP_,如果不是W5500,就改成W5500:(默认值就是)

修改工作模式为可变数据长度模式:(默认值就是)

③ 修改 wizchip_conf.c
将以下四个函数补充完整:
// 片选使能
void wizchip_cs_select(void)
{
// 片选引脚拉低
HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_RESET);
}
// 取消片选使能
void wizchip_cs_deselect(void)
{
// 片选引脚拉高
HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_SET);
}
// 通过SPI读1个字节
uint8_t wizchip_spi_readbyte(void)
{
uint8_t rx_byte;
HAL_SPI_Receive(&hspi2, &rx_byte, 1, 1000);
return rx_byte;
}
// 通过 SPI 写入1个字节
void wizchip_spi_writebyte(uint8_t wb)
{
HAL_SPI_Transmit(&hspi2, &wb, 1, 1000);
}添加一个封装注册功能的函数,并在 wizchip_conf.h 中添加原型:
// 函数实现:注册函数
void development_reg_func(void)
{
// 1. 注册进入和退出临界区的函数
reg_wizchip_cris_cbfunc(wizchip_cris_enter, wizchip_cris_exit);
// 2. 注册片选和取消片选的函数
reg_wizchip_cs_cbfunc(wizchip_cs_select, wizchip_cs_deselect);
// 3. 注册SPI读写数据的函数
reg_wizchip_spi_cbfunc(wizchip_spi_readbyte, wizchip_spi_writebyte);
}5.3.4 自定义代码
Int_W5500.h
#ifndef __INT_W5500_H__
#define __INT_W5500_H__
#include "wizchip_conf.h"
#include "socket.h"
#include "gpio.h"
#include "Com_Debug.h"
/**
* @brief Initialize W5500.
*
*/
void Int_W5500_Init(void);
/**
* @brief 上传数据至服务器
*
* @param tx_data 待上传数据指针
* @param tx_len 待上传数据长度
*/
void Int_W5500_Upload(uint8_t *tx_data, uint16_t tx_len);
#endif /* __INT_W5500_H__ */Int_W5500.c
#include "Int_W5500.h"
// 定义IP地址
uint8_t local_ip[4] = {192, 168, 12, 200};
// 定义子网掩码
uint8_t subnet_mask[4] = {255, 255, 255, 0};
// 定义网关IP地址
uint8_t gateway_ip[4] = {192, 168, 12, 1};
// 定义MAC地址
uint8_t mac_addr[6] = {0xA0, 0x11, 0x22, 0x33, 0x44, 0x55};
// 定义服务器IP地址
uint8_t server_ip[4] = {192, 168, 12, 82};
// 定义服务器端口号
uint16_t server_port = 8848;
/**
* @brief Initialize W5500.
*
*/
void Int_W5500_Init(void)
{
// 1. 复位W5500
// 先拉低RST引脚,低电平至少支持500us,这里100ms
HAL_GPIO_WritePin(W5500_RST_GPIO_Port, W5500_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
// 拉高RST引脚,并延时等待稳定
HAL_GPIO_WritePin(W5500_RST_GPIO_Port, W5500_RST_Pin, GPIO_PIN_SET);
HAL_Delay(100);
// 2. 注册函数
devlopment_reg_func();
// 3. 给W5500设置IP地址、子网掩码、网关IP地址、MAC地址
setSIPR(local_ip);
setSUBR(subnet_mask);
setGAR(gateway_ip);
setSHAR(mac_addr);
}
/**
* @brief 上传数据至服务器
*
* @param tx_data 待上传数据指针
* @param tx_len 待上传数据长度
*/
void Int_W5500_Upload(uint8_t *tx_data, uint16_t tx_len)
{
// 定义socket id
uint8_t socket_id = 0;
// 定义变量,保存socket状态
uint8_t socket_status = 0;
// 等到连接成功,SOCK得到ESTABLISHED状态
do
{
// 获取SOCKET状态
socket_status = getSn_SR(socket_id);
// 如果连接是Closed状态,打开Socket
if (socket_status == SOCK_CLOSED)
{
if (socket(socket_id, Sn_MR_TCP, 2501, 0) == socket_id)
{
DEBUG_PRINTLN("Socket Client Create Success!");
}
else
{
DEBUG_PRINTLN("Socket Client Create Failed!");
continue;;
}
}
// 如果是 SOCK_INIT 状态,进行连接
if (socket_status == SOCK_INIT)
{
if (connect(socket_id, server_ip, server_port) == SOCK_OK)
{
DEBUG_PRINTLN("Socket Client Connect Success!");
}
else
{
DEBUG_PRINTLN("Socket Client Connect Failed!");
continue;;
}
}
// 如果是 SOCK_CLOSE_WAIT 状态,关闭连接
if (socket_status == SOCK_CLOSE_WAIT)
{
close(socket_id);
DEBUG_PRINTLN("Socket Client Close Success!");
}
} while (socket_status != SOCK_ESTABLISHED);
// 发送数据
if (send(socket_id, tx_data, tx_len) == tx_len)
{
DEBUG_PRINTLN("Socket Client Send Success!");
}
else
{
DEBUG_PRINTLN("Socket Client Send Failed!");
}
}5.3.5 TCP 三次握手


5.3 应用层
main.c
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* 代码省略 ....*/
/* USER CODE BEGIN 2 */
DEBUG_PRINTLN("定位器网关项目...");
// 初始化W5500
Int_W5500_Init();
DEBUG_PRINTLN("W5500初始化完成...");
// 初始化LLCC68
Int_LLCC68_Init();
DEBUG_PRINTLN("LLCC68初始化完成,准备接收Lora数据...");
// 定义Lora接收缓冲区
uint8_t lora_rx_buf[256];
// 定义变量,保存接收到数据长度
uint16_t lora_rx_len = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 如果LLCC68接收到数据
Int_LLCC68_Receive(lora_rx_buf, &lora_rx_len);
if (lora_rx_len > 0)
{
// 打印机接收到的数据
DEBUG_PRINTLN("接收到数据:%s", lora_rx_buf);
DEBUG_PRINTLN("数据长度:%d \n\n", lora_rx_len);
// 上传数据至服务器
Int_W5500_Upload(lora_rx_buf, lora_rx_len);
DEBUG_PRINTLN("数据上传完成...");
}
}
/* USER CODE END 3 */
}