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

【STM32-学习笔记-9-】SPI通信

文章目录

  • SPI通信
    • Ⅰ、SPI通信概述
      • 1、SPI技术规格
        • 2、SPI应用
      • 3、硬件电路
        • 移位示意图
    • Ⅱ、SPI时序基本单元
      • ①、起始条件
      • ②、终止条件
      • ③、交换一个字节(模式0)
      • ④、交换一个字节(模式1)
      • ⑤、交换一个字节(模式2)
      • ⑥、交换一个字节(模式3)
    • Ⅲ、SPI时序
      • ①、发送指令
      • ②、指定地址写
      • ③、指定地址读
    • Ⅳ、W25Q64 - Nor Flash(闪存)
      • ①、硬件电路
      • ②、W25Q64框图
      • ③、Flash操作注意事项
      • ④、指令表
      • ⑤、电气特性表
      • ⑥、软件模拟SPI
        • 1>W25Q64.c
        • 2>W25Q64.h
        • 3>W25Q64_Ins.h
    • Ⅴ、硬件SPI(SPI外设)
      • 1、SPI外设简介
      • 2、SPI框图
      • 3、SPI基本结构
      • 4、主模式全双工连续传输
      • 5、非连续传输
    • Ⅵ、配置SPI外设
      • 1、SPI函数
      • 2、SPI_InitTypeDef结构体参数
        • ①、SPI_Mode
        • ②、SPI_Direction
        • ③、SPI_DataSize
        • ④、SPI_FirstBit
        • ⑤、SPI_BaudRatePrescaler
        • ⑥、SPI_CPOL
        • ⑦、SPI_CPHA
        • ⑧、SPI_NSS
        • ⑨、SPI_CRCPolynomial
      • 3、SPI的四种工作模式
      • 4、SPI外设
        • HardSPI.c

SPI通信

Ⅰ、SPI通信概述

SPISerial Peripheral Interface,串行外设接口)是一种高速、全双工、同步的通信总线,广泛应用于嵌入式系统与外围设备间的短距离通信。SPI由摩托罗拉公司在20世纪80年代中期开发,后逐渐发展成为行业规范。它采用主从模式,通常由一个主设备(Master)和一个或多个从设备(Slave)组成。主设备负责控制通信过程,包括时钟信号的生成、从设备的选择以及数据的发送与接收

1、SPI技术规格

  • SPI四根通信线
    • SCK(Serial Clock):时钟信号线,由主设备产生,用于同步数据传输
    • MOSI(Master Output, Slave Input):主设备输出、从设备输入的数据线
    • MISO(Master Input, Slave Output):主设备输入、从设备输出的数据线
    • CS/SS(Chip Select/Slave Select):从设备选择信号线,用于主设备选择与其通信的从设备(默认1
  • 工作模式:SPI有四种工作模式,由CPOL(时钟极性)和CPHA(时钟相位)定义。这决定了数据采样和发送的时钟边沿
  • 数据帧格式:通常为8位或16位,可以配置为MSB(高位在前)或LSB(低位在前)。
  • 传输速率:SPI支持较高的数据传输速率,通常能达到甚至超过10M/bps
  • 通信特点:全双工通信,可以同时发送和接收数据;同步通信,使用时钟信号来同步数据传输;连接简单,硬件结构简单
2、SPI应用
  • 存储器芯片:如EEPROM、SRAM、SPI Flash等,用于数据的高速读写和存储
  • 传感器:用于与各种传感器进行通信,获取传感器数据
  • 显示器:如液晶显示器和OLED显示器,传输图像数据和控制信号
  • 通信模块:如无线模块等,用于数据传输
  • 其他外设:如ADC、DAC等

3、硬件电路

image-20250108163022842

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起

  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚

  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

移位示意图

image-20250108170335243

Ⅱ、SPI时序基本单元

①、起始条件

SS从高电平切换到低电平

image-20250108170847890

②、终止条件

SS从低电平切换到高电平

image-20250108170914447

③、交换一个字节(模式0)

  • CPOL(时钟极性)=0:空闲状态时,SCK为低电平
  • CPHA(时钟相位)=0:SCK第一个边沿移入数据,第二个边沿移出数据
    • 由于SCK第一个边沿就要移入数据,因此在SCK之前,就要先将数据移出

image-20250108171658293

④、交换一个字节(模式1)

CPOL(时钟极性)=0:空闲状态时,SCK为低电平

CPHA(时钟相位)=1:SCK第一个边沿移出数据,第二个边沿移入数据

    • SCK上升沿时,MOSI和MISO都将数据移至数据寄存器中
    • 直到SCK下降沿时,
      • 主机移入数据寄存器中的最高位数据“B7”移入从机的最低位;
      • 从机移入数据寄存器中的最高位数据“B7”移入主机的最低位,从而完成数据交换

image-20250108171827304

⑤、交换一个字节(模式2)

CPOL(时钟极性)=1:空闲状态时,SCK为高电平

CPHA(时钟相位)=0:SCK第一个边沿移入数据,第二个边沿移出数据

image-20250108171910609

⑥、交换一个字节(模式3)

CPOL(时钟极性)=1:空闲状态时,SCK为高电平

CPHA(时钟相位)=1:SCK第一个边沿移出数据,第二个边沿移入数据

image-20250108171941946

Ⅲ、SPI时序

①、发送指令

  • 向SS指定的设备,发送指令(0x06)

image-20250108174857750

②、指定地址写

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

image-20250110110128634

③、指定地址读

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

image-20250110110155463

Ⅳ、W25Q64 - Nor Flash(闪存)

image-20250108175316341

①、硬件电路

image-20250109111414536

②、W25Q64框图

image-20250109112639477

  • W25Q64闪存芯片中有8Mbyte闪存空间,这些空间被划分为128Block 0~Block 127),每个块占有64kb

  • 每个块又被分成16扇区Sector 0~Sector 15),每个扇区占有4kb

  • 扇区又可以划分成16个,每页占有256byte

请添加图片描述

③、Flash操作注意事项

  • 写入操作时:

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

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

④、指令表

image-20250109152616615

⑤、电气特性表

image-20250109154933784

⑥、软件模拟SPI

