STM32-SPI和W25Q64

本内容基于江协科技STM32视频学习之后整理而得。

文章目录

  • 1. SPI(串行外设接口)通信
    • 1.1 SPI通信简介
    • 1.2 硬件电路
    • 1.3 移位示意图
    • 1.4 SPI时序基本单元
    • 1.5 SPI时序
      • 1.5.1 发送指令
      • 1.5.2 指定地址写
      • 1.5.3 指定地址读
  • 2. W25Q64
    • 2.1 W25Q64简介
    • 2.2 硬件电路
    • 2.3 W25Q64框图
    • 2.4 Flash操作注意事项
    • 2.5 手册指令集
  • 3. SPI外设简介
    • 3.1 SPI框图
    • 3.2 SPI基本结构
    • 3.3 主模式全双工连续传输
    • 3.4 非连续传输
    • 3.5 软件 / 硬件波形对比
    • 3.6 库函数

1. SPI(串行外设接口)通信

1.1 SPI通信简介

  • SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
  • 四根通信线:SCK(Serial Clock)串行时钟线、MOSI(Master Output Slave Input)主机输出从机输入、MISO(Master Input Slave Output)主机输入从机输出、SS(Slave Select)从机选择
  • 同步,全双工(数据的发送和接收单独用一条线)
  • 支持总线挂载多设备(一主多从)

1.2 硬件电路

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起
  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚
  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

image.png

  • SCK时钟线由主机控制,对主机来说,时钟线为输出,对所有从机来说,时钟线为输入;
  • MOSI:主机是MO,主机输出,从机输入。数据通过MOSI线由主机输出,从机输入。
  • MISO:主机输入从机输出。三个从机通过MISO输出,主机通过MISO输入。当从机的SS引脚是高电平时,它的MISO引脚,必须切换为高阻态,相当于引脚断开,不输出任何电平。这样就可以防止,一条线有多个输出,而导致的电平冲突问题。在SS为低电平时,MISO才允许变为推挽输出。
  • SS线低电平有效。

1.3 移位示意图

image.png

  • 移位寄存器有一个时钟输入端,SPI一般都是高位先行的,所以,每来一个时钟,移位寄存器都会向左进行移位。移位寄存器的时钟源是由主机提供的,这里叫做波特率发生器,它产生的时钟驱动主机的移位寄存器进行移位。同时,这个时钟也通过SCK引脚进行输出,接到从机的移位寄存器里。
  • 主机移位寄存器左边移出去的数据通过MOSI引脚,输入到从机移位寄存器的右边。从机移位寄存器左边移出去的数据,通过MISO引脚,输入到主机移位寄存器的右边。
  • 波特率发生器时钟的上升沿,所有移位寄存器向左移动一位,移出去的位放到引脚上。波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位。
  • SPI通信的基础是交换一个字节,可以实现发送一个字节、接收一个字节、发送同时接收一个字节。

1.4 SPI时序基本单元

  • 起始条件:SS从高电平切换到低电平
  • 终止条件:SS从低电平切换到高电平

image.png

  • 交换一个字节(模式0)

  • CPOL=0:空闲状态时,SCK为低电平

  • CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

    • CPOL(Clock Polarity)时钟极性
    • CPHA(Clock Phase)时钟相位:决定是第一个时钟采样移入还是第二个时钟采样移入,
      image.png
  • 交换一个字节(模式1)

  • CPOL=0:空闲状态时,SCK为低电平

  • CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据

    • SS为高电平时,MISO为高阻态。SS下降沿之后,从机的MISO被允许开启输出;SS上升沿之后,从机的MISO必须置回高阻态。
    • SCK上升沿时,主机和从机同时移出数据,主机通过MOSI移出最高位,此时MOSI的电平就表示了主机要发送数据的B7;从机通过MISO移出最高位,MISO的电平就表示了从机要发送数据的B7,时钟运行产生下降沿,此时主机和从机同时移入数据,也就是进行数据采样,主机移出的B7进入从机移位寄存器的最低位,从机移出的B7进入主机移位寄存器的最低位。这样,一个时钟脉冲产生完毕,一个数据位传输完毕。当主机和从机完成了一个字节的数据交换后,如果主机只想交换一个字节,那这时可以置SS为高电平,结束通信。在SS的上升沿,MOSI还可以再变化一次,将MOSI置到一个默认的高电平或低电平,但MISO,从机必须置回高组态,如果主机的MISO为上拉输入的话,则MISO引脚的电平就是默认的高电平,如果主机MISO为浮空输入,则MISO引脚的电平不确定。
      image.png
  • 交换一个字节(模式2)

  • CPOL=1:空闲状态时,SCK为高电平

  • CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

