STM32_11(SPI)

一、SPI通信

  • SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
  • 四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)
  • MOSI:是主设备输出、从设备输入的数据信号线;、MISO:主设备输入、从设备输出的数据信号线; 
  • 同步,全双工
  • 支持总线挂载多设备(一主多从)

1. SPI硬件电路

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起
  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚
  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入
  • 主机只能选择一个从机,选择多个从机就会导致数据冲突。当从机的SS引脚为高电平,就是从机未被选中,它的MISO引脚必须切换为高阻态,也就是把引脚断开。这样就可以防止一条线有多个输出,而导致的电平冲突问题。

2. 移位示意图

        移位寄存器有一个时钟输入端,因为SPI都是高位先行,所以每来一个时钟,移位寄存器就会向左移位,从机的移位寄存器同理。移位寄存器的时钟源是由主机提供的,这里叫做波特率发生器,它产生的时钟驱动主机的移位寄存器进行移位。同时,这个时钟也通过SCK引脚进行输出,接到从机的移位寄存器里。主机移位寄存器左边移出去的数据通过MOSI引脚,输入到从机的移位寄存器的右边,从机移位寄存器的数据根据MISO输入到主机移位寄存器的右边。

        首先规定,波特率发生器时钟上升沿,所有移位寄存器向左移动一位,移出去的位放在引脚上,波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位。

3. SPI时序基本单元

① 起始条件和终止条件

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

② 模式0

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

总体来说,MOSI和MISO都提前SCK半个周期。

② 模式1

  • 交换一个字节(模式1)
  • CPOL=0:空闲状态时,SCK为低电平
  • CPHA=1(时钟相位:决定第一个时钟采样移入还是第二个时钟采样移入):SCK第一个边沿移出数据,第二个边沿移入数据

        SS高电平时,MISO用一条中间的线表示高阻态,SS下降沿之后,从机的MISO被允许开启输出。SS上升沿之后,从机的MISO必须置回高阻态。当SCK为上升沿时,主机和从机同时移除数据,主机通过MOSI移除最高位,此时的MOSI的电平就表示主机要发送数据B7,从机通过MISO移除最高位,此时MISO就表示从机要发送数据B7。之后时钟运行,产生下降沿,此时的主机和从机需同时移入数据,也就是数据采样,这里主机移除B7,进入从机移位寄存器的最低位,从机移除B7,进去主机移位寄存器的最低位。一个时钟脉冲产生完毕,一位数据传输完毕。

③ SPI时序(发送指令)

        在这里我们使用的是模式0,首先SS是高电平,SCK是低电平。SS产生下降沿,时序开始,在下降沿时刻,MOSI和MISO就开始比变换数据,MOSI的指令码仍为0,所以保持低电平不变,MISO从机没有数据发给主机,引脚电平没有变换。从机采样输入,得到0,主机采样输入,得到1。之后主机要发送数据1,SCK下降沿,数据移出,主机将1移出到MOSI,MOSI变高电平。当主机发送0时候,SCK下降沿,MOSI变为0。SCK上升沿,数据采样,从机接收数据为0。总体来说,SCK低电平时变化时期,高电平时读取时期(下降沿变换数据,上升沿采样数据)。

        这个SPI时序代表,主机用0x06换来了从机的0xFF。

④ SPI时序(指定地址写)

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

⑤ SPI时序(指定地址读)

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

二、SPI外设

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

1. SPI框图

        首先,移位寄存器右边低位的数据一位一位地从MOSI移出,MISO的数据一位一位地以到做左边移位寄存器的数据高位。

        这个可以控制是低位先行还是高位先行。

        假如我们需要连续发送一串数据,第一个数据写入发送缓冲区(TDR),当移位寄存器没有数据移位时,TDR的数据就会立刻转入移位寄存器,开始移位,这个转入时刻,会置状态寄存器的TXE为1(表示发送寄存器空),紧接着,下一个数据就可以提前写入TDR等待,一旦上个数据发送完成,下一个数据就可以立刻跟进,实现不间断的连续传输。当数据到移位寄存器后,它就会自动产生时钟,将数据移出去,在移除的过程中,MISO数据也会移入。一旦数据移除完成,数据移入也完成。这时,移入的数据就整体从移位寄存器转入到接收缓冲区RDR,这时会将状态寄存器RXNE置1(表示接收寄存器非空)。当我们检测RXNE置1后,就需要尽快把数据从RDR读出来,在下个数据来之前就可以读出RDR ,实现连续接收。

