KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记13 - STM32的SDIO学习5 - 卡的轮询读写擦
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记13 - STM32的SDIO学习5 - 卡的轮询读写擦
- 一、前情提要
- 二、目标
- 三、技术方案
- 3.1 读写擦的操作
- 3.1.1 读卡操作
- 3.1.2 写卡操作
- 3.1.3 擦除操作
- 3.2 一些技术点
- 3.2.1 轮询标志位的选择不唯一
- 3.2.2 写和擦的卡状态查询
- 3.2.3 写的速度
- 四、代码实现
- 4.1 接口定义
- 4.2 `read_block`接口的实现
- 4.3 `write_block`接口的实现
- 4.4 `erase_block`接口的实现
- 4.5 `send_cmd`内部函数
- 五、测试与结论
- 5.1 测试用例
- 5.2 运行结果
- 5.3 其他测试结果
- 六、总结
一、前情提要
在上一篇提到了要实现SDIO内存卡的读写擦,但是由于程序在调试的时候出现了一些bug,所以一直没有把这个坑填上。最近由于做了一些测试,把读写擦实现了。所以特此来把这个坑填上。
二、目标
- 实现读写擦的函数。
- 编写测试用例,将一个块擦除,写入内容,再读出来。
三、技术方案
3.1 读写擦的操作
读写擦的具体的指令其实很多帖子都有介绍,笔者就是参考的手册本身。但是具体的流程还是要说一下。
3.1.1 读卡操作
- 设置SDIO_DLEN和SDIO_DCTRL两个寄存器。在SDIO_DLEN设置块大小,一般是512字节;在SDIO_DCTRL里设置块大小是9(代表512)、数据传输方向是卡到MCU,暂不启动。必要的话CMD16设置卡的块大小。
- CMD7+RCA选中卡。
- 置位SDIO_DCTRL的Dten位,使能MCU的传输。
- CMD17+块地址要求卡发送数据
- 轮询SDIO_STA的SDIO_STA_RXFIFOHF位看看有没有数据到位;轮询SDIO_STA的SDIO_STA_DATAEND位检查卡是否已经发送完成。
- 轮询SDIO_STA的SDIO_STA_RXDAVL把管子里的数据都收拾出来。
- 通过复位SDIO_DCTRL的Dten位以关闭DPSM。
- 通过SDIO_ICR清了SDIO_STA。
- 收工
3.1.2 写卡操作
- 设置SDIO_DLEN和SDIO_DCTRL两个寄存器。在SDIO_DLEN设置块大小,一般是512字节;在SDIO_DCTRL里设置块大小是9(代表512)、数据传输方向是MCU到卡,暂不启动。必要的话CMD16设置卡的块大小。
- CMD7+RCA选中卡。
- 置位SDIO_DCTRL的Dten位,使能MCU的传输。
- CMD24+块地址通知卡MCU将要发送数据
- 轮询SDIO_STA的SDIO_STA_TXFIFOHE位看看是否管子里有空间发数据;轮询SDIO_STA的SDIO_STA_DATAEND位检查MCU是否已经发送完成。
- 轮询SDIO_STA的SDIO_STA_DBCKEND直至发送结束
- 通过复位SDIO_DCTRL的Dten位以关闭DPSM。
- CMD13轮询卡的状态。直至状态离开PROG状态。
- 收工
3.1.3 擦除操作
- CMD7+RCA选中卡。
- CMD32设置起始块、CMD33设置终止块和CMD38执行擦除。
- CMD13轮询卡的状态。直至离开PROG状态。
- 收工
3.2 一些技术点
3.2.1 轮询标志位的选择不唯一
由于没有采用DMA,所以读写的时候都必须手动轮询SDIO_STA的某些标志位来保证读写操作的顺利完成。但是参考手册会发现对于读写操作并没有规定操作规范。有的时候对于同一个目的可以有多个标志位可以使用。这里确实是有多个标志位可以采用。但是要通过测试去验证。
3.2.2 写和擦的卡状态查询
卡在执行写和擦的操作时候会处于PROG状态。这个时候必须要轮询至状态转移才可以保证操作的成功。
3.2.3 写的速度
按照卡的SDIO_STATUS,很多时候卡的速度都是24MBit/s或50MBit/s,但是在实际操作的时候会发现速度似乎只能开到6.7MBit/s左右,不论是单线模式还是4线模式都不行。看时钟信号发现是非常连续的,所以排除了发送数据的时候有延迟的原因。这个问题目前没有解决,如果未来找到了原因再记录。