image.png

  • 交换一个字节(模式3)
  • CPOL=1:空闲状态时,SCK为高电平
  • CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据

image.png

1.5 SPI时序

1.5.1 发送指令

  • 发送指令
  • 向SS指定的设备,发送指令(0x06)。0x06是写使能指令,

SPI采用指令码加读写数据的模型。SPI起始后,第一个交换发送给从机的数据一般叫做指令码,在从机中,对应的会定义一个指令集,当需要发送什么指令时,就可以在起始后第一个字节,发送指令集里面的数据,这样就能指导从机完成相应的功能了。不同的指令,可以有不同的数据个数。有的指令,只需要一个字节的指令码就可以完成。而有的指令,后面就需要再跟要读写的数据。

image.png

1.5.2 指定地址写

  • 指定地址写
  • 向SS指定的设备,发送写指令(0x02),随后在指定地址(Address[23:0])下,写入指定数据(Data)

image.png

1.5.3 指定地址读

  • 指定地址读
  • 向SS指定的设备,发送读指令(0x03),随后在指定地址(Address[23:0])下,读取从机数据(Data)

image.png

2. W25Q64

2.1 W25Q64简介

  • W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景

  • 存储介质:Nor Flash(闪存)

  • 时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)

  • 存储容量(24位地址):

    W25Q40: 4Mbit / 512KByte
    W25Q80: 8Mbit / 1MByte
    W25Q16: 16Mbit / 2MByte
    W25Q32: 32Mbit / 4MByte
    W25Q64: 64Mbit / 8MByte
    W25Q128: 128Mbit / 16MByte
    W25Q256: 256Mbit / 32MByte

2.2 硬件电路

image.png

  • CS:低电平有效。
  • WP:写保护,配合内部的寄存器配置,可以实现硬件的写保护。低电平有效,WP接低电平,保护住,不让写;WP接高电平,不保护,可以写。
  • C1:滤波;R1和D1电源指示灯,接通电源就亮。

2.3 W25Q64框图

image.png

  • 存储器以字节为单位,每个字节都有唯一的地址。W25Q64的地址宽度是24位,3个字节。24位地址,最大寻址范围是16MB,该芯片只有8MB,所以地址空间只用了一半。8MB的空间排到最后一个字节就是7F FF FF。
  • 在整个空间中以64KB为一个基本单元,划分为若干的块Block,8*1024/64=128块。每一块再进行更细的划分,以4KB进行划分,分为16个扇区Sector。页是256个字节,一个扇区是4KB,以256个字节划分,得到4*1024/256=16页。每一行为一页,一页内的地址变化,仅限于地址的最低一个字节。
  • 控制逻辑就是整个芯片的管理员,控制逻辑左边是SPI的通信引脚,这些引脚与主控芯片进行连接,主控芯片通过SPI协议,把指令和数据发给控制逻辑,控制逻辑就会自动去操作内部电路来完成想要的功能。
  • 控制逻辑上面的状态寄存器,比如芯片是否处于忙状态、是否写使能、是否写保护等都可以在这个状态寄存器里体现。
  • 写控制逻辑与外部的WP引脚相连,是配合WP引脚实现硬件写保护的。
  • 高电压生成器:是配合Flash进行编程的,因为Flash是掉电不丢失的,所以需要一个高压源。
  • 页地址锁存/计数器、字节地址锁存/计数器:用来指定地址的,
  • 通过SPI总共发过来3个字节的地址。因为一页是256字节,所以一页内的字节地址就取决于最低一个字节,而高位的2个字节就对应的是页地址。
  • 所以发过来的3个字节的前2个字节会进到页地址锁存计数器里,最后一个字节会进到字节地址锁存计数器里。页地址通过写保护和行解码来选择要操作哪一页。字节地址通过这个列解码和256字节页缓存来进行指定字节的读写操作。又因为地址锁存都是有一个计数器的,所以这个地址指针在读写之后可以自动加1,因此可以实现从指定地址开始,连续读写多个字节的目的。
    256字节的页缓存区是一个256字节的RAM存储器,读写是通过这个RAM缓存区来进行的,写入的数据会先放到缓存区里,然后在时序结束后,芯片再将缓存区的数据复制到对应的Flash里,进行永久保存。
    为什么数据要先进入缓存区呢?是因为SPI写入的频率是非常高的,