2. SPI基本结构

3. 主模式全双工连续传输(效率更高)

4. 非连续传输(代码友好)

步骤:

1、等待TXE置1;

2、写入数据到TDR寄存器;

3、等待RXNE为1;

4、读取RDR接收的数据。

三、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

1. W25Q64硬件电路图

 

 

        /CS(/代表低电平有效或者CS上面有一横线也是低电平有效。

        这里的CS对应SS,DI对应MOSI,DO对应MISO。

2. Flash操作注意事项

  • 写入操作时:
  • 写入操作前,必须先进行写使能
  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除,擦除后,所有数据位变为1
  • 擦除必须按最小擦除单元进行(最小的擦除单元是一个扇区4096字节,最大的能把全部擦除)
  • 连续写入多字节时,最多写入一页(256字节)的数据,超过页尾位置的数据,会回到页首覆盖写入
  • 写入操作结束后,芯片进入忙状态,不响应新的读写操作
  • 读取操作时:直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

四、代码部分

1. SPI软件配置代码

#include "Bsp_SPI.h"/* SS写数据 */
void Bsp_SPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}/* SCK写数据 */
void Bsp_SPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}/* MOSI写数据 */
void Bsp_SPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}/* MISO读数据 */
uint8_t Bsp_SPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}/* SPI初始化 */
void Bsp_SPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_Init(GPIOA, &GPIO_InitStructure);Bsp_SPI_W_SS(1);Bsp_SPI_W_SCK(0);}/* SPI起始 */
void Bsp_SPI_Start(void)
{Bsp_SPI_W_SS(0);
}/* SPI终止 */
void Bsp_SPI_Stop(void)
{Bsp_SPI_W_SS(1);
}/* MOSI和MISO交换字节 */
/* 模式0 */
uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{uint8_t ByteReceive = 0x00;for (uint8_t i = 0; i < 8; i++){Bsp_SPI_W_MOSI(ByteSend & (0x80 >> i));Bsp_SPI_W_SCK(1);if (Bsp_SPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}Bsp_SPI_W_SCK(0);}return ByteReceive;
}/* 模式1 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{uint8_t ByteReceive = 0x00;for (uint8_t i = 0; i < 8; i++){Bsp_SPI_W_SCK(1);Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));Bsp_SPI_W_SCK(0);if (Bsp_SPI_R_MISO == 1){ByteReceive |= (0x80 >> i);}}return ByteReceive;
}*//* 模式3 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{uint8_t ByteReceive = 0x00;for (uint8_t i = 0; i < 8; i++){Bsp_SPI_W_SCK(0);Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));Bsp_SPI_W_SCK(1);if (Bsp_SPI_R_MISO == 1){ByteReceive |= (0x80 >> i);}}return ByteReceive;
}*//* 模式2 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{uint8_t ByteReceive = 0x00;for (uint8_t i = 0; i < 8; i++){Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));Bsp_SPI_W_SCK(0);if (Bsp_SPI_R_MISO == 1){ByteReceive |= (0x80 >> i);}Bsp_SPI_W_SCK(1);}return ByteReceive;
}*/

2. W25Q64地址封装

#ifndef __W25Q64_INS_H
#define __W25Q64_INS_H#define W25Q64_WRITE_ENABLE                         0x06
#define W25Q64_WRITE_DISABLE                        0x04
#define W25Q64_READ_STATUS_REGISTER_1               0x05
#define W25Q64_READ_STATUS_REGISTER_2               0x35
#define W25Q64_WRITE_STATUS_REGISTER                0x01
#define W25Q64_PAGE_PROGRAM                         0x02
#define W25Q64_QUAD_PAGE_PROGRAM                    0x32
#define W25Q64_BLOCK_ERASE_64KB                     0xD8
#define W25Q64_BLOCK_ERASE_32KB                     0x52
#define W25Q64_SECTOR_ERASE_4KB                     0x20
#define W25Q64_CHIP_ERASE                           0xC7
#define W25Q64_ERASE_SUSPEND                        0x75
#define W25Q64_ERASE_RESUME                         0x7A
#define W25Q64_POWER_DOWN                           0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE                0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET           0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID     0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID               0x90
#define W25Q64_READ_UNIQUE_ID                       0x4B
#define W25Q64_JEDEC_ID                             0x9F
#define W25Q64_READ_DATA                            0x03
#define W25Q64_FAST_READ                            0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT                0x3B
#define W25Q64_FAST_READ_DUAL_IO                    0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT                0x6B
#define W25Q64_FAST_READ_QUAD_IO                    0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO              0xE3#define W25Q64_DUMMY_BYTE                           0xFF                // 空地址,代表没用的地址,因为在传输过程中总会只有发送或只有接收的时候#endif