从上面的这个图中可以看到,时钟信号SDIO_CLK(红色)其实是非常连贯的。但是频率只能达到6.8,也就是5+2分频。所以笔者认为其实换成DMA传输也不太可能改善这个。但是未来如果有机会试试再测试吧。
四、代码实现
4.1 接口定义
SDIO内存卡的接口定义如下所示:
#ifndef _SDIO_Memory_CARD_H_
#define _SDIO_Memory_CARD_H_#include "stdint.h"
typedef enum {waitRsp_noRsp = 0,waitRsp_shortRsp = 1,waitRsp_longRsp = 3,
}WaitRspKind;typedef struct {void (*init)(void);uint32_t (*card_identification)(void);uint32_t (*read_SD_status)(void);uint32_t (*erase_block)(uint32_t, uint32_t);uint32_t (*read_block)(uint32_t, uint32_t*);uint32_t (*write_block)(uint32_t, uint32_t*);
}SDIO_Memory_Card_Def;extern const SDIO_Memory_Card_Def SDIO_Memory_Card;
#endif
添加了3个函数接口,分别是
uint32_t (*erase_block)(uint32_t, uint32_t);uint32_t (*read_block)(uint32_t, uint32_t*);uint32_t (*write_block)(uint32_t, uint32_t*);
这三个接口的实现如下所示。但是由于前面说了逻辑,具体的每行的解释这里就不说了。
4.2 read_block接口的实现
; uint32_t read_block(uint32_t, uint32_t*);
; r0 is the address of the block,
; r1 is the read buffer.align 4
read_block procpush {r4 - r11, lr}ldr rSDIO, =SDIO_BaseAddrldr rCard_Info, =card_info_datasub sp, #4 * 2ldrb r4, card_isSDSClsl r0, r4str r0, [sp, #0]str r1, [sp, #4]; Select the Card. mov r0, #7:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmd
; Set the block size in case of SDSC. mov r0, #16:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, #512 bl send_cmdldr r4, [sp, #0] ; The address of the block in the SD Memory Cardldr r5, [sp, #4] ; The address of the buffer
; Send CMD17 to inform the card to start a data sending.mov r0, #17:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, r4bl send_cmd mov r0, #0str r0, [rSDIO, #SDIO_DCTRL]mov r0, #512str r0, [rSDIO, #SDIO_DLEN]mov r0, #(9 :shl: 4):or:SDIO_DCTRL_DTDIR_Card2Controller \:or: SDIO_DCTRL_Dtenstr r0, [rSDIO, #SDIO_DCTRL] reading_data_start ldr r0, [rSDIO, #SDIO_STA] tst r0, #SDIO_STA_RXACTbeq reading_data_start
reading_dataldr r0, [rSDIO, #SDIO_STA] tst r0, #SDIO_STA_DATAENDbne reading_clear_the_FIFOtst r0, #SDIO_STA_RXFIFOHFbeq reading_dataldr r1, [rSDIO, #SDIO_FIFO]str r1, [r5]add r5, #4b reading_data
reading_clear_the_FIFOldr r0, [rSDIO, #SDIO_STA]tst r0, #SDIO_STA_RXDAVLbeq reading_completedldr r1, [rSDIO, #SDIO_FIFO]str r1, [r5]add r5, #4b reading_clear_the_FIFO
reading_completed mov r0, #0str r0, [rSDIO, #SDIO_DCTRL]mov r0, #0x7ffstr r0, [rSDIO, #SDIO_ICR]mov r0, #7:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, #0bl send_cmdmov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmdldr r0, [rSDIO, #SDIO_RESP1]ubfx r0, r0, #9, #4add sp, #4 * 2pop {r4 - r11, lr}bx lrltorgendp
4.3 write_block接口的实现
; uint32_t write_block(uint32_t, uint32_t*);align 4
write_block procpush {r4 - r11, lr} ldr rSDIO, =SDIO_BaseAddrldr rCard_Info, =card_info_dataldrb r4, card_isSDSClsl r0, r4sub sp, #4 * 2str r0, [sp, #0]str r1, [sp, #4]mov r0, #7:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmdmov r0, #16:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, #512 bl send_cmdldr r4, [sp, #0] ; The address of the block in the SD Memory Cardldr r5, [sp, #4] ; The address of the buffermov r6, #0;mov r0, #24:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, r4bl send_cmd mov r0, #0str r0, [rSDIO, #SDIO_DCTRL]mov r0, #512str r0, [rSDIO, #SDIO_DLEN]mov r0, #(9:shl:4):or:SDIO_DCTRL_Dtenstr r0, [rSDIO, #SDIO_DCTRL]
writing_data_startldr r0, [rSDIO, #SDIO_STA]tst r0, #SDIO_STA_TXACTbeq writing_data_startmov r1, #SDIO_STA_DBCKEND:or:SDIO_STA_DCRCFAIL
writing_dataldr r0, [rSDIO, #SDIO_STA]tst r0, r1bne writing_completedtst r0, #SDIO_STA_TXFIFOEbeq writing_dataldr r0, [r5]str r0, [rSDIO, #SDIO_FIFO]add r5, #4add r6, #1b writing_data
writing_completedmov r0, #0str r0, [rSDIO, #SDIO_DCTRL]
; mov r0, #12:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMEN
; ldr r1, card_rca
; bl send_cmd
write_block_the_card_is_programming mov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rca bl send_cmdldr r0, [rSDIO, #SDIO_RESP1]ubfx r1, r0, #9, #4cmp r1, #7beq write_block_the_card_is_programmingmov r0, #0x7ffstr r0, [rSDIO, #SDIO_ICR]mov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rca bl send_cmdldr r0, [rSDIO, #SDIO_RESP1]add sp, #4 * 2pop {r4 - r11, lr}bx lrendp
4.4 erase_block接口的实现
; uint32_t erase_block(uint32_t, uint32_t);
; r0: Start block
; r1: End blockalign 4
erase_block procpush {r4 - r11, lr}ldr rSDIO, =SDIO_BaseAddrldr rCard_Info, =card_info_datasub sp, #4 * 2ldrb r4, card_isSDSClsl r0, r4lsl r1, r4str r0, [sp, #0]; [sp, #0] is the start block str r1, [sp, #4]; [sp, #4] is the end blockmov r0, #7:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmd mov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmdmov r0, #32:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, [sp, #0];bl send_cmdmov r0, #33:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, [sp, #4];bl send_cmdmov r0, #38:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENmov r1, #0bl send_cmderase_block_the_card_is_programmingmov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rca bl send_cmdldr r0, [rSDIO, #SDIO_RESP1]ubfx r1, r0, #9, #4cmp r1, #7beq erase_block_the_card_is_programmingmov r0, #7:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmd mov r0, #13:or:SDIO_CMD_WAITRESP_Short:or:SDIO_CMD_CPSMENldr r1, card_rcabl send_cmdldr r0, [rSDIO, #SDIO_RESP1]ubfx r0, r0, #9, #4add sp, #4 * 2pop {r4 - r11, lr}bx lrltorgendp
4.5 send_cmd内部函数
虽然前面的几个帖子中也讲到了这个内部函数的实现。但是为了方便阅读,这里还是把它粘过来了。
; Priviate Function Name: Send_cmd
; Args: r0 - cmd, r1 - arg
; 实现这个函数align 4
send_cmd procpush {r4 - r11, lr}ldr rSDIO, =SDIO_BaseAddrldr rCard_Info, =card_info_datamov r2, #0x7fstr r2, [rSDIO, #SDIO_ICR]str r1, [rSDIO, #SDIO_ARG]str r0, [rSDIO, #SDIO_CMD]
wait_for_responseldr r1, [rSDIO, #SDIO_STA]tst r1, #SDIO_STA_CMDREND:or:SDIO_STA_CCRCFAIL:or:SDIO_STA_CTIMEOUTbeq wait_for_responsebic r0, #SDIO_CMD_CPSMENstr r0, [rSDIO, #SDIO_CMD]pop {r4 - r11, lr} bx lrendp
五、测试与结论
5.1 测试用例
#include "cmsis_os2.h" // CMSIS RTOS header file
#include "SDIO_TestCase.h"
#include "SDIO_Memory_Card.h"
#include "stdio.h"
/*----------------------------------------------------------------------------* Thread 1 'Thread_Name': Sample thread*---------------------------------------------------------------------------*/static osThreadId_t tid_SDIO_Testcase; // thread idvoid SDIO_Testcase (void *argument); // thread functionint Init_SDIO_Testcase (void) {tid_SDIO_Testcase = osThreadNew(SDIO_Testcase, NULL, NULL);if (tid_SDIO_Testcase == NULL) {return(-1);}return(0);
}__NO_RETURN void SDIO_Testcase (void *argument) {static uint32_t resp = 0;static union{uint32_t buf32[512 / 4];char buf8[512];}rBuf, wBuf;(void)argument;sprintf(wBuf.buf8, "I love Miao! I love you, Da Miao");SDIO_Memory_Card.card_identification();SDIO_Memory_Card.read_SD_status();// SDIO_Memory_Card.erase_block(0,0);SDIO_Memory_Card.read_block(0, rBuf.buf32);SDIO_Memory_Card.erase_block(10,15);SDIO_Memory_Card.read_block(10, rBuf.buf32);SDIO_Memory_Card.write_block(11, wBuf.buf32);SDIO_Memory_Card.read_block(11, rBuf.buf32);while (1) {resp = (resp + 1)%100;osDelay(101);}
}
5.2 运行结果

可以看到,笔者成功地向第11块中写入了一行英文,“I love you, Da Miao, Kitty and Andy!”。
5.3 其他测试结果
对于这种SDIO内存卡,用单线还是四线数据总线模式其实都是成立的。只要MCU和卡的设置都协调好就可以了。
我把程序换到了另一个pin都引出来的板子上,把波形打出来。
单线模式下的波形。红线是SDIO_CLK,黄线是D0。也许有人会认为,这不就是个高速的I2C么。其实不是的。会看到,每一帧都没有ACK和NACK。所以不能替代I2C。

四线模式下的波形。红线是SDIO_CLK,其他是D0、D1和D2。由于这个示波器是借的,没有配数字探头,所以看不全所有的信号。
但是从调试上可以看到都能实现操作。

这里注明一下,因为HX32F4的开发板没有将SDIO有关的引脚引出,所以无法测量。我用另一个板子做了测试,但是用的IDE是Segger Embedded Studio做的,也就是上面的这个界面。
六、总结
这样,用轮询的方式实现读写擦SD卡的驱动就实现了。有若干的技术点:
- 读的速率可以根据卡的额定速度来,但是写入的速度不能高于6.8MBit/s。
- 写入和擦除之后要轮询卡的状态,确认卡已经从PROG状态中转出。
- 读写擦的轮询的标志位其实可以有多个选择。但是要测试确认。
- 管子的数据是32位的,但是发送的是按照8位的。所以可以认为是一次发4个字节。读写缓冲区都必须是字对齐(4字节对齐)。
- 要查询SDIO_STATUS,根据版本号确认如何读写。这里还是点一下,2GB以下的卡的寻址是以字节的,而以上的都是以块寻址的。当然,读写的时候都要以块为单位。比如,1GB的卡以字节寻址到第10块,但是还是要一次读1个整块。除非中途用CMD12打断。
这样就可以实现一套SDIO内存卡的驱动。
相关文章:
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记13 - STM32的SDIO学习5 - 卡的轮询读写擦
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记13 - STM32的SDIO学习5 - 卡的轮询读写擦 一、前情提要二、目标三、技术方案3.1 读写擦的操作3.1.1 读卡操作3.1.2 写卡操作3.1.3 擦除操作 3.2 一些技术点3.2.1 轮询标志位的选择不唯一3.2.2 写和擦的卡状态查询3.2.3 写的速度 四、代…...
【C++】HP-Socket(三):UdpClient、UdpServer、UdpCast、UdpNode的区别
1、简述 UDP是无连接的,在UDP传输层中并没有客户端和服务端的概念。但是可以在应用层定义客户端和服务端,可以灵活的互换客户端和服务端,或者同时既是客户端也是服务端。 HP-Socket中在应用层定义了四种UDP组件:UdpClient、UdpS…...
java设计模式六 访问者
访问者模式(Visitor Pattern)是一种设计模式,它允许你将算法附加到对象结构中的各个元素上,而不必修改对象结构本身。它主要用于处理对象结构非常稳定,但频繁需要在此结构上执行不同操作的场景。访问者模式通过将操作移…...
中间件研发之Springboot自定义starter
Spring Boot Starter是一种简化Spring Boot应用开发的机制,它可以通过引入一些预定义的依赖和配置,让我们快速地集成某些功能模块,而无需繁琐地编写代码和配置文件。Spring Boot官方提供了很多常用的Starter,例如spring-boot-star…...
libcity笔记:添加新模型(以RNN.py为例)
创建的新模型应该继承AbstractModel或AbstractTrafficStateModel 交通状态预测任务——>继承 AbstractTrafficStateModel类轨迹位置预测任务——>继承AbstractModel类 1 AbstractTrafficStateModel 2 RNN 2.1 构造函数 2.2 predict 2.3 calculate_loss...
Ansible---自动化运维工具
一、Ansible概述 1.1 Ansible简介 Ansible是一款自动化运维工具,通过ssh对目标主机进行配置、应用部署、任务执行、编排调度等操作。它简化了复杂的环境管理和自动化任务,提高了工作效率和一致性,同时,Ansible的剧本(playbooks)…...
5.Git
Git是一个分布式版本控制工具,主要用于管理开发过程中的源代码文件(Java类、xml文件、html文件等)。通过Git仓库来存储和管理这些文件,Git仓库分为两种 本地仓库:开发人员自己电脑上的Git仓库远程仓库:远程…...
探索中位数快速排序算法:高效寻找数据集的中间值
在计算机科学领域,寻找数据集的中位数是一个常见而重要的问题。而快速排序算法作为一种高效的排序算法,可以被巧妙地利用来解决中位数查找的问题。本文将深入探讨中位数快速排序算法的原理、实现方法以及应用场景,带你领略这一寻找中间值的高…...
密码学《图解密码技术》 记录学习 第十五章
目录 十五章 15.1本章学习的内容 15.2 密码技术小结 15.2.1 密码学家的工具箱 15.2.2 密码与认证 15.2.3 密码技术的框架化 15.2.4 密码技术与压缩技术 15.3 虚拟货币——比特币 15.3.1 什么是比特币 15.3.2 P2P 网络 15.3.3地址 15.3.4 钱包 15.3.5 区块链 15.3.…...
如何在 Ubuntu 16.04 上为 Nginx 创建自签名 SSL 证书
简介 TLS,即传输层安全协议,及其前身SSL,即安全套接字层,是用于将普通流量包装在受保护的加密包装中的网络协议。 使用这项技术,服务器可以在服务器和客户端之间安全地发送流量,而不会被外部方拦截。证书…...
5.协议的编解码
本章内容其实没有多大难度,主要考察大家的细心程度.计算数据长度然后截取相应字节数组并按照协议进行解码,编码则反之。 1.基础消息的编解码 Override public BasicMessage decode(byte[] bytes) {int dataLength ByteUtil.bytesToInt(ByteUtil.extra…...
数据结构基础| 线性表
线性表 定义 没有元素则为空表 例子: 稀疏多项式的运算 图书信息管理系统 特点 线性结构 同类型 线性表的类型定义 1.基本操作: InitList(&L) 操作结果:构造空的线性表L DestroyList(&L) 初始化条件:线性表L存在 操作结果:销毁线性表L(线性表L不存在) Cle…...
嵌入式学习
笔记 作业 有如下结构体 struct Student{ char name[16]; int age; double math_score; double chinese_score; double english_score; double physics_score; double chemistry…...
sass-loader和node-sass与node版本的依赖问题
sass-loader和node-sass与node版本的依赖问题 没有人会陪你走到最后,碰到了便是有缘,即使到了要下车的时候,也要心存感激地告别,在心里留下空白的一隅之地,多年后想起时依然心存甘味。——林清玄 报错截图 报错信息 np…...
基于BP神经网络的QPSK解调算法matlab性能仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ........................................................................ for ij 1:leng…...
Linux服务器常用巡检命令
在Linux服务器上进行常规巡检是确保服务器稳定性和安全性的重要措施之一。以下是一些常用的巡检命令和技巧: 1. 查看系统信息 1.1 系统信息显示 命令:uname -a [rootlinux100 ~]# uname -a Linux linux100 4.15.0-70-generic #79-Ubuntu SMP…...
VSCode 配置 CMake
VSCode 配置 C/C 环境的详细过程可参考:VSCode 配置 C/C 环境 1 配置C/C编译环境 如果是 Windows 环境,需要安装 MingW。 方案一 可以去官网(https://sourceforge.net/projects/mingw-w64/)下载安装包。 注意安装路径不要出现中文。 打开 windows she…...
《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制德国每日风能和太阳能产量3D线图
在MATLAB中,要绘制3D线图,可以使用 plot3 函数。 在《MATLAB科研绘图与学术图表绘制从入门到精通》书中通过绘制德国每日风能和太阳能产量3D线图解释了如何在MATLAB中绘制3D线图。 购书地址:https://item.jd.com/14102657.html...
【信息系统项目管理师知识点速记】质量管理:控制质量
控制质量是为了评估绩效,确保项目输出完整、正确且满足客户期望,而监督和记录质量管理活动执行结果的过程。控制质量过程需要在整个项目期间开展,其目的是测量产品或服务的完整性、合规性和适用性,以确保项目达到主要干系人的质量要求。 12.5.1 输入 项目管理计划 质量管理…...
【云原生】Pod 的生命周期(一)
【云原生】Pod 的生命周期(一)【云原生】Pod 的生命周期(二) Pod 的生命周期(一) 1.Pod 生命期2.Pod 阶段3.容器状态3.1 Waiting (等待)3.2 Running(运行中)3…...
ComfyUI-WanVideoWrapper完整指南:从零开始掌握AI视频生成神器
ComfyUI-WanVideoWrapper完整指南:从零开始掌握AI视频生成神器 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 你是否曾梦想过用AI将静态图片变成动态视频?或者让文字描述…...
魔兽争霸III终极优化指南:WarcraftHelper让你的游戏体验焕然一新
魔兽争霸III终极优化指南:WarcraftHelper让你的游戏体验焕然一新 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为…...
开发者知识管理工具CodingIT:架构设计与应用实践
1. 项目概述:一个面向开发者的“一站式”知识管理工具最近在整理个人技术笔记和项目文档时,我发现自己陷入了典型的“信息碎片化”困境:代码片段散落在Gist、笔记软件、本地文件甚至聊天记录里;项目文档要么是简陋的README&#x…...
Ubuntu服务器性能检测工具NetData安装
1. NetData安装 打开Ubuntu终端并输入以下指令: $ bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh)中途会提示安装文件将为占用磁盘空间,是否继续(Y/N),输入Y即可,安装完成后的截图如下…...
云代理商:Hermes Agent如何通过技能沉淀降低长期算力消耗
在 AI 智能体规模化落地的今天,算力成本高、重复推理多、长期运行效率衰减,已成为企业和开发者的核心痛点。传统 AI 智能体每处理一次相似任务,都要从零开始推理、反复调用工具,大量算力浪费在重复劳动中,长期使用成本…...
3步自动化优化:智能管理Cursor AI开发环境的革命性方案
3步自动化优化:智能管理Cursor AI开发环境的革命性方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…...
AI 术语通俗词典:Logistic 函数
Logistic 函数是数学、统计学、机器学习和人工智能中非常常见的一个术语。它用来描述一种把任意实数平滑映射到 0 和 1 之间的 S 形函数。换句话说,Logistic 函数是在回答:如果一个输入值可以从负无穷到正无穷变化,怎样把它转换成一个具有概率…...
告别‘玄学’:用Python从零实现一个能纠3个错的BCH码(附完整代码)
告别‘玄学’:用Python从零实现一个能纠3个错的BCH码(附完整代码) 在数字通信系统中,错误控制编码是确保数据可靠传输的核心技术之一。BCH码作为一种强大的循环码,不仅能检测错误,还能纠正多个随机错误&…...
企业级ai应用如何通过taotoken实现稳定低成本的多模型调用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业级AI应用如何通过Taotoken实现稳定低成本的多模型调用 在构建面向生产环境的企业级AI应用时,开发团队常常面临两个…...
AI智能体协同框架agentsync:事件驱动与状态同步实战解析
1. 项目概述与核心价值最近在探索AI智能体(Agent)的协同工作流时,我遇到了一个非常有意思的项目:obielin/agentsync。乍一看这个名字,你可能会联想到“代理同步”,但它的内涵远不止于此。简单来说ÿ…...
