【NXP-MCXA153】SPI驱动移植
介绍
SPI总线由摩托罗拉公司开发,是一种全双工同步串行总线,由四个IO口组成:CS、SCLK、MISO、MOSI;通常用于CPU和外设之间进行通信,常见的SPI总线设备有:TFT LCD、QSPI FLASH、时钟模块、IMU等;NXP-MCXA153开发板上集成了两路SPI总线,本次实验将重点介绍RT-Thread系统中SPI BSP驱动的移植过程
移植流程
以SPI0为例
① 在board里边添加相应的外设:配置spi0外设为复位状态、设置GPIO引脚功能
② 添加相应的Kconfig开关,用以指示相应的外设开启与关闭(本质是通过宏定义或者条件编译的方式)
③ 根据SDK_2_14_2_FRDM-MCXA153提供的spi示例工程编写spi总线驱动,需要实现几个关键的函数
- rt_hw_spi_init
- spi_configure
- spixfer
④ 添加相应的库文件依赖:fsl_lpspi.c、fsl_lpspi_edma.c
引脚对应关系
| 序号 | GPIO | function |
|---|---|---|
| 1 | P1_3 | CS |
| 2 | P1_1 | SCLK |
| 3 | P1_2 | MISO |
| 4 | P1_0 | MOSI |
驱动文件
board.c
在rt_hw_board_init函数里加入以下代码
edma_config_t userConfig = {0};
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DMA0, &userConfig);
pin_mux.c
在BOARD_InitPins函数里加入以下代码
#ifdef BSP_USING_SPI0RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn);const port_pin_config_t port1_0_pin56_config = {/* Internal pull-up/down resistor is disabled */kPORT_PullDisable,/* Low internal pull resistor value is selected. */kPORT_LowPullResistor,/* Fast slew rate is configured */kPORT_FastSlewRate,/* Passive input filter is disabled */kPORT_PassiveFilterDisable,/* Open drain output is disabled */kPORT_OpenDrainDisable,/* Low drive strength is configured */kPORT_LowDriveStrength,/* Normal drive strength is configured */kPORT_NormalDriveStrength,/* Pin is configured as LPSPI0_SDO */kPORT_MuxAlt2,/* Digital input enabled */kPORT_InputBufferEnable,/* Digital input is not inverted */kPORT_InputNormal,/* Pin Control Register fields [15:0] are not locked */kPORT_UnlockRegister};/* PORT1_0 (pin 56) is configured as LPSPI0_SDO */PORT_SetPinConfig(PORT1, 0U, &port1_0_pin56_config);const port_pin_config_t port1_1_pin57_config = {/* Internal pull-up/down resistor is disabled */kPORT_PullDisable,/* Low internal pull resistor value is selected. */kPORT_LowPullResistor,/* Fast slew rate is configured */kPORT_FastSlewRate,/* Passive input filter is disabled */kPORT_PassiveFilterDisable,/* Open drain output is disabled */kPORT_OpenDrainDisable,/* Low drive strength is configured */kPORT_LowDriveStrength,/* Normal drive strength is configured */kPORT_NormalDriveStrength,/* Pin is configured as LPSPI0_SCK */kPORT_MuxAlt2,/* Digital input enabled */kPORT_InputBufferEnable,/* Digital input is not inverted */kPORT_InputNormal,/* Pin Control Register fields [15:0] are not locked */kPORT_UnlockRegister};/* PORT1_1 (pin 57) is configured as LPSPI0_SCK */PORT_SetPinConfig(PORT1, 1U, &port1_1_pin57_config);const port_pin_config_t port1_2_pin58_config = {/* Internal pull-up/down resistor is disabled */kPORT_PullDisable,/* Low internal pull resistor value is selected. */kPORT_LowPullResistor,/* Fast slew rate is configured */kPORT_FastSlewRate,/* Passive input filter is disabled */kPORT_PassiveFilterDisable,/* Open drain output is disabled */kPORT_OpenDrainDisable,/* Low drive strength is configured */kPORT_LowDriveStrength,/* Normal drive strength is configured */kPORT_NormalDriveStrength,/* Pin is configured as LPSPI0_SDI */kPORT_MuxAlt2,/* Digital input enabled */kPORT_InputBufferEnable,/* Digital input is not inverted */kPORT_InputNormal,/* Pin Control Register fields [15:0] are not locked */kPORT_UnlockRegister};/* PORT1_2 (pin 58) is configured as LPSPI0_SDI */PORT_SetPinConfig(PORT1, 2U, &port1_2_pin58_config);const port_pin_config_t port1_3_pin59_config = {/* Internal pull-up/down resistor is disabled */kPORT_PullDisable,/* Low internal pull resistor value is selected. */kPORT_LowPullResistor,/* Fast slew rate is configured */kPORT_FastSlewRate,/* Passive input filter is disabled */kPORT_PassiveFilterDisable,/* Open drain output is disabled */kPORT_OpenDrainDisable,/* Low drive strength is configured */kPORT_LowDriveStrength,/* Normal drive strength is configured */kPORT_NormalDriveStrength,/* Pin is configured as LPSPI0_PCS0 */kPORT_MuxAlt2,/* Digital input enabled */kPORT_InputBufferEnable,/* Digital input is not inverted */kPORT_InputNormal,/* Pin Control Register fields [15:0] are not locked */kPORT_UnlockRegister};/* PORT1_3 (pin 59) is configured as LPSPI0_PCS0 */PORT_SetPinConfig(PORT1, 3U, &port1_3_pin59_config);
#endif
board/Kconfig
加入SPI0相关配置
menuconfig BSP_USING_SPIconfig BSP_USING_SPIbool "Enable SPI"select RT_USING_SPIdefault yif BSP_USING_SPIconfig BSP_USING_SPI0bool "Enable SPI0"default endif
drv_spi.c
spi驱动层修改如下
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-08-3 hywing The first version for MCXA*/
#include "rtdevice.h"
#include "drv_spi.h"
#include "fsl_common.h"
#include "fsl_lpspi.h"
#include "fsl_lpspi_edma.h"#define DMA_MAX_TRANSFER_COUNT (32767)enum
{
#ifdef BSP_USING_SPI0SPI1_INDEX,
#endif
};struct lpc_spi
{struct rt_spi_bus parent;LPSPI_Type *LPSPIx;clock_attach_id_t clock_attach_id;clock_div_name_t clock_div_name;clock_name_t clock_name;DMA_Type *DMAx;uint8_t tx_dma_chl;uint8_t rx_dma_chl;edma_handle_t dma_tx_handle;edma_handle_t dma_rx_handle;dma_request_source_t tx_dma_request;dma_request_source_t rx_dma_request;lpspi_master_edma_handle_t spi_dma_handle;rt_sem_t sem;char *name;
};static struct lpc_spi lpc_obj[] =
{
#ifdef BSP_USING_SPI0{.LPSPIx = LPSPI0,.clock_attach_id = kFRO12M_to_LPSPI0,.clock_div_name = kCLOCK_DivLPSPI0,.clock_name = kCLOCK_Fro12M,.tx_dma_request = kDma0RequestLPSPI0Tx,.rx_dma_request = kDma0RequestLPSPI0Rx,.DMAx = DMA0,.tx_dma_chl = 0,.rx_dma_chl = 1,.name = "spi0",},
#endif
};struct lpc_sw_spi_cs
{rt_uint32_t pin;
};rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
{rt_err_t ret = RT_EOK;struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));struct lpc_sw_spi_cs *cs_pin = (struct lpc_sw_spi_cs *)rt_malloc(sizeof(struct lpc_sw_spi_cs));cs_pin->pin = pin;rt_pin_mode(pin, PIN_MODE_OUTPUT);rt_pin_write(pin, PIN_HIGH);ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);return ret;
}static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
{rt_err_t ret = RT_EOK;
// struct lpc_spi *spi = RT_NULL;
// spi = (struct lpc_spi *)(device->bus->parent.user_data);
// ret = lpc_spi_init(spi->SPIx, cfg);return ret;
}static void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData)
{struct lpc_spi *spi = (struct lpc_spi *)userData;rt_sem_release(spi->sem);}static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{int i;lpspi_transfer_t transfer = {0};RT_ASSERT(device != RT_NULL);RT_ASSERT(device->bus != RT_NULL);RT_ASSERT(device->bus->parent.user_data != RT_NULL);struct lpc_spi *spi = (struct lpc_spi *)(device->bus->parent.user_data);struct lpc_sw_spi_cs *cs = device->parent.user_data;if (message->cs_take){rt_pin_write(cs->pin, PIN_LOW);}transfer.dataSize = message->length;transfer.rxData = (uint8_t *)(message->recv_buf);transfer.txData = (uint8_t *)(message->send_buf);// if(message->length < MAX_DMA_TRANSFER_SIZE)if (0){LPSPI_MasterTransferBlocking(spi->LPSPIx, &transfer);}else{uint32_t block, remain;block = message->length / DMA_MAX_TRANSFER_COUNT;remain = message->length % DMA_MAX_TRANSFER_COUNT;for (i = 0; i < block; i++){transfer.dataSize = DMA_MAX_TRANSFER_COUNT;if (message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i * DMA_MAX_TRANSFER_COUNT);if (message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i * DMA_MAX_TRANSFER_COUNT);LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer);rt_sem_take(spi->sem, RT_WAITING_FOREVER);}if (remain){transfer.dataSize = remain;if (message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i * DMA_MAX_TRANSFER_COUNT);if (message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i * DMA_MAX_TRANSFER_COUNT);LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer);rt_sem_take(spi->sem, RT_WAITING_FOREVER);}}if (message->cs_release){rt_pin_write(cs->pin, PIN_HIGH);}return message->length;
}static struct rt_spi_ops lpc_spi_ops =
{.configure = spi_configure,.xfer = spixfer
};int rt_hw_spi_init(void)
{int i;for (i = 0; i < ARRAY_SIZE(lpc_obj); i++){CLOCK_SetClockDiv(lpc_obj[i].clock_div_name, 1u);CLOCK_AttachClk(lpc_obj[i].clock_attach_id);lpc_obj[i].parent.parent.user_data = &lpc_obj[i];lpc_obj[i].sem = rt_sem_create("sem_spi", 0, RT_IPC_FLAG_FIFO);lpspi_master_config_t masterConfig;LPSPI_MasterGetDefaultConfig(&masterConfig);masterConfig.baudRate = 12 * 1000 * 1000;masterConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;masterConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;masterConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;LPSPI_MasterInit(lpc_obj[i].LPSPIx, &masterConfig, CLOCK_GetFreq(lpc_obj[i].clock_name));EDMA_CreateHandle(&lpc_obj[i].dma_tx_handle, lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl);EDMA_CreateHandle(&lpc_obj[i].dma_rx_handle, lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl);EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl, lpc_obj[i].tx_dma_request);EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl, lpc_obj[i].rx_dma_request);LPSPI_MasterTransferCreateHandleEDMA(lpc_obj[i].LPSPIx, &lpc_obj[i].spi_dma_handle, LPSPI_MasterUserCallback, &lpc_obj[i], &lpc_obj[i].dma_rx_handle, &lpc_obj[i].dma_tx_handle);rt_spi_bus_register(&lpc_obj[i].parent, lpc_obj[i].name, &lpc_spi_ops);}return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_spi_init);
SConscript
在Libraries/MCXA153/SConscript文件里边加上以下代码
if GetDepend('BSP_USING_SPI'):src += ['MCXA153/drivers/fsl_lpspi.c']src += ['MCXA153/drivers/fsl_lpspi_edma.c']
测试用例
打开menuconfig使能spi0驱动