2.4 Flash操作注意事项

写入操作时:

  • 写入操作前,必须先进行写使能
  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除,擦除后,所有数据位变为1
  • 擦除必须按最小擦除单元(4096个字节)进行
  • 连续写入多字节时,最多写入一页(256字节(RAM缓存区))的数据,超过页尾位置的数据,会回到页首覆盖写入
  • 写入操作结束后,芯片进入忙状态,不响应新的读写操作

读取操作时:

  • 直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

2.5 手册指令集

  • Write Enable 写使能:06,先起始,再交换一个字节,第一个字节是发送方向,发送0x06指令
  • Write Disable写失能:04,起始,交换字节发送指令码04,终止。
  • Read Status Register-1 读状态寄存器1:05,起始,交换字节发送指令码05,要读数据,继续交换字节,通过交换读取一个字节,该字节就是状态寄存器的S7-S0,S0是BUSY位,S1是WEL位,主要用来查看忙状态的
  • Page Program页编程:02,就是写数据,起始、交换字节发送指令02,然后继续交换发送地址的23-16位、15-8位、7-0位,这三个字节用来指定地址,再之后,就可以写入数据D7-D0,该数据写入到刚才指定的地址下。如果继续交换写入的话,后续的字节就从起始地址开始依次存储,
    Sector Erase(4KB)扇区擦除:20,起始,交换字节发送指令20,之后再交换发送3个字节的地址,终止。发送之后,这个指定地址所在的扇区就会被整个擦除。
  • JEDEC ID 读取ID号:9F,起始,交换发送9F,随后继续交换读取3个字节,终止。第一个字节是厂商ID,后两个字节是设备ID,
  • Read Data 读取数据:03,起始,交换发送指令03,之后交换发送3个字节的地址,再之后交换读取数据,该数据是3个字节地址下的数据。再继续读取,后面数据就是从指定地址开始依次读存储的数据。

3. SPI外设简介

  • STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
  • 可配置8位/16位数据帧、高位先行/低位先行
  • 时钟频率:fPCLK / 分频系数 = fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)
    • APB2的PCLK是72MHz,APB1的PCLK是36MHz。
  • 支持多主机模型、主或从操作
  • 可精简为半双工/单工通信
  • 支持DMA
  • 兼容I2S协议
  • STM32F103C8T6 硬件SPI资源:SPI1(挂载在APB2)、SPI2(挂载在APB1)

3.1 SPI框图

