当前位置: 首页 > news >正文

SPI 通信协议

1. SPI通信

1. 什么是SPI通信协议

2. SPI的通信过程  

在一开始会先把发送缓冲器的数据(8位)。一次性放到移位寄存器里。 移位寄存器会一位一位发送出去。但是要先放到锁存器里。然后从机来读取。从机的过程也一样。当移位寄存器的数据全部发送完。其实是主机与从机交换了数据。这时一次性把移位寄存器的数据放到接收缓冲器中。

 

3. SPI的几种模式 

CPOL时钟极性决定空闲时的高低电平。设置为1。空闲就是高电平。设置为0。空闲就是低电平。

CPHA时钟相位什么时候进行采样。设置为0。在第一个时钟边沿采集。所以在采集前要准备好数据。设置为1。在第二个时钟边沿采集。

 

 

 

 

具体采用那种模式。查看从机手册支持哪种SPI模式来进行选择。

4. SPI的具体连接模式。

一主一从

一主多从 (通过哪个从机的片选使能来选择。如果某个从机选中。其他的从机就不起作用)

SPI不支持多主机的。 

 

对从机比较多那么相应的片选引脚也需要更多。可以采用菊花链连接来减少I/o口。从而节省资源。

但这种连接对于SPI通信也会变的复杂。

 5. SPI于IIC的比较

 

1. W25Q32介绍

当MCU资源不够用就可以外接一个W25Qxx芯片。

1. W25Q32的命名。

 2. W25Q32的引脚。

 WP:写保护引脚  在进行写操作时先要取消写保护才能进行写操作。

 /HOLD or /RESET:如果这个引脚有效。即使片选有效。W25Q32也不会生效相当于高组态。

其他引脚:CS DO DI  CLK  GND  VCC。

3. 存储划分的方便管理

对SPI发送的指令然后驱动电路对存储数据进行操作。

 

 4. w25Q32具体硬件图。 

 

5. W25Q32的寄存器

 只看状态寄存器1的低两位其余的自行查手册。

 6. 指令操作。(具体看手册指令的作用以及指令发送怎么获取数据)

 

 1. 读指令

具体的伪代码 

 

2. 擦除

 

 

 

3. 写指令 

3.  dome 实现SPI读取W25Q32

1. 程序设计 

 

  

2. 写数据注意事项

 

 

 

 

3. 具体的接线 

因为是模拟SPI所以引脚可以任意设定。

这里选择是SCL = PA5 ,MOSI = PA7 ,MISO = PA6 ,CS = PA4。

 soft_spi.h

#ifndef _SOFT_SPI_H
#define _SOFT_SPI_H
/**
filename: soft_spi.h**/
#include "gd32f10x.h"
#include "systick.h"//定义表示具体IO口的资源宏(模拟SPI的选用的引脚)
#define SPI_PORT GPIOA
#define SPI_MOSI GPIO_PIN_7
#define SPI_MISO GPIO_PIN_6
#define SPI_SCK  GPIO_PIN_5
#define SPI_CS   GPIO_PIN_4/* SPI的模式 */
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3void soft_spi_init(void);                  // spi通信准备,初始化
void soft_spi_init_io(void);               // 初始化spi通信用到的io口
void soft_spi_init_mode(uint8_t spi_mode); // 初始化spi通信模式,时钟相位和时钟极性void soft_spi_begin(void);               // 开始spi通信
void soft_spi_w_cs(uint8_t bit_value);   // 写片选cs口uint8_t soft_spi_swap(uint8_t byte_to_send); /* 交换数据 */void soft_spi_w_sck(uint8_t bit_value);   // 写时钟口
void soft_spi_w_mosi(uint8_t bit_value);  // 写MOSI口
uint8_t soft_spi_r_miso(void);            // 读MISO口void soft_spi_end(void);  // 结束spi通信#endif

soft_spi.c