短接MISO和MOSI引脚(P1_0和P1_2)进行自发自收测试

测试程序
#include <rtthread.h>
#include "rtdevice.h"
#include "drv_spi.h"#define SPI_BUS_NAME "spi0"
#define SPI_DEV_NAME "spi00" static struct rt_spi_device *spi_device;static void spi_sample(void)
{ rt_err_t result; struct rt_spi_configuration cfg; uint8_t tx_buf[] = "Hello RT-Thread!"; uint8_t rx_buf[sizeof(tx_buf)]; rt_base_t cs = 1*32+3; rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEV_NAME, cs);/* »ñÈ¡SPIÉ豸 */spi_device = (struct rt_spi_device *)rt_device_find(SPI_DEV_NAME);if (!spi_device){rt_kprintf("can't find %s device!\n", SPI_BUS_NAME);}/* ÅäÖÃSPIÉ豸 */cfg.data_width = 8;cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;cfg.max_hz = 12* 1000 * 1000;/* ÉèÖÃSPIÉ豸 */rt_spi_configure(spi_device, &cfg); result = rt_spi_transfer(spi_device, tx_buf, rx_buf, sizeof(tx_buf)); if (result == sizeof(tx_buf)) { rt_kprintf("Send: %s\n", tx_buf); rt_kprintf("Received: %s\n", rx_buf); } else { rt_kprintf("spi transfer failed! error code: %d\n", result); }
} int main(void)
{ spi_sample(); return 0;
}
运行结果