image.png

  • 移位寄存器:右边的数据低位一位一位地从MOSI移出去,
    MISO的数据一位一位地移入到左边的数据高位。
  • LSBFIRST是控制低位先行还是高位先行,给0,先发送MSB即高位,给1,先发送LSB即低位
    MOSI与MISO的交叉方框是主要用来进行主从模式引脚变换的。这个SPI外设可以做主机也可以做从机,做主机时,这个交叉就不用,MOSI为MO,主机输出;MISO为MI,主机输入。STM32做从机时,MOSI为SI,从机输入,走交叉路线输入到移位寄存器,MISO为SO,从机输出,也走交叉路线,移位寄存器输出到MISO。
  • 接收缓冲区就是接收数据寄存器RDR,发送缓冲区实际上就是发送数据寄存器TDR。TDR和RDR占用同一个地址,统一叫做DR。当要发送一系列数据流时,数据写入发送缓冲区,当移位寄存器没有数据移位时,发送缓冲区的数据会立刻转入移位寄存器,开始移位。这个转入时刻会置状态寄存器的TXE为1,表示发送寄存器空。当检查到TXE为1时,下一个数据,就可以提前写入到TDR里了,一旦上个数据发完,下一个数据就可以立刻跟进,实现不间断的连续传输。移位寄存器一旦有数据进来了,就会自动产生时钟,将数据移出去,在移出去的过程中,MISO的数据也会移入,一旦数据移出完成,数据移入也完成。这时,移入的数据就会整体的从移位寄存器转入到接收缓冲区RDR,这个时刻会置状态寄存器的RXNE为1,表示接收寄存器非空。当检查RXNE置1后,就要尽快把数据从RDR读出来,在下一个数据到来之前,读出RDR,可以实现连续接收。否则,如果下一个数据已经收到了,上一个数据还没从RDR读出来,那么RDR的数据就会被覆盖,就不能实现连续的数据流了。
  • 波特率发生器用来产生SCK时钟的,内部主要是一个分频器。
  • CR1寄存器的三个位BR0、BR1、BR2,用来控制分频系数。
  • SPE是SPI使能,就是SPI_Cmd函数配置的位。
  • BR配置波特率,就是SCK时钟频率。
  • MSTR配置主从模式,1是主模式,0是从模式。
  • CPOL和CPHA用来选择SPI的4种模式。
  • SR寄存器:TXE为发送寄存器空,RXNE为接收寄存器非空
  • CR2寄存器:主要是使能位,如中断使能、DMA使能
  • NSS:SS就是从机选择,低电平有效,所以这里前面加了个N。

3.2 SPI基本结构

image.png

3.3 主模式全双工连续传输

image.png
示例使用SPI模式3。

  • SCK默认是高电平,在第一个下降沿,MOSI和MISO移出数据。上升沿移入数据。
  • SS置低电平开始时序,在刚开始时,TXE为1,表示TDR空,
  • 可以写入数据,指示就是软件写入0xF1至SPI_DR,0xF1就是要发送的第一个数据,写入之后TDR(发送缓冲器)变为0xF1,同时TXE=0,此时,TDR是等候区,移位寄存器才是真正的发送区。等候区TDR中的0xF1就会立刻转入移位寄存器,开始发送。转入瞬间置TXE标志为1,表示发送寄存器空。然后移位寄存器有数据了,波形就自动开始生成 (MISO/MOSI(输出)),数据F1的波形就开始产生了,在移位产生F1波形的同时,等候区TDR是空的,为了移位完成时,下一个数据能不间断地跟随,这里就要提早把下一个数据写入到TDR里等着了,
  • 写入F1后,软件等待TEX=1,然后写入0xF2至SPI_DR。写入之后,TDR的内容变成F2了。然后F1数据波形产生完毕后,F2转入移位寄存器开始发送,这时TXE=1,就尽快把下一个数据F3放到TDR里等着(软件等待TEX=1,然后写入0xF3至SPI_DR).如果只想发送3个数据,F3转入移位寄存器之后,TXE=1,就不需要再继续写入了。在最后一个TXE=1之后,还要继续再等待一段时间,F3的波形才能完整发送完,等波形完全发送完之后,BUSY标志由硬件清除,这才表示波形发送完了。
  • SPI是全双工,发送的同时,还有接收。
  • 在第一个字节发送完成后,第一个字节的接收也完成了。接收到的数据1是A1,这时移位寄存器的数据整体转入RDR,RDR随后存储的就是A1。转入的同时RXNE标志位也置1,表示收到数据了(软件等到RXNE=1,然后从SPI_DR读出A1),接收之后,软件清除RXNE标志位,当下一个数据A2收到后,RXNE重新置1。当监测到RXNE=1时,就继续读出RDR,即第二个数据A2。在最后一个字节时序完全产生之后,数据3才能收到。一个字节波形收到后,移位寄存器的数据自动转入RDR,会覆盖原有的数据,所以读取RDR要及时。