#include "soft_spi.h"uint8_t clock_polar;
uint8_t clock_phase;// spi通信准备,初始化
void soft_spi_init(void){soft_spi_init_io();soft_spi_init_mode(SPI_MODE0);
}// 初始化spi通信用到的io口
void soft_spi_init_io(void){rcu_periph_clock_enable(RCU_GPIOA); /* 使能GPIOA时钟 */gpio_init(SPI_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SPI_MOSI|SPI_SCK|SPI_CS); /* MOSI, SCK, CS 配置成推挽输出  */gpio_init(SPI_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, SPI_MISO); /* MISO 输入模式  */
}// 初始化spi通信模式,时钟相位和时钟极性
void soft_spi_init_mode(uint8_t spi_mode){switch(spi_mode){case SPI_MODE0:clock_polar = 0;clock_phase = 0;break;case SPI_MODE1:clock_polar = 0;clock_phase = 1;break;case SPI_MODE2:clock_polar = 1;clock_phase = 0;break;case SPI_MODE3:clock_polar = 1;clock_phase = 1;break;default:break;}
}// 开始spi通信
void soft_spi_begin(void){soft_spi_w_cs((bit_status)0);  /* 把从机的片选拉低 */
}// 写片选cs口
void soft_spi_w_cs(uint8_t bit_value){gpio_bit_write(SPI_PORT, SPI_CS, (bit_status)bit_value);
}/*
重要函数,spi主机的移位寄存器与spi从机移位寄存器交换数值
*/
uint8_t soft_spi_swap(uint8_t byte_to_send){uint8_t byte_receive = 0x00;uint8_t i;for(i = 0; i < 8; i++){soft_spi_w_sck(clock_polar ? 1:0); /* 先有一个SCLghh空闲 */ delay_1us(1);if(clock_phase){if(soft_spi_r_miso() == 1)byte_receive |= (0x80 >> i); /* 采集数据 */soft_spi_w_sck(clock_phase ? 0 : 1);delay_1us(1);soft_spi_w_mosi(byte_to_send & (0x80 >> i)); /* 先写 */}else{soft_spi_w_mosi(byte_to_send & (0x80 >> i)); /* 先写 */soft_spi_w_sck(clock_phase ? 0 : 1); /* 产生沿 */delay_1us(1);if(soft_spi_r_miso() == 1)byte_receive |= (0x80 >> i); /* 采集数据 */}}return byte_receive;
}// 写时钟口
void soft_spi_w_sck(uint8_t bit_value){gpio_bit_write(SPI_PORT, SPI_SCK, (bit_status)bit_value);
}// 写MOSI口
void soft_spi_w_mosi(uint8_t bit_value){gpio_bit_write(SPI_PORT, SPI_MOSI, (bit_status)bit_value);
}// 读MISO口
uint8_t soft_spi_r_miso(void){return gpio_input_bit_get(SPI_PORT, SPI_MISO);    
}// 结束spi通信
void soft_spi_end(void){soft_spi_w_sck(clock_polar ? 1:0); /* 根据模式来选择空闲电平 */soft_spi_w_cs((bit_status)1); /* 片选拉高 */
}

 w25qxx_spi.h

#ifndef _W25QXX_SPI_H
#define _W25QXX_SPI_H#include "gd32f10x.h"
#include "w25qxx_ins.h"
#include "soft_spi.h"#define W25QXX_ID_1           1#define W25QXX_SR_ID_1        1
#define W25QXX_SR_ID_2        2
#define W25QXX_SR_ID_3        3void w25qxx_init(void);void w25qxx_wait_busy(void);
uint8_t w25qxx_read_sr(uint8_t sregister_id);  // 读状态寄存器void w25qxx_read(uint8_t *p_buffer, uint32_t read_addr, uint16_t num_read_bytes);void w25qxx_write(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes);
void w25qxx_write_nocheck(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes);
void w25qxx_write_page(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes); void w25qxx_erase_sector(uint32_t sector_addr);
void w25qxx_erase_chip(void);void w25qxx_write_enable(void);
void w25qxx_write_disable(void);void w25qxx_power_down(void);
void w25qxx_wake_up(void);void w25qxx_cs_enable(uint8_t cs_id);
void w25qxx_cs_disable(uint8_t cs_id);
uint8_t w25qxx_swap(uint8_t byte_to_send);#endif

 w25qxx_spi.c

 