3. 软件SPI读取W25Q64

#include "Bsp_W25Q64.h"void W25Q64_Init(void)
{Bsp_SPI_Init();
}/* 读取ID */
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_JEDEC_ID);               // 发送0x9F指令码*MID = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);      // 返回制造厂商ID*DID = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);      // 返回设备ID的高8位*DID <<= 8;                         *DID |= Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);     // 返回设备ID的低8位Bsp_SPI_Stop();
}/* 使能 */
void W25Q64_WriteEnable(void)
{Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_WRITE_ENABLE);         Bsp_SPI_Stop();
}/* 读状态寄存器1(主要读取BUSY位,判断是否在忙) */
void W25Q64_WaitBusy(void)
{uint32_t TimeOut = 100000;Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);   while ((Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)        // 判断状态寄存器1的最低位,也就是BUSY位是否在忙。0:忙     1:在忙{TimeOut--;if (TimeOut == 0){break;}}Bsp_SPI_Stop();
}/* 页编程 */
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataAarry, uint16_t Length)
{W25Q64_WriteEnable();                       // 使能Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_PAGE_PROGRAM);Bsp_SPI_SwapByte(Address >> 16);Bsp_SPI_SwapByte(Address >> 8);Bsp_SPI_SwapByte(Address);for (uint16_t i = 0; i < Length; i++){Bsp_SPI_SwapByte(DataAarry[i]);}Bsp_SPI_Stop();W25Q64_WaitBusy();
}/* 扇区擦除 */
void W25Q64_SectorErase(uint32_t Address)
{W25Q64_WriteEnable();                       // 使能Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);Bsp_SPI_SwapByte(Address >> 16);Bsp_SPI_SwapByte(Address >> 8);Bsp_SPI_SwapByte(Address);Bsp_SPI_Stop();W25Q64_WaitBusy();
}/* 读数据 */
void W25Q64_ReadData(uint32_t Address, uint8_t *DataAarry, uint32_t Length)
{Bsp_SPI_Start();Bsp_SPI_SwapByte(W25Q64_READ_DATA);Bsp_SPI_SwapByte(Address >> 16);Bsp_SPI_SwapByte(Address >> 8);Bsp_SPI_SwapByte(Address);for (uint32_t i = 0; i < Length; i++){DataAarry[i] = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);}Bsp_SPI_Stop();
}

4. 硬件SPI读取W25Q64

#include "Bsp_SPI.h"/* SS写数据 */
void Bsp_SPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}/* SPI初始化 */
void Bsp_SPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_InitTypeDef SPI_InitStructure;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;                    // 分频系数,分频越高速度越快(注意:SPI1是72M,SPI2是36M。因为SPI1是在APB2,SPI2是在APB1)SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                            // 选择第一个边沿采样还是第二个边沿采样SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                              // 时钟极性:因为在这里选择模式0SPI_InitStructure.SPI_CRCPolynomial = 7;                                                // CRC校验多项式,默认值7SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                       // 8位数据帧SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                      // 双线全双工模式SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                      // 高位先行SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                           // 选择向前设备时SPI主机SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                               // NSS引脚,一般没用到选择软件NSSSPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);Bsp_SPI_W_SS(1);}/* SPI起始 */
void Bsp_SPI_Start(void)
{Bsp_SPI_W_SS(0);
}/* SPI终止 */
void Bsp_SPI_Stop(void)
{Bsp_SPI_W_SS(1);
}/* MOSI和MISO交换字节 */
/* 模式0 */
uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{uint32_t TimeOut = 10000;uint8_t ByteReceive;while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != 1){TimeOut--;if (TimeOut == 0){break;} }SPI_I2S_SendData(SPI1, ByteSend);TimeOut = 10000;while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != 1){TimeOut--;if (TimeOut == 0){break;} }ByteReceive = SPI_I2S_ReceiveData(SPI1);return  ByteReceive;
}