#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
//模拟SPI
//输出:>SS:	PA4
//输出:>SCK:	PA5
//输出:>MOSI:	PA7
//输入:>MISO:	PA6void MySPI_W_SS(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}
void MySPI_W_SCK(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}
void MySPI_W_MOSI(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}
uint8_t MySPI_R_MISO(void) {return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}void MySPI_Init(void)
{//初始化GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_Init(GPIOA, &GPIO_InitStructure);//配置默认电平MySPI_W_SS(1);MySPI_W_SCK(0);//使用SPI模式0
}//起始条件-----SS从高电平切换到低电平
void MySPI_Start(void)
{MySPI_W_SS(0);
}//终止条件-----SS从低电平切换到高电平
void MySPI_Stop(void)
{MySPI_W_SS(1);
}//交换一个字节(模式0)
uint8_t MySPI_SwapByte_Mod0(uint8_t ByteSend)
{uint8_t	ByteReceive = 0;uint8_t	i = 0;for(i = 0;i < 8;i++){MySPI_W_MOSI(ByteSend & (0x80 >> i));MySPI_W_SCK(1);if(MySPI_R_MISO() == 1) {ByteReceive |= 0x80 >> i;}MySPI_W_SCK(0);}return ByteReceive;
}
方法2:使用移位模型
//uint8_t MySPI_SwapByte_Mod0(uint8_t ByteSend)
//{
//	uint8_t	ByteReceive = 0;
//	uint8_t	i = 0;
//	for(i = 0;i < 8;i++)
//	{
//		MySPI_W_MOSI(ByteSend & 0x80);
//		ByteSend <<= 1
//		MySPI_W_SCK(1);
//		if(MySPI_R_MISO() == 1) {ByteSend |= 0x01;}
//		MySPI_W_SCK(0);
//	}
//	return ByteSend;
//}//交换一个字节(模式1)
uint8_t MySPI_SwapByte_Mod1(uint8_t ByteSend)
{uint8_t	ByteReceive = 0;uint8_t	i = 0;for(i = 0;i < 8;i++){MySPI_W_SCK(1);MySPI_W_MOSI(ByteSend & (0x80 >> i));MySPI_W_SCK(0);if(MySPI_R_MISO() == 1) {ByteReceive |= 0x80 >> i;}}return ByteReceive;
}
1>W25Q64.c
#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
#include "W25Q64.h"
#include "W25Q64_Ins.h"void W25Q64_Init(void)
{MySPI_Init();
}//读取ID
void W25Q64_ReadID(W25Q64_ID_TypeDef* ID)
{MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_JEDEC_ID);ID->Manufacturer_ID = MySPI_SwapByte_Mod0(W25Q64_Dummy_BYTE);ID->Device_ID = MySPI_SwapByte_Mod0(W25Q64_Dummy_BYTE);ID->Device_ID <<= 8;ID->Device_ID |= MySPI_SwapByte_Mod0(W25Q64_Dummy_BYTE);MySPI_Stop();
}//W25Q64写使能
void W25Q64_W_Enable(void)
{MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_WRITE_ENABLE);MySPI_Stop();
}//W25Q64读状态寄存器1(判断是否处于忙状态)
void W25Q64_WaitBusy(void)
{uint32_t Timeout = 100000;MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_READ_STATUS_REGISTER_1);while((MySPI_SwapByte_Mod0(W25Q64_Dummy_BYTE) & 0x01) == 1){Timeout--;if(Timeout == 0){break;//超时退出}}MySPI_Stop();
}/*************************************************************************************** 名称				W25Q64_PageProgram* 功能				W25Q64页编程* 参数Addr			写入数据的地址* 参数DataArray	存放写入数据的数组* 参数Count		写入的数据数量*/
//Count <= 256  (256字节页面缓冲区)
void W25Q64_PageProgram(uint32_t Addr, uint8_t* DataArray, uint16_t Count)
{W25Q64_W_Enable();//写使能MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_PAGE_PROGRAM);//写入页编程指令MySPI_SwapByte_Mod0(Addr >> 16);//A23~A16MySPI_SwapByte_Mod0(Addr >> 8);	//A15~A8MySPI_SwapByte_Mod0(Addr);		//A7~A0	uint16_t i = 0;for(i = 0;i < Count;i++){MySPI_SwapByte_Mod0(DataArray[i]);}MySPI_Stop();W25Q64_WaitBusy();//等待忙状态
}//W25Q64扇区擦除(4KB)
void W25Q64_SectorErase(uint32_t Addr)
{W25Q64_W_Enable();//写使能MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_SECTOR_ERASE_4KB);//写入扇区擦除(4KB)指令MySPI_SwapByte_Mod0(Addr >> 16);//A23~A16MySPI_SwapByte_Mod0(Addr >> 8);	//A15~A8MySPI_SwapByte_Mod0(Addr);		//A7~A0	MySPI_Stop();W25Q64_WaitBusy();//等待忙状态
}/*************************************************************************************** 名称				W25Q64_ReadData* 功能				W25Q64读取数据* 参数Addr			读取数据的地址* 参数DataArray	存放读取数据的数组* 参数Count		读取的数据数量* 返回值			无*/
void W25Q64_ReadData(uint32_t Addr, uint8_t* DataArray, uint32_t Count)
{uint32_t i;MySPI_Start();MySPI_SwapByte_Mod0(W25Q64_READ_DATA);//写入读取数据指令MySPI_SwapByte_Mod0(Addr >> 16);//A23~A16MySPI_SwapByte_Mod0(Addr >> 8);	//A15~A8MySPI_SwapByte_Mod0(Addr);		//A7~A0for(i = 0;i < Count;i++){	DataArray[i] = MySPI_SwapByte_Mod0(W25Q64_Dummy_BYTE);}MySPI_Stop();
}
2>W25Q64.h
#ifndef __W25Q64_H__
#define __W25Q64_H__
#include "stdint.h"typedef struct
{uint8_t Manufacturer_ID;//厂商IDuint16_t Device_ID;//设备ID
}W25Q64_ID_TypeDef;void W25Q64_Init(void);
void W25Q64_ReadID(W25Q64_ID_TypeDef* ID);//读取ID
void W25Q64_PageProgram(uint32_t Addr, uint8_t* DataArray, uint16_t Count);//页编程
void W25Q64_SectorErase(uint32_t Addr);//W25Q64扇区擦除(4KB)
void W25Q64_ReadData(uint32_t Addr, uint8_t* DataArray, uint32_t Count);//读取数据#endif
3>W25Q64_Ins.h
#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	//读取状态寄存器-1
#define W25Q64_READ_STATUS_REGISTER_2				0x35	//读取状态寄存器-2
#define W25Q64_WRITE_STATUS_REGISTER				0x01	//写入状态寄存器
#define W25Q64_PAGE_PROGRAM							0x02	//页面编程
#define W25Q64_QUAD_PAGE_PROGRAM					0x32	//四页面编程
#define W25Q64_BLOCK_ERASE_64KB						0xD8	//块擦除(64KB)
#define W25Q64_BLOCK_ERASE_32KB						0x52	//块擦除(32KB)
#define W25Q64_SECTOR_ERASE_4KB						0x20	//扇区擦除(4KB)
#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	//退出掉电或高性能模式/设备ID
#define W25Q64_MANUFACTURER_DEVICE_ID				0x90	//制造商/设备ID
#define W25Q64_READ_UNIQUE_ID						0x4B	//读取唯一ID
#define W25Q64_JEDEC_ID								0x9F	//JEDEC ID
#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

Ⅴ、硬件SPI(SPI外设)

1、SPI外设简介

  • STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担

  • 可配置8位/16位数据帧高位先行/低位先行

  • 时钟频率:

    • 时钟频率 = f P C L K 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 = 总线时钟频率 预分频系数 时钟频率=\frac{f_{PCLK}}{2, 4, 8, 16, 32, 64, 128, 256} =\frac{总线时钟频率}{预分频系数} 时钟频率=2,4,8,16,32,64,128,256fPCLK=预分频系数总线时钟频率
  • 支持多主机模型、主或从操作

  • 可精简为半双工/单工通信

  • 支持DMA

  • 兼容I2S协议(数字音频信号传输协议)

  • STM32F103C8T6 硬件SPI资源:SPI1挂载在APB2上,PCLK为72MHz)、SPI2挂载在APB1上,PCLK为36MHz