#include "w25qxx_spi.h"/* w25Q的初始化 */
void w25qxx_init(void){soft_spi_init();
}// 如果SR-1的BUSY位为1的话,一直等待,直到BUSY位为0,结束等待
// 判断是否在忙
void w25qxx_wait_busy(void){while((w25qxx_read_sr(W25QXX_SR_ID_1) & 0x01) == 0x01){;}
}// 读状态寄存器
uint8_t w25qxx_read_sr(uint8_t sregister_id){uint8_t command, result;switch(sregister_id){case W25QXX_SR_ID_1:command = W25QXX_READ_STATUS_REGISTER_1;break;case W25QXX_SR_ID_2:command = W25QXX_READ_STATUS_REGISTER_2;break;case W25QXX_SR_ID_3:command = W25QXX_READ_STATUS_REGISTER_3;break;default:command = W25QXX_READ_STATUS_REGISTER_1;break;}w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(command);result = w25qxx_swap(0xFF);w25qxx_cs_disable(W25QXX_ID_1);return result;
}// 读flash的数据
// *p_buffer 读回的数据的存放位置
void w25qxx_read(uint8_t *p_buffer, uint32_t read_addr, uint16_t num_read_bytes){uint16_t i;w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_READ_DATA); //发送读数据的指令w25qxx_swap(read_addr >> 16);  //发送24bit地址w25qxx_swap(read_addr >> 8);w25qxx_swap(read_addr);for(i=0; i < num_read_bytes; i++){p_buffer[i] = w25qxx_swap(0xFF);}w25qxx_cs_disable(W25QXX_ID_1);
}// 
uint8_t W25QXX_Buffer[4096];  //用来存放从sector读出的bytes
void w25qxx_write(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes){uint32_t sec_num;uint16_t sec_remain;uint16_t sec_off;uint16_t i;sec_num	= write_addr / 4096;              //要写入的位置处在第sec_num个扇区上sec_off = write_addr % 4096;sec_remain = 4096 - sec_off;if(num_write_bytes <= sec_remain){w25qxx_read(W25QXX_Buffer, sec_num * 4096, 4096);  //扇区的数据读出来for(i = 0; i < sec_remain; i++){if(W25QXX_Buffer[i + sec_off] != 0xFF)  //说明这个扇区的第i+sec_off位没有擦除break;}if(i < sec_remain){ // 扇区没有擦除w25qxx_erase_sector(sec_num * 4096);for(i = 0; i < sec_remain; i++){W25QXX_Buffer[i + sec_off] = p_buffer[i];}w25qxx_write_nocheck(W25QXX_Buffer, sec_num * 4096, 4096);}else{              // 扇区sec_remain部分是擦除过的w25qxx_write_nocheck(p_buffer, write_addr, num_write_bytes);}}else{w25qxx_read(W25QXX_Buffer, sec_num * 4096, 4096);  //扇区的数据读出来for(i = 0; i < sec_remain; i++){if(W25QXX_Buffer[i + sec_off] != 0xFF)  //说明这个扇区的第i+sec_off位没有擦除break;}if(i < sec_remain){ // 扇区没有擦除w25qxx_erase_sector(sec_num * 4096);for(i = 0; i < sec_remain; i++){W25QXX_Buffer[i + sec_off] = p_buffer[i];}w25qxx_write_nocheck(W25QXX_Buffer, sec_num * 4096, 4096);}else{              // 扇区sec_remain部分是擦除过的w25qxx_write_nocheck(p_buffer, write_addr, sec_remain);}write_addr += sec_remain;p_buffer += sec_remain;num_write_bytes -= sec_remain;w25qxx_write(p_buffer, write_addr, num_write_bytes);}//判断读出来的数据是否都为0xFF//扇区是否删除//判断是否跨页
}// 调用之前先确保扇区删除
void w25qxx_write_nocheck(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes){uint16_t page_remain = 256 - write_addr % 256;if(num_write_bytes <= page_remain){w25qxx_write_page(p_buffer, write_addr, num_write_bytes);}else{w25qxx_write_page(p_buffer, write_addr, page_remain);p_buffer += page_remain;write_addr += page_remain;num_write_bytes -= page_remain;w25qxx_write_nocheck(p_buffer, write_addr, num_write_bytes);}
}// page program
// 保证没有跨页写的前提下调用此函数往某个页上写内容
void w25qxx_write_page(uint8_t *p_buffer, uint32_t write_addr, uint16_t num_write_bytes){uint16_t i;w25qxx_write_enable();w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_PAGE_PROGRAM);w25qxx_swap(write_addr >> 16);  //发送24bit地址w25qxx_swap(write_addr >> 8);w25qxx_swap(write_addr);for(i = 0; i < num_write_bytes; i++){w25qxx_swap(p_buffer[i]);}w25qxx_cs_disable(W25QXX_ID_1);w25qxx_wait_busy();
}/* 擦除一个扇区 */
void w25qxx_erase_sector(uint32_t sector_addr){w25qxx_write_enable();w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_SECTOR_ERASE_4KB);w25qxx_swap(sector_addr >> 16);w25qxx_swap(sector_addr >> 8);w25qxx_swap(sector_addr);w25qxx_cs_disable(W25QXX_ID_1);w25qxx_wait_busy();
}/* 擦除全部 */
void w25qxx_erase_chip(void){w25qxx_write_enable();w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_CHIP_ERASE);w25qxx_cs_disable(W25QXX_ID_1);w25qxx_wait_busy();
}
/* 使能写保护 */
void w25qxx_write_enable(void){w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_WRITE_ENABLE);w25qxx_cs_disable(W25QXX_ID_1);
}/* 失能写保护 */
void w25qxx_write_disable(void){w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_WRITE_DISABLE);w25qxx_cs_disable(W25QXX_ID_1);
}// 低电量休眠
void w25qxx_power_down(void){w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_POWER_DOWN);w25qxx_cs_disable(W25QXX_ID_1);
}// 唤醒
void w25qxx_wake_up(void){w25qxx_cs_enable(W25QXX_ID_1);w25qxx_swap(W25QXX_RELEASE_POWER_DOWN_HPM_DEVICE_ID);w25qxx_cs_disable(W25QXX_ID_1);
}/*
brief:使能片选引脚cs
cs_id: cs引脚的序号,即第几个w25qxx flash
*/
void w25qxx_cs_enable(uint8_t cs_id){switch(cs_id){case W25QXX_ID_1:soft_spi_begin();break;default:break;}
}// brief:失能片选引脚cs
void w25qxx_cs_disable(uint8_t cs_id){switch(cs_id){case W25QXX_ID_1:soft_spi_end();break;default:break;}
}/*
**** 交换数据
*/
uint8_t w25qxx_swap(uint8_t byte_to_send){return soft_spi_swap(byte_to_send);
}

 w25qxx_ins.h (w25Q32的指令集)