5. 主程序

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Bsp_W25Q64.h"uint8_t MID;
uint16_t DID;
uint8_t ArrayWrite[] = {0x11, 0x22, 0x33, 0x44};
uint8_t ArrayRead[4];int main(void)
{OLED_Init();                        W25Q64_Init();/* 显示厂商和设备ID号 */OLED_ShowString(1, 1, "MID:    DID:");OLED_ShowString(2, 1, "W:");OLED_ShowString(3, 1, "R:");W25Q64_ReadID(&MID, &DID);OLED_ShowHexNum(1, 5, MID, 2);OLED_ShowHexNum(1, 13, DID, 4);W25Q64_SectorErase(0x000000);                    // 只要末尾3个十六进制数为0,那肯定是扇区的起始地址(不擦除,掉电不丢失)。如果不擦除则改写则会数据出错,因为只能1变0不能0变1的操作所以修改数据前得擦除。W25Q64_PageProgram(0x00000, ArrayWrite, 4);      // 写入数据ArrayWrite,并且写入的数据不能跨页W25Q64_ReadData(0x000000, ArrayRead, 4);         // 读数据/* 显示写入数据 */OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);/* 显示读出数据 */OLED_ShowHexNum(3, 3, ArrayRead[0], 2);OLED_ShowHexNum(3, 6, ArrayRead[1], 2);OLED_ShowHexNum(3, 9, ArrayRead[2], 2);OLED_ShowHexNum(3, 12, ArrayRead[3], 2);while (1){}
}

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

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

相关文章

还在愁没项目?来瞧瞧这些另类赚钱方式

客套话不多说&#xff0c;直接上案例&#xff0c;这些都是正儿八经的真实案例&#xff0c;相信大家通过这些人的案例自然能摸索整理出一套属于自己的项目&#xff01;摸索不出&#xff0c;也多多少少能受一些灵感上的启发。 小A是长期混B站的&#xff0c;大家称他为“B站搬运工…

C++ 通过SQLite实现命令行工具

本文介绍了一个基于 C、SQLite 和 Boost 库的简单交互式数据库操作 Shell。该 Shell 允许用户通过命令行输入执行各种数据库操作&#xff0c;包括添加、删除主机信息&#xff0c;设置主机到特定主机组&#xff0c;以及显示主机和主机组列表。通过调用 SQLite3 库实现数据库连接…

【网络安全】meterpreter攻击实战

1.meterpreter 攻击成功后可以做什么指令&#xff1f; 远程控制命令执行摄像头监控密码获取创建后门用户破坏篡改系统。 2.创建后门用户并开启远程连接&#xff1a; net user zhangsan 123456/add && net localgroup adminstrators zhangsan/add exit run getgul -…

拓数派荣获上海市“智慧工匠”工业软件创新案例奖

近日&#xff0c;由上海市经济和信息化委员会指导、上海市城市数字化转型应用促进中心主办、上海中创产业创新研究院承办的“工业软件赋能新型工业化”主题沙龙暨2023“智慧工匠”工业软件创新案例竞赛颁奖典礼在上海圆满落幕。拓数派凭借上汽集团工业数据管理服务平台案例成功…

ROS vscode使用基本配置

1、创建ros工作空间 2、启动 vscode 3、vscode 中编译 ros ctrl shift B 调用编译&#xff0c;选择:catkin_make:build 修改.vscode/tasks.json 文件 4、 创建 ROS 功能包 选定 src ---> create catkin package 依次设置包名、添加依赖 5、C 实现 在功能包的 src 下…

Yolov8训练数据集过程 + 测试测试集 + 继续训练+报错解决

做自己第一次使用Yolov8训练的记录 1、下载代码 官网的我没找到对应的视频教程&#xff0c;操作起来麻烦&#xff0c;一下这个链接的代码可以有对应bilibili教程&#xff1a;完整且详细的Yolov8复现训练自己的数据集 选择这个下载&#xff1a; 2、安装需要的包&#xff1a; …

扫码听音乐该如何制作?音乐的二维码生成方法

多个音频文件怎么做成一个二维码显示&#xff1f;二维码在现在的生活中拥有丰富的使用场景&#xff0c;可以用来作为多种内容类型的载体&#xff0c;比如音频二维码就是经常被使用的一种二维码类型。通过扫秒二维码来听音频文件&#xff0c;更加的灵活方便&#xff0c;那么音频…

MySQL C代码连接

环境&#xff1a;5.7.42-0ubuntu0.18.04.1 (Ubuntu) mysql接口介绍 初始化mysql指针 用来生成MySQL对象&#xff0c;返回值为MySQL*&#xff0c;MySQL*是MySQL对象的指针。 MySQL在mysql.h中是一个结构体 链接数据库 初始化完毕之后&#xff0c;必须先链接数据库&#xff…