2、SPI框图

图中所示的是低位先行

image-20250111145559624

  • 发送缓冲区的数据移至移位寄存器中时,会置TXE发送寄存器空)标志位
  • 当移位寄存器中的数据移动至接收缓冲区时,会置RXNE接收寄存器非空)标志位

3、SPI基本结构

image-20250111191525365

4、主模式全双工连续传输

image-20250111191911988

5、非连续传输

image-20250111191919123

Ⅵ、配置SPI外设

1、SPI函数

// 重置指定的SPI/I2S为默认值
void SPI_I2S_DeInit(SPI_TypeDef* SPIx);// 初始化指定的SPI,根据初始化结构体配置参数
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);// 初始化指定的I2S,根据初始化结构体配置参数
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct);// 初始化SPI初始化结构体的默认值
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);// 初始化I2S初始化结构体的默认值
void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct);// 开启或关闭指定的SPI
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);// 开启或关闭指定的I2S
void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);// 开启或关闭SPI/I2S的中断
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);// 开启或关闭SPI/I2S的DMA请求
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);// 通过SPI/I2S发送数据(写DR数据寄存器)
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
// 通过SPI/I2S接收数据(读DR数据寄存器)
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);// 配置SPI的内部NSS软件管理
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);// 开启或关闭SPI的SS输出
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);// 配置SPI的数据大小
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);// 通过SPI发送CRC值
void SPI_TransmitCRC(SPI_TypeDef* SPIx);// 开启或关闭SPI的CRC计算
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);// 获取SPI的CRC值
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);// 获取SPI的CRC多项式
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);
// 配置SPI的双向线模式
void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);// 获取SPI/I2S标志状态
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
// 清除SPI/I2S标志
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);// 获取SPI/I2S中断状态
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
// 清除SPI/I2S中断待处理位
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

2、SPI_InitTypeDef结构体参数

①、SPI_Mode

指定SPI的工作模式

  • 该参数可以是@ref SPI_mode的值

  • @ref SPI_mode

    • 宏定义解释

      1. SPI_Mode_Master
        • 描述:定义了SPI主模式。在这种模式下,SPI设备作为主设备,负责控制时钟信号(SCLK),并发起数据传输。主设备通常用于控制从设备,如传感器、存储器等
      2. SPI_Mode_Slave
        • 描述:定义了SPI从模式。在这种模式下,SPI设备作为从设备,响应主设备的时钟信号(SCLK),并根据主设备的指令进行数据传输。从设备通常用于提供数据或接收数据,如传感器、存储器等

      宏函数

      1. IS_SPI_MODE(MODE)
        • 描述:这是一个宏函数,用于检查给定的工作模式设置是否有效
        • 参数MODE,代表SPI的工作模式设置
        • 功能:检查MODE是否等于SPI_Mode_MasterSPI_Mode_Slave中的任一个
        • 返回值:如果MODE有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_Mode_Master0x0104SPI主模式
      SPI_Mode_Slave0x0000SPI从模式
      宏函数描述
      IS_SPI_MODE(MODE)检查MODE是否为有效的SPI工作模式设置
②、SPI_Direction

指定SPI的单向或双向数据模式

  • 该参数可以是@ref SPI_data_direction

    • 宏定义解释

      1. SPI_Direction_2Lines_FullDuplex
        • 描述:定义了SPI的全双工模式,使用两条线进行数据传输。在这种模式下,SPI设备可以同时发送和接收数据
      2. SPI_Direction_2Lines_RxOnly
        • 描述:定义了SPI的仅接收模式,使用两条线进行数据传输。在这种模式下,SPI设备仅接收数据,不发送数据
      3. SPI_Direction_1Line_Rx
        • 描述:定义了SPI的单线接收模式。在这种模式下,SPI设备使用一条线进行数据接收
      4. SPI_Direction_1Line_Tx
        • 描述:定义了SPI的单线发送模式。在这种模式下,SPI设备使用一条线进行数据发送

      宏函数

      1. IS_SPI_DIRECTION_MODE(MODE)
        • 描述:这是一个宏函数,用于检查给定的数据方向设置是否有效
        • 参数MODE,代表SPI的数据方向设置
        • 功能:检查MODE是否等于SPI_Direction_2Lines_FullDuplexSPI_Direction_2Lines_RxOnlySPI_Direction_1Line_RxSPI_Direction_1Line_Tx中的任一个
        • 返回值:如果MODE有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_Direction_2Lines_FullDuplex0x0000全双工模式,使用两条线
      SPI_Direction_2Lines_RxOnly0x0400仅接收模式,使用两条线
      SPI_Direction_1Line_Rx0x8000单线接收模式
      SPI_Direction_1Line_Tx0xC000单线发送模式
      宏函数描述
      IS_SPI_DIRECTION_MODE(MODE)检查MODE是否为有效的SPI数据方向设置
