libftdi1学习笔记 5 - SPI Nor Flash

目录

1.  初始化

2. CS控制例子

3. 读ID

3.1 制造商

3.2 容量大小

3.3 设置IO类型

3.3.1 setQSPIWinbond

3.3.2 setQSPIMxic

3.3.3 setQSPIMicrochip

3.3.4 setQSPIMicron

4. 写保护

5. 等待空闲

6. 擦除扇区

7. 页编程

8. 页读

9. 写

10. 读

11. 验证


基于MPSSE SPI实现Nor Flash的读写。也定义两组flash。

typedef enum
{SFLASH_PORT_0 = 0,SFLASH_PORT_1,SFLASH_PORT_MAX,
}sflash_port_e;

定义一个结构体记录flash的属性

typedef struct 
{sflash_io_e ioType;uint8_t spiPort;void (*pCSEnable)(uint8_t port, bool enable);sflash_manufactor_e manufactor;sflash_size size;sflash_addr_size_e addrSize;
}sflash_s;

ioType:表示flash的IO类型,一般支持3种接口方式:

typedef enum
{SFLASH_SPI = 0,SFLASH_DSPI,SFLASH_QSPI,
}sflash_io_e;

spiPort:表示该flash使用哪组SPI

pCSEnable:对应CS脚控制的接口函数

manufactor:该flash的生产商

typedef enum
{SFLASH_Winbond = 0,SFLASH_Cypress,SFLASH_ESMT,SFLASH_GigaDevice,SFLASH_MXIC,SFLASH_Micron,SFLASH_ISIS,SFLASH_Microchip,SFLASH_ZBit,SFLASH_FuDan,SFLASH_BOYA,SFLASH_Unknown,
}sflash_manufactor_e;

size:该flash的大小

typedef enum
{SFLASH_SIZE_256KB = 0,SFLASH_SIZE_512KB,SFLASH_SIZE_1MB,SFLASH_SIZE_2MB,SFLASH_SIZE_4MB,SFLASH_SIZE_8MB,SFLASH_SIZE_16MB,SFLASH_SIZE_32MB,
}sflash_size;

addrSize:该flash的地址宽度

typedef enum
{SFLASH_ADDR_24BIT = 3,SFLASH_ADDR_32BIT,
}sflash_addr_size_e;

1.  初始化

void sflashInit(uint8_t port, sflash_s init)
{if(port >= SFLASH_PORT_MAX)return;sflash[port] = init;
}

2. CS控制例子

初始化spi要根据实际情况配置CS的控制函数,例如:

#define SFLASH_CS_PIN       3
void sflash0CS(uint8_t port, bool enable)
{spiCPOL(port);mpsseGpioWrite(SFLASH_CS_PIN, !enable);
}

3. 读ID

通过命令0x9F读取flash的Jedec ID,其函数原型为:

uint32_t sflashReadJedecID(uint8_t port)

返回值即是id。

    uint8_t cmd[4] = {CMD_READ_ID, 0xff, 0xff, 0xff};uint32_t id;sflash[port].pCSEnable(port, true);spiWriteBytes(sflash[port].spiPort, cmd, 1);spiReadBytes(sflash[port].spiPort, cmd + 1, 3);sflash[port].pCSEnable(port, false);id = ((uint32_t)cmd[1] << 16) | (uint32_t)(cmd[2] << 8) | (uint32_t)(cmd[3]);

由于flash的QSPI方式和品牌商有关,这里根据ID做判断(注意,这套规则并不是所有厂商都符合)

3.1 制造商

由ID的16~23位确定品牌商

    switch (id & 0xff0000){case 0xEF0000:sflash[port].manufactor = SFLASH_Winbond;printf("sflash Winbond\n");break;case 0x010000:sflash[port].manufactor = SFLASH_Cypress;printf("sflash Cypress\n");break;case 0x8C0000:sflash[port].manufactor = SFLASH_ESMT;printf("sflash ESMT\n");break;case 0xC80000:sflash[port].manufactor = SFLASH_GigaDevice;printf("sflash GigaDevice\n");break;case 0xC20000:sflash[port].manufactor = SFLASH_MXIC;printf("sflash MXIC\n");break;case 0x200000:sflash[port].manufactor = SFLASH_Micron;printf("sflash Micron\n");break;case 0x5E0000:sflash[port].manufactor = SFLASH_ZBit;printf("sflash ZBit\n");break;case 0x9D0000:sflash[port].manufactor = SFLASH_ISIS;printf("sflash ISIS\n");break;case 0xA10000:sflash[port].manufactor = SFLASH_FuDan;printf("sflash FuDan\n");break;case 0xBF0000:sflash[port].manufactor = SFLASH_Microchip;printf("sflash Microchip\n");break;case 0x680000:sflash[port].manufactor = SFLASH_BOYA;printf("sflash BOYA\n");break;default:sflash[port].manufactor = SFLASH_Unknown;printf("sflash Unknown\n");break;}