3.4 非连续传输

image.png
模式3,SCK默认高电平。如果你检测到TXE=1了,TDR为空,就软件写入0xF1至SPI_DR,这时TDR的值变为F1,TXE变为0,目前移位寄存器也是空,F1会立刻转入移位寄存器开始发送,波形产生,并且TXE置1,表示可以把下一个数据放在TDR里候着了。等到第一个字节时序结束,也就是第一个字节接收完成,这时接收的RXNE置1,先把第一个接收到的数据读出来,之后再写入下一个字节数据(软件等待TXE=1,但是较晚写入0xF2至SPI_DR),之后数据2开始发送,等先把接收的数据2收着,再继续写入数据3。数据3时序结束后,再接收数据3置换回来的数据。
1、 等待TXE=1;2. 写入发送的数据至TDR,3. 等待RXNE=1,4. 读取RDR接收的数据。之后交换第二个字节,重复该4步。

3.5 软件 / 硬件波形对比

image.png

3.6 库函数

// 恢复缺省配置
void SPI_I2S_DeInit(SPI_TypeDef* SPIx);
// 初始化
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
// 结构体变量初始化
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);
// 外设使能
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
// 中断使能
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
// DMA使能
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
// 写DR数据寄存器
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
// 读DR数据寄存器
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

// 可以获取TXE和RXNE标志位的状态
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);



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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JVM系列】Full GC(完全垃圾回收)的原因及分析

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【小沐学Python】在线web数据可视化Python库:Bokeh

文章目录 1、简介2、安装3、测试3.1 创建折线图3.2 添加和自定义渲染器3.3 添加图例、文本和批注3.4 自定义您的绘图3.5 矢量化字形属性3.6 合并绘图3.7 显示和导出3.8 提供和筛选数据3.9 使用小部件3.10 嵌入Bokeh图表到Flask应用程序 结语 1、简介 https://bokeh.org/ https…

从0到1:培训老师预约小程序开发笔记二

背景调研 培训老师预约小程序: 教师和学生可以更便捷地安排课程,并提升教学质量和学习效果,使之成为管理和提升教学效果的强大工具。培训老师可以在小程序上设置自己的可预约时间,学员可以根据老师的日程安排选择合适的时间进行预…

【HICE】dns正向解析

1.编辑仓库 2.挂载 3.下载软件包 4.编辑named.conf 5.编辑named.haha 6.重启服务 7.验证本地域名是否解析

Mysql 数据库主从复制-CSDN

查询两台虚拟机的IP 主虚拟机IP 从虚拟机IP服务 修改对应的配置文件 查询对应配置文件的命令 find / -name my.cnf编辑对应的配置文件 主 my.cnf (部分配置) [mysqld] ########basic settings######## server_id 1 log_bin /var/log/mysql/mysql-…

leetcode 709. 转换成小写字母

leetcode 709. 转换成小写字母 题解 class Solution { public:string toLowerCase(string s) {string ans;for (int i 0; i < s.size(); i) {if (s[i] > A && s[i] < Z) {s[i] 32;}ans s[i];}return ans;} };

室内定位可视化:精准导航与实时位置展示

通过图扑室内定位可视化技术&#xff0c;提供精准的导航服务和实时位置展示&#xff0c;帮助用户高效找到目标地点&#xff0c;提升空间管理和资源配置的效率与体验。

【昇思25天学习打卡营打卡指南-第十九天】基于MobileNetv2的垃圾分类

CycleGAN图像风格迁移互换 模型介绍 模型简介 CycleGAN(Cycle Generative Adversarial Network) 即循环对抗生成网络&#xff0c;来自论文 Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks 。该模型实现了一种在没有配对示例的情况下学习…

go语言的异常处理机制

error 在go语言中&#xff0c;异常被定义为实现了error接口的类型&#xff0c;error接口只定义了一个返回string类型Error&#xff08;&#xff09;方法&#xff0c;任何实现了Error()方法的类型都可以被定义为异常&#xff0c;以下是一个自定义的异常类型&#xff1a; typ…

【零基础】学JS