③、SPI_DataSize

指定SPI数据大小

  • 该参数可以是@ref SPI_data_size

    • 宏定义解释

      1. SPI_DataSize_16b
        • 描述:定义了SPI的数据大小为16位。在这种模式下,每次数据传输的大小为16位(2字节)
      2. SPI_DataSize_8b
        • 描述:定义了SPI的数据大小为8位。在这种模式下,每次数据传输的大小为8位(1字节)

      宏函数

      1. IS_SPI_DATASIZE(DATASIZE)
        • 描述:这是一个宏函数,用于检查给定的数据大小设置是否有效
        • 参数DATASIZE,代表SPI的数据大小设置
        • 功能:检查DATASIZE是否等于SPI_DataSize_16bSPI_DataSize_8b中的任一个
        • 返回值:如果DATASIZE有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_DataSize_16b0x080016位数据大小
      SPI_DataSize_8b0x00008位数据大小
      宏函数描述
      IS_SPI_DATASIZE(DATASIZE)检查DATASIZE是否为有效的SPI数据大小设置
④、SPI_FirstBit

指定数据传输是MSB(高位先行)还是LSB(低位先行)

  • 该参数可以是@ref SPI_MSB_LSB_transmission

    • 宏定义解释

      1. SPI_FirstBit_MSB
        • 描述:定义了SPI的数据传输顺序为先传输最高位(MSB)高位先行。在这种模式下,数据的最高位(最左边的位)先被发送和接收。这是最常见的数据传输顺序,适用于大多数SPI设备
      2. SPI_FirstBit_LSB
        • 描述:定义了SPI的数据传输顺序为先传输最低位(LSB)低位先行。在这种模式下,数据的最低位(最右边的位)先被发送和接收。这种配置在某些特定的应用场景中可能有用,例如在处理某些特殊的编码或数据格式时

      宏函数

      1. IS_SPI_FIRST_BIT(BIT)
        • 描述:这是一个宏函数,用于检查给定的数据传输顺序设置是否有效
        • 参数BIT,代表SPI的数据传输顺序设置
        • 功能:检查BIT是否等于SPI_FirstBit_MSBSPI_FirstBit_LSB中的任一个
        • 返回值:如果BIT有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_FirstBit_MSB0x0000先传输最高位(MSB)高位先行
      SPI_FirstBit_LSB0x0080先传输最低位(LSB)低位先行
      宏函数描述
      IS_SPI_FIRST_BIT(BIT)检查BIT是否为有效的SPI数据传输顺序设置
⑤、SPI_BaudRatePrescaler

指定波特率预算器值,该值将为用于配置发送和接收SCK时钟

  • 通信时钟来源于主时钟。不需要设置从时钟

  • 该参数可以是@ref spi_baudrate_precaler

    • 宏定义解释

      1. SPI_BaudRatePrescaler_2
        • 描述:定义了SPI的波特率预分频器为2。这意味着SPI时钟频率是系统时钟频率的1/2
      2. SPI_BaudRatePrescaler_4
        • 描述:定义了SPI的波特率预分频器为4。这意味着SPI时钟频率是系统时钟频率的1/4
      3. … …

      宏函数

      1. IS_SPI_BAUDRATE_PRESCALER(PRESCALER)
        • 描述:这是一个宏函数,用于检查给定的波特率预分频器设置是否有效
        • 参数PRESCALER,代表SPI的波特率预分频器设置
        • 功能:检查PRESCALER是否等于预定义的波特率预分频器值中的任一个
        • 返回值:如果PRESCALER有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_BaudRatePrescaler_20x0000预分频器为2
      SPI_BaudRatePrescaler_40x0008预分频器为4
      SPI_BaudRatePrescaler_80x0010预分频器为8
      SPI_BaudRatePrescaler_160x0018预分频器为16
      SPI_BaudRatePrescaler_320x0020预分频器为32
      SPI_BaudRatePrescaler_640x0028预分频器为64
      SPI_BaudRatePrescaler_1280x0030预分频器为128
      SPI_BaudRatePrescaler_2560x0038预分频器为256
      宏函数描述
      IS_SPI_BAUDRATE_PRESCALER(PRESCALER)检查PRESCALER是否为有效的SPI波特率预分频器设置
⑥、SPI_CPOL

指定时钟极性(Clock Polarity)配置决定了SPI时钟线(SCLK)的默认电平

  • 该参数可以是@ref SPI_Clock_Polarity

    • 宏定义解释

      1. SPI_CPOL_Low
        • 描述定义了SPI的时钟极性为低电平。在这种配置下,SPI时钟线(SCLK)的默认电平为低电平(0)。数据在时钟从低到高的边沿(上升沿)被采样,在从高到低的边沿(下降沿)被发送
      2. SPI_CPOL_High
        • 描述定义了SPI的时钟极性为高电平。在这种配置下,SPI时钟线(SCLK)的默认电平为高电平(1)。数据在时钟从高到低的边沿(下降沿)被采样,在从低到高的边沿(上升沿)被发送

      宏函数

      1. IS_SPI_CPOL(CPOL)
        • 描述:这是一个宏函数,用于检查给定的时钟极性设置是否有效
        • 参数CPOL,代表SPI的时钟极性设置
        • 功能:检查CPOL是否等于SPI_CPOL_LowSPI_CPOL_High中的任一个
        • 返回值:如果CPOL有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_CPOL_Low0x0000时钟极性为低电平
      SPI_CPOL_High0x0002时钟极性为高电平
      宏函数描述
      IS_SPI_CPOL(CPOL)检查CPOL是否为有效的SPI时钟极性设置
⑦、SPI_CPHA

定义了SPI的时钟相位(Clock Phase)配置决定了数据在时钟的哪个边沿被采样和发送