3.2 容量大小

根据ID的位0~7确定容量大小

    switch(id & 0xff){case 0x12:sflash[port].size = SFLASH_SIZE_256KB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 256KB, 24bits address\n");break;case 0x13:sflash[port].size = SFLASH_SIZE_512KB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 512KB, 24bits address\n");break;case 0x14:sflash[port].size = SFLASH_SIZE_1MB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 1MB, 24bits address\n");break;case 0x15:sflash[port].size = SFLASH_SIZE_2MB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 2MB, 24bits address\n");break;case 0x16:sflash[port].size = SFLASH_SIZE_4MB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 4MB, 24bits address\n");break;case 0x17:sflash[port].size = SFLASH_SIZE_8MB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 8MB, 24bits address\n");break;case 0x18:sflash[port].size = SFLASH_SIZE_16MB;sflash[port].addrSize = SFLASH_ADDR_24BIT;printf("sflash size 16MB, 24bits address\n");break;case 0x19:sflash[port].size = SFLASH_SIZE_32MB;sflash[port].addrSize = SFLASH_ADDR_32BIT;printf("sflash size 32MB, 32bits address\n");break;}

3.3 设置IO类型

    if (sflash[port].ioType == SFLASH_QSPI){sflashSetQSPI(true);}else{sflashSetQSPI(false);}

根据不同制造商设置flash的IO类型,这里只实现SPI和QSPI的方式,部分制造商的设定方式是一样的。

bool sflashSetQSPI(uint8_t port, bool enable)
{bool ret = false;switch(sflash[port].manufactor){case SFLASH_Winbond:case SFLASH_GigaDevice:case SFLASH_Cypress:case SFLASH_ZBit:case SFLASH_BOYA:case SFLASH_FuDan:ret = setQSPIWinbond(port, enable);break;case SFLASH_MXIC:case SFLASH_ESMT:case SFLASH_ISIS:ret = setQSPIMxic(port, enable);break;case SFLASH_Microchip:ret = setQSPIMicrochip(port, enable);break;case SFLASH_Micron:ret = setQSPIMicron(port, enable);break;default:return false;}return ret;
}

3.3.1 setQSPIWinbond

第一种方式以Winbond为代表,QSPI的使能位在Status2寄存器中。

通过命令0x35读入该寄存器值,通过0x31写即可。

bool setQSPIWinbond(uint8_t port, bool enable)
{uint8_t cmd[2] = {0x35, 0xff};sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 1) < 0)return false;if(spiReadBytes(sflash[port].spiPort, cmd + 1, 1) < 0)return false;sflash[port].pCSEnable(port, false);if(enable == true){if ((cmd[1] & 0x02) == 0x02) //QE == 1{return true;}cmd[1] |= 0x02;}else{if ((cmd[1] & 0x02) == 0x00) //QE == 0{return true;}cmd[1] &= (uint8_t)0xFD;}cmd[0] = 0x31;sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 2) < 0)return false;sflash[port].pCSEnable(port, false);return true;
}

3.3.2 setQSPIMxic

第二种方式以Mxic为代表,QSPI的使能位在Status寄存器的位6

通过命令0x05读入该寄存器,0x01写。

bool setQSPIMxic(uint8_t port, bool enable)
{uint8_t cmd[2] = {0x05, 0xff};sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 1) < 0)return false;if(spiReadBytes(sflash[port].spiPort, cmd + 1, 1) < 0)return false;sflash[port].pCSEnable(port, false);if(enable == true){if ((cmd[1] & 0x40) == 0x40) //QE == 1{return true;}cmd[1] |= 0x40;}else{if ((cmd[1] & 0x40) == 0x00) //QE == 0{return true;}cmd[1] &= (uint8_t)0xBF;}cmd[0] = 0x01;sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 2) < 0)return false;sflash[port].pCSEnable(port, false);return true;
}