#ifndef _W25QXX_INS_H
#define _W25QXX_INS_H#define W25QXX_WRITE_ENABLE							        0x06
#define W25QXX_WRITE_DISABLE						        0x04
#define W25QXX_READ_STATUS_REGISTER_1				        0x05
#define W25QXX_READ_STATUS_REGISTER_2				        0x35
#define W25QXX_READ_STATUS_REGISTER_3				        0x15
#define W25QXX_READ_DATA							        0x03
#define W25QXX_READ_UNIQUE_ID						        0x4B
#define W25QXX_WRITE_STATUS_REGISTER_1				        0x01
#define W25QXX_WRITE_STATUS_REGISTER_2                      0x31
#define W25QXX_WRITE_STATUS_REGISTER_3                      0x11 
#define W25QXX_PAGE_PROGRAM							        0x02
#define W25QXX_QUAD_PAGE_PROGRAM					        0x32
#define W25QXX_BLOCK_ERASE_64KB						        0xD8
#define W25QXX_BLOCK_ERASE_32KB						        0x52
#define W25QXX_SECTOR_ERASE_4KB						        0x20
#define W25QXX_CHIP_ERASE							        0xC7
#define W25QXX_ERASE_SUSPEND						        0x75
#define W25QXX_ERASE_RESUME							        0x7A
#define W25QXX_POWER_DOWN							        0xB9
#define W25QXX_HIGH_PERFORMANCE_MODE				        0xA3
#define W25QXX_CONTINUOUS_READ_MODE_RESET			        0xFF
#define W25QXX_RELEASE_POWER_DOWN_HPM_DEVICE_ID             0xAB
#define W25QXX_MANUFACTURER_DEVICE_ID				        0x90
#define W25QXX_JEDEC_ID								        0x9F
#define W25QXX_FAST_READ							        0x0B
#define W25QXX_FAST_READ_DUAL_OUTPUT				        0x3B
#define W25QXX_FAST_READ_DUAL_IO					        0xBB
#define W25QXX_FAST_READ_QUAD_OUTPUT				        0x6B
#define W25QXX_FAST_READ_QUAD_IO					        0xEB
#define W25QXX_OCTAL_WORD_READ_QUAD_IO				        0xE3
#define W25QXX_DUMMY_BYTE							        0xFF#endif

 对于w25Q3的写操作是比较复杂的。比如要考虑写的大小是否大于一页.以及在写之前要判断是否擦除。因为要先擦除才能写入。