时钟相位CPHA):

  • CPHA = 0:数据在时钟的第一个边沿被采样,在第二个边沿被发送
  • CPHA = 1:数据在时钟的第二个边沿被采样,在第一个边沿被发送
  • 该参数可以是@ref SPI_Clock_Phase

    • 宏定义解释

      1. SPI_CPHA_1Edge
        • 描述0定义了SPI的时钟相位为第一个时钟边沿。在这种配置下,数据在时钟的第一个边沿(上升沿或下降沿,取决于时钟极性)被采样,在第二个边沿被发送
      2. SPI_CPHA_2Edge
        • 描述1定义了SPI的时钟相位为第二个时钟边沿。在这种配置下,数据在时钟的第二个边沿被采样,在第一个边沿被发送

      宏函数

      1. IS_SPI_CPHA(CPHA)
        • 描述:这是一个宏函数,用于检查给定的时钟相位设置是否有效
        • 参数CPHA,代表SPI的时钟相位设置
        • 功能:检查CPHA是否等于SPI_CPHA_1EdgeSPI_CPHA_2Edge中的任一个
        • 返回值:如果CPHA有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_CPHA_1Edge0x0000数据在第一个时钟边沿被采样
      SPI_CPHA_2Edge0x0001数据在第二个时钟边沿被采样
      宏函数描述
      IS_SPI_CPHA(CPHA)检查CPHA是否为有效的SPI时钟相位设置
⑧、SPI_NSS

从设备选择(Slave Select,NSS)管理配置决定了SPI从设备的NSS信号是由硬件控制还是软件控制

  • 该参数可以是@ref SPI_Slave_Select_management

    • 宏定义解释

      1. SPI_NSS_Soft
        • 描述:定义了SPI的NSS信号由软件管理
          • 在这种模式下,NSS信号由软件控制,通常在每次数据传输前后手动设置和清除。这适用于需要灵活控制NSS信号的场景,例如在多从设备系统中,主设备需要精确控制每个从设备的NSS信号
      2. SPI_NSS_Hard
        • 描述:定义了SPI的NSS信号由硬件管理
          • 在这种模式下,NSS信号由硬件自动控制,通常在数据传输开始时自动置低,在数据传输结束时自动置高。这适用于简单的SPI通信场景,减少了软件控制的复杂性

      宏函数

      1. IS_SPI_NSS(NSS)
        • 描述:这是一个宏函数,用于检查给定的从设备选择管理设置是否有效
        • 参数NSS,代表SPI的从设备选择管理设置
        • 功能:检查NSS是否等于SPI_NSS_SoftSPI_NSS_Hard中的任一个
        • 返回值:如果NSS有效,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      SPI_NSS_Soft0x0200NSS信号由软件管理
      SPI_NSS_Hard0x0000NSS信号由硬件管理
      宏函数描述
      IS_SPI_NSS(NSS)检查NSS是否为有效的SPI从设备选择管理设置
⑨、SPI_CRCPolynomial

CRC(Cyclic Redundancy Check,循环冗余校验)多项式配置

  • 复位值为0x0007,根据应用可以设置其它数值

    • 注:在I2S模式下不使用
  • CRC校验

    • CRC校验是一种常用的错误检测方法,通过在数据传输前后计算CRC值,可以检测数据在传输过程中是否发生了错误
    • CRC多项式是一个特定的多项式,用于生成CRC校验码。不同的多项式会产生不同的CRC校验码,因此选择合适的多项式非常重要

3、SPI的四种工作模式

模式CPOL(时钟极性)CPHA(时钟相位)数据采样时刻
模式000在时钟的上升沿采样数据
模式101在时钟的下降沿采样数据
模式210在时钟的下降沿采样数据
模式311在时钟的上升沿采样数据

4、SPI外设

HardSPI.c
#include "stm32f10x.h"                  // Device header
#include "HardSPI.h"
//硬件SPI
//输出:>SS:		PA4		由软件控制
//输出:>SCK:	PA5		由硬件控制
//输出:>MOSI:	PA7		由硬件控制
//输入:>MISO:	PA6		由硬件控制void HardSPI_W_SS(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}void HardSPI_Init(void)
{//初始化GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//将SS(软件控制)配置为通用推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//将输出口配置为复用推挽输出GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//将输入口配置为上拉输入GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);//配置SPISPI_InitTypeDef SPI_InitStruct;SPI_InitStruct.SPI_Mode = SPI_Mode_Master;//主从模式选择SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//选择全双工SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;//设置8位数据大小SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;//设置为高位先行SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;//设置分频系数为128SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;//0SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;//0	CPOL=0;CPHA=0时为模式0SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;//配置SS由软件管理SPI_InitStruct.SPI_CRCPolynomial = 0x0007;//不使用CRC校验,复位值为0x0007SPI_Init(SPI1, &SPI_InitStruct);SPI_Cmd(SPI1,ENABLE);//使能SPI外设HardSPI_W_SS(1);//配置默认电平
}//起始条件-----SS从高电平切换到低电平
void HardSPI_Start(void) {HardSPI_W_SS(0);
}//终止条件-----SS从低电平切换到高电平
void HardSPI_Stop(void) {HardSPI_W_SS(1);
}//交换一个字节(模式0)
uint8_t HardSPI_SwapByte_Mod0(uint8_t ByteSend)
{while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == !SET);//当发送数据寄存器为空标志位(TXE)== 1时,才跳出循环SPI_I2S_SendData(SPI1, ByteSend);//发送数据(写入DR时会自动清除TXE标志位)while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == !SET);//接收缓冲区接收到数据时跳出循环return  SPI_I2S_ReceiveData(SPI1);//接收数据(读DR时会自动清除RXNE标志位)
}

相关文章:

【STM32-学习笔记-9-】SPI通信

文章目录 SPI通信Ⅰ、SPI通信概述1、SPI技术规格2、SPI应用 3、硬件电路移位示意图 Ⅱ、SPI时序基本单元①、起始条件②、终止条件③、交换一个字节&#xff08;模式0&#xff09;④、交换一个字节&#xff08;模式1&#xff09;⑤、交换一个字节&#xff08;模式2&#xff09;…...

kalilinux - 目录扫描之dirsearch

情景导入 先简单介绍一下dirsearch有啥用。 假如你现在访问一个网站&#xff0c;例如https://www.example.com/ 它是一个电商平台或者其他功能性质的平台。 站在开发者的角度上思考&#xff0c;我们只指导https://www.example.com/ 但不知道它下面有什么文件&#xff0c;文…...

(12)springMVC文件的上传