3.3.3 setQSPIMicrochip

Microchip的QSPI是 通过命令的方式使能(0x38)和禁止(0xFF)的。以SST26VF040A为例:

bool setQSPIMicrochip(uint8_t port, bool enable)
{uint8_t cmd[1] = {0x38};if(enable == true){sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 1) < 0)return false;sflash[port].pCSEnable(port, false);}else{cmd[0] = 0xff;sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 1) < 0)return false;sflash[port].pCSEnable(port, false);}return true;
}

3.3.4 setQSPIMicron

Micron(以MT25QL256为例)的QSPI通过读写易失性配置寄存器的位7配置。

通过命令0x85读入该寄存器,0x81写。

bool setQSPIMicron(uint8_t port, bool enable)
{uint8_t cmd[2] = {0x85, 0xff};sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 1) < 0)return false;if(spiReadBytes(sflash[port].spiPort, cmd + 1, 1) < 0)return false;sflash[port].pCSEnable(port, false);if(enable == true){if ((cmd[1] & 0x80) == 0x80) //QE == 1{return true;}cmd[1] |= 0x80;}else{if ((cmd[1] & 0x80) == 0x00) //QE == 0{return true;}cmd[1] &= (uint8_t)0x7F;}cmd[0] = 0x81;sflash[port].pCSEnable(port, true);if(spiWriteBytes(sflash[port].spiPort, cmd, 2) < 0)return false;sflash[port].pCSEnable(port, false);return true;
}

4. 写保护

使能写的命令为:

#define CMD_WRITE_ENABLE        0x06

对应的函数:

void sflashWriteEnable(uint8_t port)
{uint8_t cmd[1] = {CMD_WRITE_ENABLE};sflash[port].pCSEnable(port, true);spiWriteBytes(sflash[port].spiPort, cmd, 1);sflash[port].pCSEnable(port, false);
}

禁止写的命令为:

#define CMD_WRITE_DISABLE       0x04

对应的函数:

void sflashWriteDisable(uint8_t port)
{uint8_t cmd[1] = {CMD_WRITE_DISABLE};sflash[port].pCSEnable(port, true);spiWriteBytes(sflash[port].spiPort, cmd, 1);sflash[port].pCSEnable(port, false);
}

5. 等待空闲

通过读状态寄存器等待设备空闲。

void sflashWaitFree(uint8_t port)
{while(true){uint8_t cmd[2] = {CMD_READ_STATUS, 0xFF};sflash[port].pCSEnable(port, true);spiWriteBytes(sflash[port].spiPort, cmd, 1);spiReadBytes(sflash[port].spiPort, cmd + 1, 1);sflash[port].pCSEnable(port, false);if((cmd[1] & 0x01) == 0)break;usleep(1000);}
}

6. 擦除扇区

一般扇区大小为4096个字节,擦除扇区的命令

#define CMD_SECTOR_ERASE        0x20

命令后面接需要擦除扇区的起始地址。

在擦除命令前必须先设置写使能,擦除根据芯片不同可能需要几十ms才能完成(例如W25Q128FVxxIQ需要45ms,SST26VF032B需要25ms),等待一段时间后判断擦除是否完成,最后恢复写保护。

void sflashEraseSector(uint8_t port, uint32_t addr)
{uint8_t cmd[5] = {CMD_SECTOR_ERASE, 0, 0, 0, 0};uint8_t offset = 1;if(sflash[port].addrSize == SFLASH_ADDR_32BIT)cmd[offset++] = (uint8_t)(addr >> 24);cmd[offset++] = (uint8_t)(addr >> 16);cmd[offset++] = (uint8_t)(addr >> 8);cmd[offset++] = (uint8_t)(addr >> 0);sflashWriteEnable(port);sflash[port].pCSEnable(port, true);spiWriteBytes(sflash[port].spiPort, cmd, offset);sflash[port].pCSEnable(port, false);usleep(1000 * 20);sflashWaitFree(port);sflashWriteDisable(port);
}

7. 页编程

void sflashPageProgram(uint8_t port, uint32_t addr, uint8_t *buf, uint16_t len)

norflash的写不能按字节写,最小单位为页,一般页的大小为256字节。但是实际上页内是可以按照字节写的。比如可以在地址16的位置写10个字节数据。