相关文章:

SPI 通信协议

1. SPI通信 1. 什么是SPI通信协议 2. SPI的通信过程 在一开始会先把发送缓冲器的数据&#xff08;8位&#xff09;。一次性放到移位寄存器里。 移位寄存器会一位一位发送出去。但是要先放到锁存器里。然后从机来读取。从机的过程也一样。当移位寄存器的数据全部发送完。其实…...

【图像处理】使用各向异性滤波器和分割图像处理从MRI图像检测脑肿瘤(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

5个适合初学者的初级网络安全工作,网络安全就业必看

前言 网络安全涉及保护计算机系统、网络和数据免受未经授权的访问、破坏和盗窃 - 防止数字活动和数据访问的中断 - 同时也保护用户的资产和隐私。鉴于公共事业、医疗保健、金融以及联邦政府等行业的网络犯罪攻击不断升级&#xff0c;对网络专业人员的需求很高&#xff0c;这并…...

Kafka核心原理

1、Topic的分片和副本机制 分片作用&#xff1a; 解决单台节点容量有限的问题&#xff0c;节点多&#xff0c;效率提升&#xff0c;吞吐量提升。通过分片&#xff0c;将一个大的容器分解为多个小的容器&#xff0c;分布在不同的节点上&#xff0c;从而实现分布式存储。 分片…...

探秘前后端开发世界:猫头虎带你穿梭编程的繁忙街区,解锁全栈之路

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

洛谷_分支循环

p2433 问题 5 甲列火车长 260 米&#xff0c;每秒行 12 米&#xff1b;乙列火车长220 米&#xff0c;每秒行 20 米&#xff0c;两车相向而行&#xff0c;从两车车头相遇时开始计时&#xff0c;多长时间后两车车尾相离&#xff1f;已知答案是整数。 计算方式&#xff1a;两车车…...

MySQL数据库入门到精通——进阶篇(3)

黑马程序员 MySQL数据库入门到精通——进阶篇&#xff08;3&#xff09; 1. 锁1.1 锁-介绍1.2 锁-全局锁1.3 锁-表级锁1.3.1 表级锁-表锁1.3.2 表级锁元数据锁( meta data lock&#xff0c;MDL)1.3.3 表级锁-意向锁1.3.4 表级锁意向锁测试 1.4 锁-行级锁1.4.1 行级锁-行锁1.4.2…...

Mind Map:大语言模型中的知识图谱提示激发思维图10.1+10.2

知识图谱提示激发思维图 摘要介绍相关工作方法第一步&#xff1a;证据图挖掘第二步&#xff1a;证据图聚合第三步&#xff1a;LLM Mind Map推理 实验实验设置医学问答长对话问题使用KG的部分知识生成深入分析 总结 摘要 LLM通常在吸收新知识的能力、generation of hallucinati…...

[引擎开发] 杂谈ue4中的Vulkan

接触Vulkan大概也有大半年&#xff0c;概述一下自己这段时间了解到的东西。本文实际上是杂谈性质而非综述性质&#xff0c;带有严重的主观认知&#xff0c;因此并没有那么严谨。 使用Vulkan会带来什么呢&#xff1f;简单来说就是对底层更好的控制。这意味着我们能够有更多的手段…...

docker--redis容器部署及地理空间API的使用示例-II

文章目录 Redis 地理位置类型API命令操作示例JAVA使用示例导入依赖RedisTemplate 操作GeoData示例CityInfo实体类Geo操作接口类Geo操作接口实现类SpringBoot测试类RedissonClient 操作GeoData示例docker–redis容器部署及与SpringBoot整合 docker–redis容器部署及地理空间API的…...

Vue中如何进行文件浏览与文件管理

Vue中的文件浏览与文件管理 文件浏览与文件管理是许多Web应用程序中常见的功能之一。在Vue.js中&#xff0c;您可以轻松地实现文件浏览和管理功能&#xff0c;使您的应用程序更具交互性和可用性。本文将向您展示如何使用Vue.js构建文件浏览器和文件管理功能&#xff0c;以及如…...

jenkins利用插件Active Choices Plug-in达到联动显示或隐藏参数,且参数值可修改

1. 添加组件 Active Choices Plug-in 如jenkins无法联网&#xff0c;可在以下两个地址中下载插件&#xff0c;然后放到/home/jenkins/.jenkins/plugin下面重启jenkins即可 Active Choices Active Choices | Jenkins plugin 2. 效果如下&#xff1a; sharding为空时&#xf…...

香蕉叶病害数据集

1.数据集 第一个文件夹为数据增强&#xff08;旋转平移裁剪等操作&#xff09;后的数据集 第二个文件夹为原始数据集 2.原始数据集 Cordana文件夹&#xff08;162张照片&#xff09; healthy文件夹&#xff08;129张&#xff09; Pestalotiopsis文件夹&#xff08;173张照片&…...

天地无用 - 修改朋友圈的定位: 高德地图 + 爱思助手

1&#xff0c;电脑上打开高德地图网页版 高德地图 (amap.com) 2&#xff0c;网页最下一栏&#xff0c;点击“开放平台” 高德开放平台 | 高德地图API (amap.com) 3&#xff0c;在新网页中&#xff0c;需要登录高德账户才能操作。 可以使用手机号和验证码登录。 4&#xff0c…...

AtCoder Beginner Contest 232(A-G)

A - QQ solver (atcoder.jp)直接按题意模拟即可。 B - Caesar Cipher (atcoder.jp)按题意模拟即可 C - Graph Isomorphism (atcoder.jp)按题意模拟即可 D - Weak Takahashi (atcoder.jp) 一个非常套路的网格dp E - Rook Path (atcoder.jp) &#xff08;1&#xff09;题意 有…...

计算机网络(第8版)-第5章 运输层

5.1 运输层协议概述 5.1.1 进程之间的通信 图5-1 中两个运输层之间有一个深色双向粗箭头&#xff0c;写明“运输层提供应用进程间的逻辑通信”。 图5-1 运输层为相互通信的应用进程提供了逻辑通信 5.1.2 运输层的两个主要协议 5.1.3 运输层的端口 请注意&#xff0c;这种…...

AtCoder Beginner Contest 231(D-F,H)

D - Neighbors (atcoder.jp) &#xff08;1&#xff09;题意 给出M组关系&#xff0c;问是否有一个排列&#xff0c;能表示A[i]和B[i]相邻 &#xff08;2&#xff09;思路 考虑如果有环&#xff0c;显然不能满足排列&#xff0c;因为排列中度数最多为2&#xff0c;若有超过2的显…...

【Python】map

map()函数是Python内置函数之一&#xff0c;它的主要作用是将一个函数应用于可迭代对象中的每个元素&#xff0c;并返回一个包含结果的迭代器。 map()函数的语法如下&#xff1a; map(function, iterable)function参数是一个函数&#xff0c;表示要应用于可迭代对象每个元素的…...

Swift 5.9 与 SwiftUI 5.0 中新 Observation 框架应用之深入浅出

0. 概览 Swift 5.9 一声炮响为我们带来全新的宏&#xff08;Macro&#xff09;机制&#xff0c;也同时带来了干霄凌云的 Observation 框架。 Observation 框架可以增强通用场景下的使用&#xff0c;也可以搭配 SwiftUI 5.0 而获得双剑合璧的更强威力。 在本篇博文&#xff0c…...

【已解决】在 Vite 项目中使用 eslint-config-ali 时遇到的解析错误

错误还原 搭建 Vite 项目 pnpm create vite my-vue-app --template vue-ts安装 eslint-config-ali pnpm i -D eslint-config-ali typescript-eslint/parser typescript-eslint/eslint-plugin eslint-plugin-import eslint-import-resolver-typescript vue-eslint-parser esl…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi&#xff0c;还有多少人在用&#xff1f; 去年&#xff0c;月之暗面创始人杨植麟别提有多风光了。90后清华学霸&#xff0c;国产大模型六小虎之一&#xff0c;手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水&#xff0c;单月光是投流就花费2个亿。 疯…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor

1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...