SpringMVC文件上传 首先是快速搭建一个springMVC项目 新建项目mvn依赖导入添加webMoudle添加Tomcat运行环境.在配置tomcat时ApplicationContext置为"/"配置Artfact的lib配置WEB-INF配置文件&#xff08;记得添加乱码过滤&#xff09;配置springmvc-servlet文件&…...

[Mac + Icarus Verilog + gtkwave] Mac运行Verilog及查看波形图

目录 1. MAC安装环境 1. 1 Icarus Verilog 编译 1. 2 gtkwave 查看波形 2. 安装遇到的问题 2. 1 macOS cannot verify that this app is free from malware 2. 2 gtkwave-bin is not compatible with macOS 14 or later 3. 运行示例 3. 1 源代码 3. 2 编译Verilog 3. 3 生成.v…...

yt-dlp脚本下载音频可选设置代理

import yt_dlp# 配置:是否使用代理 use_proxy = True # 设置为 False 可关闭代理# 代理地址 proxy_url = socks5://127.0.0.1:1089URLS = [https://www.bilibili.com/video/BV1WTktYcEcQ/?spm_id_from=333.1007.tianma.6-2-20.click&vd_source=dcb58f8fe1faf749f438620b…...

【向量数据库 Milvus】linux 源码安装 Milvus 2.5.3

在 Linux 系统&#xff08;如 ai 5.10.134-16.2.an8.x86_64&#xff09;上通过源码安装 Milvus 2.5.3 的步骤如下。该指南适用于 x86_64 架构的系统。 1. 环境准备 确保系统满足以下要求&#xff1a; 操作系统: Linux&#xff08;x86_64 架构&#xff09;Go: 1.21 或更高版本…...

初学stm32 --- CAN

目录 CAN介绍 CAN总线拓扑图 CAN总线特点 CAN应用场景 CAN物理层 CAN收发器芯片介绍 CAN协议层 数据帧介绍 CAN位时序介绍 数据同步过程 硬件同步 再同步 CAN总线仲裁 STM32 CAN控制器介绍 CAN控制器模式 CAN控制器模式 CAN控制器框图 发送处理 接收处理 接收过…...

linux手动安装mysql5.7

一、下载mysql5.7 1、可以去官方网站下载mysql-5.7.24-linux-glibc2.12-x86_64.tar压缩包&#xff1a; https://downloads.mysql.com/archives/community/ 2、在线下载&#xff0c;使用wget命令&#xff0c;直接从官网下载到linux服务器上 wget https://downloads.mysql.co…...

【Java】LinkedHashMap (LRU)淘汰缓存的使用

文章目录 **1. initialCapacity&#xff08;初始容量&#xff09;****2. loadFactor&#xff08;加载因子&#xff09;****3. accessOrder&#xff08;访问顺序&#xff09;****完整参数解释示例****示例验证** LinkedHashMap 在 Java 中可维护元素插入或访问顺序&#xff0c;并…...

JAVA实现五子棋小游戏(附源码)

文章目录 一、设计来源捡金币闯关小游戏讲解1.1 主界面1.2 黑棋胜利界面1.3 白棋胜利界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/145161039 JA…...

基于Java的百度AOI数据解析与转换的实现方法

目录 前言 一、AOI数据结构简介 1、官网的实例接口 2、响应参数介绍 二、Java对AOI数据的解析 1、数据解析流程图 2、数据解析实现 3、AOI数据解析成果 三、总结 前言 在当今信息化社会&#xff0c;地理信息数据在城市规划、交通管理、商业选址等领域扮演着越来越重要的…...

细说STM32F407单片机窗口看门狗WWDG的原理及使用方法

目录 一、窗口看门狗的工作原理 1、递减计数器 2、窗口值和比较器 3、看门狗的启动 4、提前唤醒中断 二、窗口看门狗的HAL驱动程序 1、窗口看门狗初始化 2.窗口看门狗刷新 3.EWI中断及其处理 三、不开启EWI的WWDG示例 1、示例功能 2、项目设置 &#xff08;1&…...

【.net core】【sqlsugar】时间查询示例

1、时间包含查询示例 //model.TimeInterval为时间区间参数&#xff0c;参数格式为2024-01-01~2025-01-01 //query为当前查询的语句内容 //为当前查询语句增加创建时间模糊搜索查询条件 query query.Where(a > ((DateTime)a.F_CreatorTime).ToString("yyyy-MM-dd HH:m…...

基于Oracle与PyQt6的电子病历多模态大模型图形化查询系统编程构建

一、引言 1.1 研究背景阐述 在当今数字化时代,医疗行业正经历着深刻的变革,数字化转型的需求日益迫切。电子病历(EMR)作为医疗信息化的核心,其管理的高效性和数据利用的深度对于提升医疗服务质量、优化临床决策以及推动医学研究具有至关重要的意义。传统的电子病历管理系…...

STM32 HAL库函数入门指南:从原理到实践

1 STM32 HAL库概述 STM32 HAL(Hardware Abstraction Layer)库是ST公司专门为STM32系列微控制器开发的一套硬件抽象层函数库。它的核心设计理念是在应用层与硬件层之间建立一个抽象层&#xff0c;这个抽象层屏蔽了底层硬件的具体实现细节&#xff0c;为开发者提供了一套统一的、…...

Harmony面试模版

1. 自我介绍 看表达能力、沟通能力 面试记录&#xff1a; 2. 进一步挖掘 2.1. 现状 目前是在职还是离职&#xff0c;如果离职&#xff0c;从上一家公司离职的原因 2.2. 项目经验 如果自我介绍工作项目经验讲的不够清楚&#xff0c;可以根据简历上的信息再进一步了解 面试记…...

数据结构知识点

【1】栈&#xff08;stack&#xff09; C 标准库提供了 std::stack 模板类&#xff0c;用于实现栈的功能。std::stack 是基于其他容器&#xff08;如 std::vector、std::deque 或 std::list&#xff09;实现的适配器类。 std::stack 可以使用不同的底层容器来实现&#xff0c…...

RPC 简介

RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种通过网络请求执行远程服务器上的代码的技术&#xff0c;使得开发者可以调用远程系统中的函数&#xff0c;就像调用本地函数一样。它隐藏了底层网络通信的细节&#xff0c;简化了分布式系统的开…...

qBittorent访问webui时提示unauthorized解决方法