喝下这碗鸡汤 “知识就是力量。” - 弗朗西斯培根 1.三元运算符 目标:能利用三元运算符执行满足条件的语句 使用场景:其实是比if双分支更简单的写法&#xff0c;可以使用三元表达式 语法&#xff1a;条件 ? 满足条件的执行代码 : 不满足条件执行的代码 接下来用一个小案例来展…

昇思25天学习打卡营第十四天|Pix2Pix实现图像转换

训练营进入第十四天&#xff0c;今天学的内容是Pix2Pix图像转换&#xff0c;记录一下学习内容&#xff1a; Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c…

读书笔记-《魔鬼经济学》

这是一本非常有意思的经济学启蒙书&#xff0c;作者探讨了许多问题&#xff0c;并通过数据找到答案。 我们先来看看作者眼中的“魔鬼经济学”是什么&#xff0c;再选一个贴近我们生活的例子进行阐述。 01 魔鬼经济学 中心思想&#xff1a;假如道德代表人类对世界运转方式的期…

Vue 3集成krpano 全景图展示

Vue 3集成krpano 全景图展示 星光云全景系统源码 VR全景体验地址 星光云全景VR系统 将全景krpano静态资源文件vtour放入vue项目中 导入vue之前需要自己制作一个全景图 需要借助官方工具进行制作 工具下载地址&#xff1a;krpano工具下载地址 注意事项&#xff1a;vuecli…

LRU缓存算法设计

LRU 缓存算法的核⼼数据结构就是哈希链表&#xff0c;双向链表和哈希表的结合体。这个数据结构⻓这样&#xff1a; 创建的需要有两个方法&#xff0c;一个是get方法&#xff0c;一个是put方法。 一些问题&#xff1a;为什么需要使用双向链表呢&#xff1f;因为删除链表的本身&…

2-26 基于matlab开发的制冷循环模型

基于matlab开发的制冷循环模型。Simscape两相流域中的制冷循环模型&#xff0c;在simulink中完成多循环温度控制。程序已调通&#xff0c;可直接运行。 2-26 制冷循环模型 Simscape两相流域 - 小红书 (xiaohongshu.com)

Web3D引擎,three.js堪称扛把子,Babylon.js差点意思。

涉及到Web3D开发&#xff0c;Three.js和Babylon.js是两个备受推崇的引擎。它们都是基于WebGL的开源3D引擎&#xff0c;用于创建交互式的3D图形应用程序&#xff0c;但要细论起来&#xff0c;three.js普及度远超Babylon .js. 一、二者的介绍 Three.js&#xff1a; Three.js 是一…

Android仿今日头条新闻(一)

新建一个侧边栏的文件&#xff0c;创建成功后直接运行。可以看到带滑动的侧边栏功能如图所示&#xff1a; 主体UI&#xff1a; 新闻UI的实现: 侧边栏&#xff1a; 更换一下颜色&#xff1a; 学习参考-浩宇开发

Objects365数据集介绍

Objects365数据集介绍 什么是Objects365数据集&#xff1f;数据集的规模与内容数据集的特点数据集下载 什么是Objects365数据集&#xff1f; Objects365是一个大规模、高质量的物体检测数据集。该数据集旨在推动物体检测技术的发展&#xff0c;特别是在真实世界场景下的应用。O…

STM32-01 推挽输出-点亮LED

本文以STM32中点亮LED为例&#xff0c;解读推挽输出的原理 推挽输出介绍 所谓的推挽输出&#xff0c;就是通过控制输出控制模块&#xff0c;打开或者关闭P-MOS或者N-MOS。 ─ 推挽模式下&#xff1a;输出寄存器上的’0’激活N-MOS&#xff0c;而输出寄存器上的’1’将激活P-M…

尚品汇-(十三)

&#xff08;1&#xff09;查询sku列表 在ManageService 中添加 /*** SKU分页列表* param pageParam* return*/ IPage<SkuInfo> getPage(Page<SkuInfo> pageParam);接口实现类 Override public IPage<SkuInfo> getPage(Page<SkuInfo> pageParam) {Qu…