地址的计算方式和擦除一样

    uint8_t cmd[5] = {CMD_PAGE_PROGRAM, 0, 0, 0, 0};uint8_t offset = 1;if(sflash[port].addrSize == SFLASH_ADDR_32BIT)cmd[offset++] = (uint8_t)(addr >> 24);cmd[offset++] = (uint8_t)(addr >> 16);cmd[offset++] = (uint8_t)(addr >> 8);cmd[offset++] = (uint8_t)(addr >> 0);

然后不同的接口有不同的命令,SPI的命令是0x02,QSPI的命令是0x32(这里有个特例,MXIC的芯片QPI的命令是0x38)。

#define CMD_PAGE_PROGRAM        0x02
#define CMD_PAGE_PROGRAM_QIO    0x32

注意,QPI的接口模式下,命令字是SPI方式发送的。 

    sflashWriteEnable(port);sflash[port].pCSEnable(port, true);if(sflash[port].ioType == SFLASH_QSPI){cmd[0] = CMD_PAGE_PROGRAM_QIO;if(sflash[port].manufactor == SFLASH_MXIC){cmd[0] = 0x38;}spiWriteBytes(sflash[port].spiPort, cmd, 1);qspiWriteBytes(sflash[port].spiPort, cmd + 1, offset);qspiWriteBytes(sflash[port].spiPort, buf, len);}else{cmd[0] = CMD_PAGE_PROGRAM;spiWriteBytes(sflash[port].spiPort, cmd, offset);spiWriteBytes(sflash[port].spiPort, buf, len);}sflash[port].pCSEnable(port, false);

最后等待编程结束

    sflashWaitFree(port);sflashWriteDisable(port);

8. 页读

对于flash来说,没有页读的概念,这里定义页读的方式是因为FTDI设备每笔最大通信是64K字节,每次读最好设置为256B,这是因为FTDI设备的最大传输字节数为64KB,由于GPIO模拟的SPI协议特别费字节,大了会超过64KB的大小,另外,太大了有时候会出现通讯错误

对于SPI接口,使用Fast Read命令0x0B,对于QSPI,使用0xEB命令。

#define CMD_FASTREAD            0x0B
#define CMD_FASTREAD_QIO        0xEB

地址的计算等同其他

    uint8_t cmd[5] = {CMD_FASTREAD, 0, 0, 0, 0};uint8_t offset = 1;if(sflash[port].addrSize == SFLASH_ADDR_32BIT)cmd[offset++] = (uint8_t)(addr >> 24);cmd[offset++] = (uint8_t)(addr >> 16);cmd[offset++] = (uint8_t)(addr >> 8);cmd[offset++] = (uint8_t)(addr >> 0);

写完地址后需要空读1-2个字节(QSPI是空读2个字节,SPI读空1个字节)

    sflash[port].pCSEnable(port, true);if(sflash[port].ioType == SFLASH_QSPI){uint8_t dummy[2];cmd[0] = CMD_FASTREAD_QIO;spiWriteBytes(sflash[port].spiPort, cmd, 1);qspiWriteBytes(sflash[port].spiPort, cmd + 1, offset);qspiReadBytes(sflash[port].spiPort, dummy, 2);qspiReadBytes(sflash[port].spiPort, buf, len);}else{uint8_t dummy[1];cmd[0] = CMD_FASTREAD;spiWriteBytes(sflash[port].spiPort, cmd, offset);spiReadBytes(sflash[port].spiPort, dummy, 1);spiReadBytes(sflash[port].spiPort, buf, len);}sflash[port].pCSEnable(port, false);

9. 写

void sflashWrite(uint8_t port, uint32_t addr, uint8_t *buf, uint32_t len)

在写之前要确保flash已经擦除。

首先判断一下地址是不是页对齐,不是就先把不齐的部分编程。

    uint32_t offset = 0;uint16_t count;if(port >= SFLASH_PORT_MAX)if(len == 0)return;if((addr % sflashPageSize) > 0){count = (len > (sflashPageSize - (addr % sflashPageSize))) ?(uint16_t)(sflashPageSize - (addr % sflashPageSize)) : (uint16_t)len;sflashPageProgram(port, addr, buf, count);offset += count;len -= count;addr += count;}

剩余的数据写完

    while (len > 0){count = (len > sflashPageSize) ? (uint16_t)sflashPageSize : (uint16_t)len;sflashPageProgram(port, addr, buf + offset, count);offset += count;len -= count;addr += count;}

10. 读

void sflashRead(uint8_t port, uint32_t addr, uint8_t *buf, uint32_t len)