现象描述 QNAP使用Container Station运行容器&#xff0c;使用Docker封装qBittorrent时&#xff0c;访问IP:PORT的方式后无法访问到webui&#xff0c;而是提示unauthorized&#xff0c;如图&#xff1a; 原因分析 此时通常是由于设备IP与qBittorrent的ip地址不在同一个网段导致…...

Windows部署NVM并下载多版本Node.js的方法(含删除原有Node的方法)

本文介绍在Windows电脑中&#xff0c;下载、部署NVM&#xff08;node.js version management&#xff09;环境&#xff0c;并基于其安装不同版本的Node.js的方法。 在之前的文章Windows系统下载、部署Node.js与npm环境的方法&#xff08;https://blog.csdn.net/zhebushibiaoshi…...

【大数据】机器学习 -----关于data.csv数据集分析案例

打开表 import pandas as pd df2 pd.read_csv("data.csv",encoding"gbk") df2.head()查看数据属性&#xff08;列标题&#xff0c;表形状&#xff0c;类型&#xff0c;行标题&#xff0c;值&#xff09; print("列标题:",df2.columns)Data…...

使用Newtonsoft.Json插件,打包至Windows平台显示不支持

在unity中使用Newtonsoft.Json插件&#xff0c;打包至Windows遇到的问题 string json JsonConvert.SerializeObject(msg); 打包windows平台&#xff0c;显示该平台不支持 出现问题的原因 JsonConvert.SerializeObject 使用了反射来动态遍历对象的属性和字段。这可能在某些平台…...

树莓派5--系统问题汇总

前言&#xff1a; 该文章是我在使用树莓派5时所遇到的问题以及解决方案&#xff0c;希望对遇到相同问题的能够有所帮助。我的树莓派系统版本为&#xff1a;Pi-OS-ROS_2024_09_29 注意&#xff1a;如果没有什么需求千万不要更新树莓派中任何软件或者系统&#xff0c;除非你真的…...

Level2逐笔成交逐笔委托毫秒记录:今日分享优质股票数据20250116

逐笔成交逐笔委托下载 链接: https://pan.baidu.com/s/11nYhOf5TL9haZdXcYTxmHQ?pwdfwg8 提取码: fwg8 -------------------- Level2逐笔成交逐笔委托数据分享下载 利用Level2的逐笔交易和委托数据&#xff0c;这种以毫秒为单位的详细信息能揭露众多关键信息&#xff0c;如庄…...

小白:react antd 搭建框架关于 RangePicker DatePicker 时间组件使用记录 2

文章目录 一、 关于 RangePicker 组件返回的moment 方法示例 一、 关于 RangePicker 组件返回的moment 方法示例 moment方法中日后开发有用的方法如下&#xff1a; form.getFieldsValue().date[0].weeksInWeekYear(),form.getFieldsValue().date[0].zoneName(), form.getFiel…...

windows远程桌面连接限定ip

1&#xff0c;Windows防火墙->高级设置->远程桌面 - 用户模式(TCP-In)->作用域->远程IP地址 2&#xff0c;启用规则...

强化学习-蒙特卡洛方法

强化学习-数学理论 强化学习-基本概念强化学习-贝尔曼公式强化学习-贝尔曼最优公式强化学习-值迭代与策略迭代强化学习-蒙特卡洛方法 文章目录 强化学习-数学理论一、蒙特卡洛方法理论(Monte Carlo, MC)二、MC Basic2.1 算法拆解2.2 MC Basic算法 三、MC Exploring Starts3.1 …...

Java并发编程——线程池(基础,使用,拒绝策略,命名,提交方式,状态)

我是一个计算机专业研0的学生卡蒙Camel&#x1f42b;&#x1f42b;&#x1f42b;&#xff08;刚保研&#xff09; 记录每天学习过程&#xff08;主要学习Java、python、人工智能&#xff09;&#xff0c;总结知识点&#xff08;内容来自&#xff1a;自我总结网上借鉴&#xff0…...

浅谈云计算08 | 基本云架构

浅谈基本云架构 一、负载分布架构二、资源池架构三、动态可扩展架构四、弹性资源容量架构五、服务负载均衡架构六、云爆发架构七、弹性磁盘供给架构八、冗余存储架构 在当今数字化时代&#xff0c;云计算已成为企业发展的核心驱动力&#xff0c;而其背后的一系列关键架构则是支…...

element select 绑定一个对象{}

背景&#xff1a; select组件的使用&#xff0c;适用广泛的基础单选 v-model 的值为当前被选中的 el-option 的 value 属性值。但是我们这里想绑定一个对象&#xff0c;一个el-option对应的对象。 <el-select v-model"state.form.modelA" …...

MySQL SQL优化技巧与原理

前言 随着业务数据量的不断增加&#xff0c;MySQL查询语句的执行效率对程序的运行效率影响逐渐增大。因此&#xff0c;进行SQL优化变得至关重要。本文将结合SQL的执行语句顺序和各种SQL场景&#xff0c;介绍一些常见的MySQL SQL优化技巧及其背后的原理。 一、MySQL SQL执行语…...

SSL:WRONG_VERSION_NUMBER 或者 net::ERR_SSL_PROTOCAL_ERROR

记录一次SSL部署成功后&#xff0c;接口请求依然报SSL错误的问题。 首先排除SSL证据链不足&#xff0c;系统时间不正确&#xff0c;TLS配置不正确等问题。 浏览器直接访问可以打开网站&#xff0c;但是postman等接口访问就一直报SSL异常&#xff1a; 类似参考资料中的这种异…...

51单片机——DS18B20温度传感器

由于DS18B20数字温度传感器是单总线接口&#xff0c;所以需要使用51单片机的一个IO口模拟单总线时序与DS18B20通信&#xff0c;将检测的环境温度读取出来 1、DS18B20模块电路 传感器接口的单总线管脚接至单片机P3.7IO口上 2、DS18B20介绍 2.1 DS18B20外观实物图 管脚1为GN…...

单细胞组学大模型(8)--- scGenePT,scGPT和GenePT的结合,实验数据和文本数据的交融模型

–https://doi.org/10.1101/2024.10.23.619972 研究团队和单位 Theofanis Karaletsos–Head Of AI - Science at Chan Zuckerberg Initiative &#xff08;Chan Zuckerberg Initiative是扎克伯格和他妻子Chan成立的科研&教育机构&#xff09; 研究简介 研究背景&…...