安防监控系统的工作原理是什么?具体包含哪些组成部分?

关于安防监控系统&#xff0c;大家熟知的就是监控系统平台&#xff0c;其实不然&#xff0c;智能视频安防监控系统涵盖的内容非常多&#xff0c;今天小编就和大家一起来探讨一下。 安防监控视频系统主要分为以下7大类&#xff1a; 1、 摄像头采集图像 安防监控系统通常使用摄…

11-30 SpringBoot

内嵌的tomcat tomcat的依赖 对于tomcat其实还是一个jar包 spring是一个IOC容器 tomcat的核心对象交给Spring容器 调用核心对象方法 启动Tomcat 1.添加依赖 tomcat-embed-core&#xff0c;叫做tomcat内嵌核心。就是这个东西把tomcat功能引入到了我们的程序中的 排除tomcat&a…

Nginx(无法解析PHP网页如何解决?FPM解决你的烦恼!)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

Android笔记(十六):前台服务

设置服务为前台服务。前台服务会在状态栏显示一个通知。通知界面与服务进行关联。 一、什么是通知&#xff1f; Notification通知是在移动应用APP提供给用户的消息提示&#xff0c;是在移动系统的通知栏中显示。当移动应用不在运行时或者在后台状态下&#xff0c;通过发布通知…

数据挖掘实战-基于word2vec的短文本情感分析(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

易点易动固定资产管理系统:提升企业固定资产管理效率的利器

固定资产是企业运营中重要的组成部分&#xff0c;对于企业的正常运转和发展至关重要。然而&#xff0c;传统的固定资产管理方法通常存在效率低下、信息不透明等问题。为了解决这些挑战&#xff0c;易点易动固定资产管理系统应运而生。本文将探讨易点易动固定资产管理系统的概念…

9款高效绘图神器,提升你的工作效率

在日常工作或生活中&#xff0c;我们必须绘制各种图表、流程图、思维导图等图形&#xff0c;或者想用画笔描述自己的想法。然而&#xff0c;我们在许多绘图软件面前感到困惑。我们不知道哪个绘图软件好&#xff0c;也没有足够的时间一一尝试 在接下来的空间里&#xff0c;我们…

堆栈_有效括号

题比较特殊&#xff0c;主要在于它的所有要输入&#xff0c;都是左括号开头&#xff0c;没有右括号开头的&#xff0c;比如"] ["&#xff0c;这种是不算为括号的&#xff0c;由于必然是对称的&#xff0c;若能符合&#xff0c;因而直接在遇到右括号时&#xff0c;检查…

基于python实现心血管疾病风险预测分析

一、项目简介 项目背景 利用心血管疾病风险预测数据集进行深入分析&#xff0c;探究不同因素与心血管疾病风险之间的关联。 数据源 Kaggle上的心血管疾病风险预测数据集。&#xff08;Cardiovascular Diseases Risk Prediction Dataset | Kaggle&#xff09; 二、数据预处…

视图层、模板(补充)

视图层 响应对象 响应---》本质都是 HttpResponse HttpResponse---》字符串render----》放个模板---》模板渲染是在后端完成 js代码是在客户端浏览器里执行的模板语法是在后端执行的redirect----》重定向 字符串参数不是是空的状态码是 3开头JsonResponse---》json格式数据 …

Moonbeam生态项目分析 — — DeFi借贷协议Moonwell

流动性激励计划Moonbeam Ignite是帮助用户轻松愉快体验Moonbeam生态的趣味活动。在Moonbeam跨链连接的推动下&#xff0c;DeFi的各种可能性在这里爆发。DeFi或许不热门&#xff0c;但总有机会捡漏&#xff0c;了解Monbeam生态项目&#xff0c;我们邀请Moonbeam大使分享他们的研…

【linux防火墙】设置开启路由转发,SNAT和DNAT转换原理及应用实操,添加自定义链归类iptables规则

目录 一、关于iptables规则的保存 1.1持久保存规则 1.2加载规则 1.3开机自动加载规则 1.4使用iptables-service软件来进行规则的保存和加载&#xff08;不建议使用&#xff09; 二、SNAT和DNAT的原理和应用 SNAT的原理与应用&#xff1a; DNAT的原理和应用&#xff1a; …