读可以任意的地址读,没有特别的处理。

    uint32_t offset = 0;uint32_t readPageSize = 256;while(len > 0){uint16_t count;count = (len > readPageSize) ? (uint16_t)readPageSize : (uint16_t)len;sflashPageRead(port, addr, buf + offset, count);offset += count;len -= count;addr += count;} 

11. 验证

配置和SPI验证一样。这里只验证SPI、Mode0的方式。

擦除扇区->写随机数据->读入数据->比较读写的数据是否相等。

    #define EX_SFLASH_SIZE          2048uint8_t wrBuf[EX_SFLASH_SIZE];uint8_t rdBuf[EX_SFLASH_SIZE];int i;uint8_t port = 0;

然后产生随机数据

    srand(time(NULL));for(i = 0; i < EX_SFLASH_SIZE; i++){wrBuf[i] = (uint8_t)rand();rdBuf[i] = 0;}

擦除一个扇区

 sflashEraseSector(port, 0 * 4096);

将随机数据写入flash

    sflashWrite(port, 0, wrBuf, EX_SFLASH_SIZE);

再从相同地址读回

    sflashRead(port, 0, rdBuf, EX_SFLASH_SIZE);

最后比较

    for(i = 0; i < EX_SFLASH_SIZE; i++){if(wrBuf[i] != rdBuf[i]){printf("sflash test fail %d: %x!=%x\n", i, wrBuf[i], rdBuf[i]);break;}}printf("sflash test finish\n");

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

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

相关文章

cesium加载高层级离线影像地图瓦片(天地图、19级Arcgis)

实际加载效果如图&#xff1a; 1、下载离线地图瓦片方式&#xff08;多种任选其一&#xff0c;个人倾向于Qgis工具&#xff09;&#xff1a; 方式1、采用第三方下载工具如&#xff1a;91卫图、水经注、全能电子地图下载器、bigemap等等。&#xff08;这些有的下载层级不够&…

Spring Boot:Web应用开发之登录与退出的实现

Spring Boot 前言实现登录功能配置拦截器 实现退出功能 前言 登录与退出功能作为 Web 应用中的基础且重要的组成部分&#xff0c;直接关系到用户的安全和隐私保护。通过实现登录与退出功能&#xff0c;可以对用户的身份进行验证和授权&#xff0c;确保只有合法的用户才能访问特…

Qwen1.5大语言模型微调实践

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的兴起和广泛应用&#xff0c;为自然语言处理&#xff08;NLP&#xff09;带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者&#xff0c;不仅拥有强大的语言生成和理…

vue3【详解】选项式 API 实现逻辑复用

抽离逻辑代码到一个函数函数命名约定为 useXxxx格式 ( React Hooks 也是 )在 setup 中引用 useXxx 函数 演示代码&#xff1a;实时获取鼠标的坐标 逻辑封装 useMousePosition.js // 导入 ref, onMounted, onUnmounted import { ref, onMounted, onUnmounted } from "vue…

锐捷云桌面的安装

按下 <DEL> 键进入 BIOS setup 界面&#xff08;初始密码为 admin &#xff09;。 输入密码之后就进入 BIOS 的 Main 界面 设置服务器 BMC IP 地址。 a 云服务器启动后&#xff0c;在 BIOS 的主页面&#xff0c;把光标移到 [Server Mgmt] 项。 b 选择 [BMC Network C…

游戏前摇后摇Q闪E闪QE闪QA等操作

备注&#xff1a;未经博主允许禁止转载 个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_w…

基于Springboot的社区防疫物资申报系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的社区防疫物资申报系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

Quartz + SpringBoot 实现分布式定时任务

文章目录 前言一、分布式定时任务解决方案二、Quartz是什么&#xff1f;1.quartz简介2.quartz的优缺点 二、Quartz分布式部署总结 前言 因为应用升级&#xff0c;由之前的单节点微服务应用升级为集群微服务应用&#xff0c;所以之前的定时任务Spring Scheduled不再适用了&…

SV-704LW 无线WIFI网络音柱

SV-704LW 无线WIFI网络音柱(工业级) 一、描述 SV-704LW是深圳锐科达电子有限公司的一款壁挂式WIFI无线网络音柱&#xff0c;通过WIFI无线接入到WIFI覆盖的网络中&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;其采用防水设计&#xff0c;功率可以从30W到6…