总结
- 另外,你也可以安装
MCUXpresso Config Tools v16,通过图形方式配置时钟树、GPIO复用 - 完整的BSP驱动代码可以在RT-Thread的仓库找到
相关文章:
【NXP-MCXA153】SPI驱动移植
介绍 SPI总线由摩托罗拉公司开发,是一种全双工同步串行总线,由四个IO口组成:CS、SCLK、MISO、MOSI;通常用于CPU和外设之间进行通信,常见的SPI总线设备有:TFT LCD、QSPI FLASH、时钟模块、IMU等;…...
Python if 编程题|Python一对一辅导教学
你好,我是悦创。 以下为 if 编程练习题: 1. 奇数乘积问题 题目描述: 编写一个程序,判断给定的两个整数是否都是奇数,如果是,返回它们的乘积;如果不是,返回它们的和。输入: num1, num2输出: n…...
机器学习——第十一章 特征选择与稀疏学习
11.1 子集搜索与评价 对一个学习任务来说,给定属性集,其中有些属性可能很关键、很有用,另一些属性则可能没什么用.我们将属性称为"特征" (feature) ,对当前学习任务有用的属性称为"相关特征" (relevant featu…...
花式表演无人机技术详解
花式表演无人机作为现代科技与艺术融合的典范,以其独特的飞行姿态、绚烂的灯光效果及精准的控制能力,在各类庆典、体育赛事、音乐会等合中展现出非凡的魅力。本文将从以下几个方面对花式表演无人机技术进行详细解析。 1. 三维建模与编程 在花式表演无人…...
服务器那点事--防火墙
Linux服务器那点事--防火墙 Ⅰ、开启关闭Ⅱ、放开端口 Ⅰ、开启关闭 禁止防火墙开机自启systemctl disable firewalld 关闭防火墙systemctl stop firewalld 查看防火墙状态systemctl status firewalldⅡ、放开端口 例如:放开3306端口 设置放开3306端口 [rootbpm2…...
C:每日一题:单身狗
一、题目: 在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。 整型数组 int arr[ ] {1,1,2,2,3,4,4} 二、思路分析: 1.,明确目标,选择…...
SQL之使用存储过程循环插入数据
1、已经创建了任务日志表 CREATE TABLE t_task_log (id bigint NOT NULL AUTO_INCREMENT,task_id bigint NOT NULL COMMENT 任务ID,read_time bigint NOT NULL COMMENT 单位秒,读取耗时,write_time bigint NOT NULL COMMENT 单位秒,写入耗时,read_size …...
智慧楼宇公厕系统小程序,提高卫生间管理使用效率
在当今的智慧楼宇中,公厕系统的管理和使用效率成为了衡量楼宇品质的重要指标之一。智慧楼宇公厕系统小程序的出现,为解决这一问题带来了全新的思路和方法。 一、检查公厕环境数据 智慧公厕系统不仅关注如厕的基本需求,还注重提升如厕环境的质…...
深度剖析:云数据库与传统数据库的显著差异
【若您对以下内容感兴趣,欢迎关注或联系我们】 在当今数字化时代,数据库技术不断演进,云数据库和传统数据库作为两种主要的数据库类型,在多个方面存在明显区别。下面我们将深入探讨这些差异。 一、部署方式 云数据库࿱…...
# 利刃出鞘_Tomcat 核心原理解析(六)
利刃出鞘_Tomcat 核心原理解析(六) 一、Tomcat专题 - 内容 1、Web 应用配置 2、Tomcat 管理配置 3、JVM 配置 4、Tomcat 集群 5、Tomcat 安全 6、Tomcat 性能调优 7、Tomcat 附加功能。 二、Tomcat专题 - Web应用配置介绍 1、Web.xml 配置文件…...
双亲委派模型
优质博文:IT-BLOG-CN 虚拟机设计团队把类加载阶段中的 “通过一个类的全限定名来获取描述此类的二进制字节流” 这个动作放到 Java虚拟机外部去实现,以便应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。 从Java虚拟机…...
Linux下ETCD安装、配置、命令
目录 1. ETCD简介 2. ETCD的安装 2.1 准备环境 2.2 下载ETCD 2.3 解压和移动文件 2.4 验证安装 3. ETCD的配置 3.1 基本配置 3.2 配置文件 3.3 集群配置 4. ETCD的常用命令 4.1 插入键值对 4.2 读取键值对 4.3 删除键值对 4.4 监视键的变化 4.5 列出所有键值 …...
【QT】静态库与动态库
文章目录 开始之前一、静态库(static Library)定义使用场景特点程序示例 二、动态库(dynamic Library)定义使用场景特点。程序示例第二种调用 开始之前 测试环境:Qt 5.15.2 Based on Qt 6.4.3(MSVC 2019, x86_64) 操作系统:Windows11 专业版 编程语言&am…...
R的行和列命名和类型的转换
下面内容摘录自: 4章8节:用R做数据重塑,行列命名和数据类型转换-CSDN博客 欢迎订阅我们专栏 一、行和列命名 在数据科学和统计分析中,命名是组织和管理数据的一个重要部分。尤其是在处理复杂的多维数据集时,为行和列命…...
某通用系统0day审计过程
前言 代码审计篇章都是自己跟几个师傅们一起审计的1day或者0day(当然都是小公司较为简单),禁止未经允许进行转载,发布到博客的用意主要是想跟师傅们能够交流下审计的思路,毕竟审计的思路也是有说法的,或者是相互源码共享也OK&…...
windows C++-高级并发和异步(一)
并发和异步的由来已经很久了,对于从xp开始编程的人来说,这个概念并不陌生,但问题在于,在早期,这两个技术被认为是操作系统提供的服务,而非编程语言的概念。 事情发生变化的原因,和C标准不断变迁…...
Java FX 学习
声明:参考视频 一. Stage与Scene 舞台与场景:JavaFX应用程序将Ul容器定义为舞台(Stage)与场景(Scene)Stage类是顶级容器,它对应于窗体,其内容由Scene决定。Scene类是所有可视化内容…...
【走迷宫】
题目 DFS代码 #include<bits/stdc.h> using namespace std; const int N 110; int matrix[N][N]; int n, m; int dx[4] {-1, 0, 1, 0}, dy[4] {0, 1, 0, -1}; int dis[N][N]; void dfs(int x, int y, int cnt) {if(cnt > dis[n-1][m-1]) return;if(x n-1 &&a…...
linux(debian)迁移var数据到已分配逻辑卷的物理盘
文章目录 0 背景1 查看当前情况1.1 查看磁盘空间1.2 列出所有可用块设备的信息,而且还能显示他们之间的依赖关系1.3 查看可用磁盘1.4 查看卷组 2 卷组中创建逻辑卷3 创建文件系统4 创建临时文件夹并挂载,然后备份源文件5 修改开机挂载配置5.1 查看原配置…...
【产品那些事】什么是应用程序安全态势管理(ASPM)?
文章目录 前言当前应用安全(AppSec)推进遇到的问题关于ASPM的定义 为什么需要ASPM:B端客户核心需求ASPM产品关键策略理想状态下的ASPMASPM与CSPM的区别国内外产品参考 前言 随着现代软件开发实践的快速演变,特别是在敏捷开发和 DevOps 的推动下…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