详解如何自定义 Android Dex VMP 保护壳

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 前言 Android Dex VMP&#xff08;Virtual Machine Protection&#xff0c;虚拟机保护&#xff09;壳是一种常见的应用保护技术&#xff0c;主要用于保护 And…...

PHP中的魔术函数

PHP 魔术函数是在某些情况下会自动调用的特殊函数&#xff0c;它们以双下划线 __ 开头&#xff0c;以下是对常见 PHP 魔术函数的详细介绍&#xff1a; ### 构造函数和析构函数 - **__construct()**&#xff1a; - 这是一个构造函数&#xff0c;在创建类的新对象时会自动调…...

excel 判断某个单元格的日期,如果超过3天,则在另一个单元格显示超过三天的公式

excel 判断某个单元格的日期&#xff0c;如果超过3天&#xff0c;则在另一个单元格显示超过三天的公式&#xff0c;公式如下&#xff1a; IF(DATEDIF(C627,TODAY(),"d")<4,"3天以内","超过三天") IF(D627"超过3天","文件赶紧…...

TCP 序列和确认号说明 | seq 和 ack 号计算方法

注&#xff1a;本文为 “TCP 序列” 相关文章合辑。 英文引文机翻未校。 TCP Sequence and Acknowledgement Numbers Explained TCP 序列和确认编号说明 TCP Sequence (seq) and Acknowledgement (ack) numbers help enable ordered reliable data transfer for TCP streams…...

【Linux】Mysql部署步骤

一、JDK安装配置 在home目录下执行命令&#xff1a;mkdir Jdk 1.将JDK 上传至该文件夹&#xff0c;有些终端工具可以直接上传文件&#xff0c;比如&#xff1a;MobaXterm 可以看到安装包已经上传上来了 2.直接安装 命令&#xff1a;rpm -ivh jdk-8u311-linux-x64.rpm 3.安装成…...

【算法】枚举

枚举 普通枚举1.铺地毯2.回文日期3.扫雷 二进制枚举1.子集2.费解的开关3.Even Parity 顾名思义&#xff0c;就是把所有情况全都罗列出来&#xff0c;然后找出符合题目要求的那一个。因此&#xff0c;枚举是一种纯暴力的算法。一般情况下&#xff0c;枚举策略都是会超时的。此时…...

【C++】构造函数与析构函数

写在前面 构造函数与析构函数都是属于类的默认成员函数&#xff01; 默认成员函数是程序猿不显示声明定义&#xff0c;编译器会中生成。 构造函数和析构函数的知识需要建立在有初步类与对象的基础之上的&#xff0c;关于类与对象不才在前面笔记中有详细的介绍&#xff1a;点我…...

力扣刷题汇总

动态规划 1 . 最大子序和 (Maximum Subarray Sum) Leetcode 53. 最大子数组和 经典dp 问题描述&#xff1a;给定一个整数数组&#xff0c;求其中和最大的连续子数组的和。 状态定义&#xff1a;dp[i] 表示以第 i 个元素结尾的最大子序和。 2 . 最长公共子序列 (Longest Commo…...

Ansible自动化运维:基础与实践

在当今的IT运维领域&#xff0c;Ansible作为一款强大的自动化运维工具&#xff0c;正发挥着日益重要的作用。本文将详细介绍Ansible的相关知识&#xff0c;包括其作用、特点、安装配置以及常用模块的使用方法&#xff0c;旨在帮助读者快速上手并熟练运用Ansible进行自动化运维工…...

微信小程序在使用页面栈保存页面信息时,如何避免数据丢失?

微信小程序在使用页面栈保存页面信息时避免数据丢失的方法&#xff1a; 一、使用全局变量存储关键数据&#xff1a; 定义一个全局变量&#xff0c;例如在 app.js 中&#xff0c;用于存储页面的重要信息。在页面的 onHide 或 onUnload 生命周期中&#xff0c;将需要保存的数据…...

我国无人机新增实名登记110.3 万架,累计完成飞行2666万小时

据央视新闻从中国民航局了解到&#xff0c;2024 年我国全年新增通航企业 145 家、通用机场 26 个&#xff0c;颁发无人驾驶航空器型号合格证 6 个、新增实名登记无人机 110.3 万架&#xff0c;无人机运营单位总数超过 2 万家&#xff0c;累计完成无人机飞行 2666 万小时&#x…...

vue3+vite+ts+router4+Pinia+Axios+sass 从0到1搭建

1、使用vite构建项目 npm create vitelatest 填写项目名的时候不能大写 2、跑起来之后配置下 import { defineConfig } from vite import vue from vitejs/plugin-vue import { resolve } from path // https://vite.dev/config/ export default defineConfig({plugins: [vue…...

C语言:-三子棋游戏代码:分支-循环-数组-函数集合

思路分析&#xff1a; 1、写菜单 2、菜单之后进入游戏的操作 3、写函数 实现游戏 3.1、初始化棋盘函数&#xff0c;使数组元素都为空格 3.2、打印棋盘 棋盘的大概样子 3.3、玩家出棋 3.3.1、限制玩家要下的坐标位置 3.3.2、判断玩家要下的位置是否由棋子 3.4、电脑出棋 3.4.1、…...

前端调试遇到的无限debugger的原理与绕过

背景 debugger 是 JavaScript 中定义的一个专门用于断点调试的关键字,只要遇到它,JavaScript 的执行便会在此处中断,进入调试模式。有了 debugger 这个关键字,我们就可以非常方便地对 JavaScript 代码进行调试,比如使用 JavaScript Hook 时,我们可以加入 debugger 关键字…...

Java负载均衡

Java中的负载均衡原理是指通过合理分配网络请求或计算任务的方式&#xff0c;将工作负载分配到多个服务器、处理单元或服务实例上&#xff0c;从而提高系统的性能、可扩展性和可用性。负载均衡不仅可以分散请求压力&#xff0c;还能增强系统的容错能力&#xff0c;避免单点故障…...

spark,读取和写入同一张表问题

读取a表&#xff0c;写入a表 1.写入的是分区表&#xff0c;不报错 2.读取上来之后&#xff0c;创建为临时视图temp&#xff0c;然后先写入a表&#xff0c;再使用temp&#xff0c;就会报错 解决办法&#xff1a;可以先使用temp&#xff0c;再写入a表 3.写入的不是分区表&…...