如何利用FLUENT计算流体力学方法解决大气与环境领域流动问题

ANSYS FLUENT是目前全球领先的商用CFD 软件&#xff0c;市场占有率达70%左右&#xff0c;是工程师和研究者不可多得的有力工具。由于采用了多种求解方法和多重网格加速收敛技术&#xff0c;因而FLUENT能达到最佳的收敛速度和求解精度。灵活的非结构化网格和基于解的自适应网格技…

从OWASP API Security TOP 10谈API安全

1.前言 应用程序编程接口&#xff08;API&#xff09;是当今应用驱动世界创新的一个基本元素。从银行、零售、运输到物联网、 自动驾驶汽车、智慧城市&#xff0c;API 是现代移动、SaaS 和 web 应用程序的重要组成部分&#xff0c;可以在面向客 户、面向合作伙伴和内部的应用程…

计算机组成原理 — 控制单元的功能

控制单元的功能 控制单元的功能微操作命令分析取指周期间址周期执行周期中断周期 控制单元的功能控制单元的外特性输入信号输出信号 控制信号举例不采用CPU内部总线的方式取指周期间址周期执行周期 采用CPU内部总线的方式取指周期间址周期执行周期 多级时序系统机器周期时钟周期…

反激电源——TL431及光耦反馈电路计算(不涉及环路补偿)

一、TL431及光耦反馈电路 TL431以及光耦电路是反激的副边反馈类型电路中的常见应用。 其反馈工作原理为&#xff1a;当副边的输出电压升高时&#xff0c;TL431的REF点采样电压也会升高&#xff0c;使得TL431的导通量增加&#xff0c;同时光耦内部的发光二极管流过的电流也增大&…

线段树汇总

线段树是一种二叉搜索树&#xff0c;与区间树相似&#xff0c;它将一个区间划分成一些单元区间&#xff0c;每个单元区间对应线段树中的一个叶结点。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数&#xff0c;时间复杂度为O(logN)。而未优化的空间复杂度为2N&a…

SpringCloud系列(4)--SpringCloud微服务工程构建

前言&#xff1a;在上节我们新建了一个SpringCloud父工程&#xff0c;这一节主要是构建微服务工程&#xff0c;通过实现订单模块和支付模块来熟悉微服务的概念和构建过程。 1、在父工程下新建模块 2、选择模块的项目类型为Maven并选择模块要使用的JDK版本 3、填写子模块的名称&…

企业网盘搭建——LNMP

php包链接&#xff1a;https://pan.baidu.com/s/1RElYTQx320pN6452N_7t1Q?pwdp8gs 提取码&#xff1a;p8gs 网盘源码包链接&#xff1a;https://pan.baidu.com/s/1BaYqwruka1P6h5wBBrLiBw?pwdwrzo 提取码&#xff1a;wrzo 目录 一.手动部署 二.自动部署 一.手动部署 …

SQL表连接详解:JOIN与逗号(,)的使用及其性能影响

省流版 在这个详细的解释中&#xff0c;我们将深入探讨SQL中表连接的概念&#xff0c;特别是JOIN和逗号&#xff08;,&#xff09;在连接表时的不同用法及其对查询性能的影响。通过实际示例和背后的逻辑分析&#xff0c;我们将揭示在不同场景下选择哪种连接方式更为合适。 1.…

BioTech - 使用 Amber 工具 松弛(Relaxation) 蛋白质三维结构 (Python)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/137889532 Amber 工具在蛋白质 松弛(Relaxation) 过程中起着重要的作用。在分子动力学模拟中,蛋白质松弛是指模拟过程中蛋白质结构达到一个较为稳定的状态。这个过程通…

社交媒体数据恢复:推特、Twitter

推特&#xff08;Twitter&#xff09;数据恢复&#xff1a;如何找回丢失的内容 随着社交媒体的普及&#xff0c;越来越多的人开始使用推特&#xff08;Twitter&#xff09;来分享生活点滴、发表观点和获取信息。然而&#xff0c;有时候我们会不小心删除了重要的推文&#xff0…

根据 Excel 列生成 SQL

公司有个历史数据刷数据的需求, 开发功能有点浪费, 手工刷数据有点慢, 所以研究了下 excel 直接生成 SQL, 挺好用, 记录一下; 例如这是我们的数据, 要求把创建时间和完成时间刷进数据库中, 工单编号唯一 Excel 公式如下: "UPDATE service_order SET create…