【NXP-MCXA153】SPI驱动移植

news2024/9/22 7:31:13

介绍

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

引脚对应关系

序号GPIOfunction
1P1_3CS
2P1_1SCLK
3P1_2MISO
4P1_0MOSI

驱动文件

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_SPI0
	RESET_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_SPI
    config BSP_USING_SPI
        bool "Enable SPI"
        select RT_USING_SPI
        default y

    if BSP_USING_SPI
        config BSP_USING_SPI0
            bool "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_SPI0
    SPI1_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的仓库找到

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

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

相关文章

假如萝卜快跑撞了人,谁来负责?

引言 自动驾驶时代来临&#xff0c;司机的身影消失。但没有了司机&#xff0c;交通事故谁来负责&#xff1f;在AI刚爆火时&#xff0c;有个半调侃的笑话很出名&#xff1a;AI肯定不能替代会计和律师&#xff0c;因为一旦出了事&#xff0c;AI负不了责&#xff0c;但会计和律师…

Nest.js 实战 (九):使用拦截器记录用户 CURD 操作日志

前言 有一天&#xff0c;公司的产品经理提了一个需求&#xff1a;系统需要记录每个用户的 CURD 操作&#xff0c;也就是说用户新增、编辑或者删除了什么数据&#xff0c;都需要记录下来&#xff0c;这个在 Nest.js 中如何实现呢&#xff1f; 这时候我们可以考虑使用 拦截器 来…

《书生大模型实战营第3期》进阶岛 第一关: 探索 InternLM 模型能力边界

文章大纲 OpenCompass 评测体验大模型对比评测 - Bad caseBad Case 1Bad Case 2Bad Case 3Bad Case 4Bad Case 5 大模型对比评测 - Good caseGood case 1Good Case 2 任务其他学习内容参考文献本人学习系列笔记第二期第三期 课程资源论文其他参考 OpenCompass 评测体验 https:…

opencv-python图像增强七:图像亮度对比度饱和度调整

文章目录 一&#xff0c;简介二&#xff0c;图像亮度对比度修改三&#xff0c;对比度增强&#xff1a; 一&#xff0c;简介 在图像处理领域&#xff0c;对比度、亮度和饱和度是影响图像视觉效果的重要因素。合理调整这三个参数&#xff0c;可以使图像更具表现力&#xff0c;满…

北斗短报文通信原理

短报文通信原理主要基于北斗卫星导航系统&#xff0c;其过程可以分为以下几个步骤&#xff1a;用户机将包含接收方ID号和通讯内容的通讯申请信号加密后通过卫星转发入站;地面中心站接收到通讯申请信号后&#xff0c;进行脱密和再加密处理&#xff0c;然后将其加入持续广播的出站…

WindowsAPI 查阅笔记:线程、多个线程互同步

1. 线程的创建 HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全属性 SIZE_T dwStackSize, //线程堆栈大小 LPTHREAD_START_ROUTINE lpStartAddress, //重要: 线程函数指针 LPVOID lpParameter, //重要: 启动线程函数 DWORD dwC…

分布式知识总结(一致性Hash算法)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 一致性Hash算法 假如有三台服务器编号node0、node1、node2&…

若依项目改造-sqlserver(2)

目前启动时&#xff0c;不需要配置数据库 1、启动时&#xff0c;不用检查数据库连接 2、可以在线导出数据库备份bak文件 3、实现不用配置jdk环境启动 4、实现启动没有控制台窗口

排序【归并排序和计数排序】

1.归并排序 1.1 基本思想 并归排序&#xff1a;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#x…

【代理模式】设计模式系列:实现与最佳实践(掌控访问的艺术)

文章目录 Java中的代理模式引言1. 代理模式概念1.1 代理模式定义1.2 代理模式的参与者1.3 代理模式的基本工作原理1.4 代理模式的优点与缺点 2. Java代理模式实现方式2.1 静态代理2.2 动态代理2.2.1 JDK动态代理2.2.2 CGLIB动态代理 2.3 两者之间的区别与选择 3. 使用案例分析3…

Mariadb数据库本机无密码登录的问题解决

Mariadb数据库本机无密码登录的问题解决 安装了mariadb后&#xff0c;发现Mariadb本机无密码才能登录 百度了很多文章&#xff0c;发现很多人是因为root的plugin设置的值不正确导致的&#xff0c;unix_socket可以不需要密码&#xff0c;mysql_native_password 是正常的。 解…

Codeforces Round 965 (Div. 2)

前言 有人在过七夕&#xff0c;我在打 cf &#xff0c;还有某人独自一人在学校机房&#xff0c;凌晨一点骑上共享单车回宿舍欣赏沿途的秋风扫落叶。 Standings&#xff1a;2166 题目链接&#xff1a;Dashboard - Codeforces Round 965 (Div. 2) - Codeforces A. Find K Distin…

未来能源技术

未来能源技术正处于全球焦点的中心&#xff0c;旨在应对气候变化、资源枯竭和能源安全的挑战。未来能源技术的发展方向集中在可再生能源、能源储存技术、智能电网、核聚变以及新材料的应用等多个领域。 1. 可再生能源技术 1.1 太阳能技术 太阳能技术是未来能源发展的核心领域之…

精密Δ-Σ ADC的有效噪声带宽

1 简介 即使对最有经验的模拟设计工程师来说&#xff0c;理解ADC噪声也是一项挑战。Δ-Σ ADC具有量化噪声和热噪声&#xff0c;其变化取决于ADC的分辨率、参考电压和输出数据速率。在系统层面上&#xff0c;噪声分析因附加的信号链组件而变得更加复杂&#xff0c;这些组件中的…

NLP_情感分类_序列模型方案

文章目录 项目背景代码导包读取数据文本预处理举例查看分词器数据集调整进一步剖析&#xff1a;对应Step [{i1}/{len(train_loader)}] 里的train_loader进一步剖析&#xff1a;Step [{i1}/{len(train_loader)}] 里的train_loader&#xff0c;原始的train_df 计算数据集中最长文…

Java 并发(四)—— volatile 和 synchronized

一、volatile 关键字 1.概念 如果我们将一个变量使用 volatile 修饰&#xff0c;这就指示 编译器&#xff0c;这个变量是共享且不稳定的&#xff0c;每次使用它都到主存中进行读取。 2.作用 保证变量对所有线程的可见性。但不能保证数据的原子性。因此不能完全保证线程安全…

STP(生成树)的概述和工作原理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

PHPStorm 环境配置与应用详解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; PHPStorm 是 JetBrains 出品的一款专业 PHP 集成开发环境&#xff08;IDE&#xff09;&#xff0c;凭借其智能的代码补全、调试功能、深度框架支持和前端开发工具&#xff0c;为用户提供了丰富的功能和工具…

简单的敏感词提示功能

简单的敏感词提示功能 1. 需求 公司现在接到通知&#xff0c;部分接口的部分手动输入字段&#xff0c;需要新增敏感词报红提示&#xff0c;敏感词汇现在应该是7000多个左右&#xff0c;需要我们提供一个敏感词校验接口&#xff0c;如果前端输入敏感词&#xff0c;则前端提示出…

在Unreal Engine中使用C++创建基础角色并添加移动功能

目录 引言 步骤一&#xff1a;创建C类 步骤二&#xff1a;编写C代码 步骤三&#xff1a;设置输入绑定 步骤四&#xff1a;在UE编辑器中测试 结论 引言 Unreal Engine&#xff08;UE&#xff09;以其强大的功能和灵活性在游戏开发界广受好评。本文将指导你如何在UE中通过…