stm32中的SPI

news2024/10/6 18:26:46

SPI的简介

文章目录

  • SPI的简介
    • 物理层
    • 协议层
      • 基本通讯过程
        • 起始和终止信号
        • 数据有效性
        • CPOL/CPHA及通讯模式
  • STM3的SPI特性及架构
    • 通讯引脚
    • 时钟控制逻辑
    • 数据控制逻辑
    • 整体控制逻辑
    • 通讯过程
  • 代码配置实现
    • 指令集
    • 结构体的定义
      • SPI时钟信号的定义
      • SPI端口定义
      • SPI命令
    • flash驱动代码
      • 初始化代码(配置端口)
      • 配置SPI模式代码
      • 发送并接受一个字节
      • 读取字节
      • 读取ID号
      • FLASH写入使能
      • 等待FLASH内部时序操作完成
      • 擦除FLASH指定扇区

物理层

在这里插入图片描述

SPI一共三条总线

SPI总线功能
SS( Slave Select)选从机
SCK (Serial Clock)时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率
MOSI (Master Output,Slave Input)主设备输出/从设备输入引脚。这条线上数据的方向为主机到从机。
MISO (Master Input,,Slave Output)主设备输入/从设备输出引脚。在这条线上数据的方向为从机到主机。

协议层

基本通讯过程

在这里插入图片描述

  1. NSS为低电平时候才有效
  2. SCK每一个周期MOSI和MISO传输一位数据
起始和终止信号
  • 起始:高变低
  • 终止:低变高
数据有效性
  • SPI 使用 MOSI 及 MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。MOSI 及 MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时,MSB先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI 通讯设备之间使用同样的协定,一般都会采用图 SPI 通讯时序 中的 MSB 先行模式。
  • 即在 SCK 的下降沿时刻,MOSI 及 MISO 的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI 及 MISO 为下一次表示数据做准备。SPI 每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。
CPOL/CPHA及通讯模式

在这里插入图片描述
在这里插入图片描述
CPHA:当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。一个边沿被设置为采样后另一个边沿只能为读取数据。
在这里插入图片描述

CPOL:控制SCK空闲时刻的电平,0为低电平,1为高电平。

在这里插入图片描述

STM3的SPI特性及架构

在这里插入图片描述

通讯引脚

在这里插入图片描述

时钟控制逻辑

由波特率发生器根据“控制寄存器 CR1”中的 BR[0:2] 位控制

在这里插入图片描述

数据控制逻辑

SPI 的 MOSI 及 MISO 都连接到数据移位寄存器上,数据移位寄存器的数据来源及目标接收、发送缓冲区以及 MISO、MOSI 线。

当从外部接收数据的时候,数据移位寄存器把数据线采样到的数据一位一位地存储到“接收缓冲区”中。

通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通讯读“数据寄存器 DR”,可以获取接收缓冲区中的内容。

DR[15:0]:数据寄存器 (Data register) 待发送或者已经收到的数据

数据寄存器对应两个缓冲区:一个用于写(发送缓冲);另外一个用于读(接收缓冲)。写操作将数据写到发送缓冲区;读操作将返回接收缓冲区里的数据。

**对SPI模式的注释:**根据SPI_CR1的DFF位对数据帧格式的选择,数据的发送和接收可以是8位或者16位的。为保证正确的操作,需要在启用SPI之前就确定好数据帧格式。

对于8位的数据,缓冲器是8位的,发送和接收时只会用到SPI_DR[7:0]。在接收时,SPI_DR[15:8]被强制为0。

对于16位的数据,缓冲器是16位的,发送和接收时会用到整个数据寄存器,即SPI_DR[15:0]。

**其中数据帧:**长度可以通过“控制寄存器 CR1”的“DFF 位”配置成 8 位及 16 位模式;配置“LSBFIRST 位”可选择 MSB 先行还是 LSB 先行。

整体控制逻辑

整体控制逻辑负责协调整个 SPI 外设,控制逻辑的工作模式根据我们配置的“控制寄存器(CR1/CR2)”的参数而改变基本的控制参数包括前面提到的 SPI 模式、波特率、LSB 先行、主从模式、单双向模式等等。

通讯过程

在这里插入图片描述

(1) 控制 NSS 信号线,产生起始信号 (图中没有画出);

(2) 把要发送的数据写入到“数据寄存器 DR”中,该数据会被存储到发送缓冲区;

(3) 通讯开始,SCK 时钟开始运行。MOSI 把发送缓冲区中的数据一位一位地传输出去;MISO 则把数据一位一位地存储进接收缓冲区中;

(4) 当发送完一帧数据的时候,“状态寄存器 SR”中的“TXE 标志位”会被置 1,表示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“RXNE 标志位”会被置 1,表示传输完一帧,接收缓冲区非空;

(5) 等待到“TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器 DR”写入数据即可;等待到“RXNE 标志位”为 1 时,通过读取“数据寄存器 DR”可以获取接收缓冲区中的内容。假如我们使能了 TXE 或 RXNE 中断,TXE 或 RXNE 置 1 时会产生 SPI 中断信号,进入同一个中断服务函数,到 SPI 中断服务程序后,可通过检查寄存器位来了解是哪一个事件,再分别进行处理。也可以使用 DMA 方式来收发“数据寄存器 DR”中的数据

代码配置实现

指令集

在这里插入图片描述

结构体的定义

SPI时钟信号的定义

#define             FLASH_SPIx                                SPI1
#define             FLASH_SPI_APBxClock_FUN                  RCC_APB2PeriphClockCmd
#define             FLASH_SPI_CLK                             RCC_APB2Periph_SPI1
#define             FLASH_SPI_GPIO_APBxClock_FUN            RCC_APB2PeriphClockCmd

SPI端口定义

#define             FLASH_SPI_SCK_PORT                        GPIOA   
#define             FLASH_SPI_SCK_PIN                         GPIO_Pin_5

#define             FLASH_SPI_MOSI_PORT                        GPIOA 
#define             FLASH_SPI_MOSI_PIN                         GPIO_Pin_7

#define             FLASH_SPI_MISO_PORT                        GPIOA 
#define             FLASH_SPI_MISO_PIN                         GPIO_Pin_6

#if (USE_BD ==1)
	#define             FLASH_SPI_GPIO_CLK                        RCC_APB2Periph_GPIOA
	
	#define             FLASH_SPI_CS_PORT                        GPIOA 
	#define             FLASH_SPI_CS_PIN                         GPIO_Pin_4
#else
	#define             FLASH_SPI_GPIO_CLK                        (RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC)
	
	#define             FLASH_SPI_CS_PORT                        GPIOC
	#define             FLASH_SPI_CS_PIN                         GPIO_Pin_0
#endif


SPI命令

#define DUMMY 						0x00	
#define READ_JEDEC_ID    			 0x9f																					
#define ERASE_SECTOR			0x20	
#define READ_STATUS				0x05
#define READ_DATA				0x03		
#define WRITE_ENABLE   		   0x06																					
#define WRITE_DATA				0x02	

flash驱动代码

初始化代码(配置端口)

在这里插入图片描述

/**
  * @brief  SPII/O配置
  * @param  无
  * @retval 无
  */
static void SPI_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure; 

	/* 使能与SPI 有关的时钟 */
	FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );
	FLASH_SPI_GPIO_APBxClock_FUN ( FLASH_SPI_GPIO_CLK, ENABLE );
	
    
  /* MISO MOSI SCK*/
  GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	       
  GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	       
  GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	       
  GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);
	
	//初始化CS引脚,使用软件控制,所以直接设置成推挽输出	
	GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	       
  GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
	
	FLASH_SPI_CS_HIGH;
}

配置SPI模式代码

static void SPI_Mode_Config(void)
{
  SPI_InitTypeDef  SPI_InitStructure; 

	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ;
	//SPI 使用模式3
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge ;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High ;
	SPI_InitStructure.SPI_CRCPolynomial = 0;//不使用CRC功能,数值随便写
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;//双线全双工
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB  ;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master  ;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft  ;	
	
	SPI_Init(FLASH_SPIx,&SPI_InitStructure);	//写入配置到寄存器
	
	SPI_Cmd(FLASH_SPIx,ENABLE);//使能SPI
	
}
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge ;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High ;

在这里插入图片描述

这段代码设置了 SPI 的时钟相位(Clock Phase),具体来说,SPI_CPHA_2Edge 表示在第二个时钟沿(第二个边沿)采样数据。让我们分解这个设置:

  • SPI_CPHA 是 SPI_InitTypeDef 结构体中的一个成员,用于配置 SPI 的时钟相位。
  • SPI_CPHA_2Edge 是一个预定义的常量,它表示在第二个时钟沿(2Edge)采样数据。

时钟相位(Clock Phase)决定了在时钟的哪个边沿数据应该被采样或变更。在 SPI 通信中,时钟相位通常有两个选项:第一个时钟沿(1Edge)和第二个时钟沿(2Edge)。

  • 当设置为 SPI_CPHA_1Edge 时,数据在第一个时钟沿(上升沿或下降沿)被采样或变更。
  • 当设置为 SPI_CPHA_2Edge 时,数据在第二个时钟沿被采样或变更。

在这个代码片段中,通过设置 SPI_CPHASPI_CPHA_2Edge,表明数据在第二个时钟沿被采样。这样的设置通常取决于与 SPI 设备通信的具体协议和要求。

综合一下这段代码是下降沿采样

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB  ;

这段代码设置了 SPI 数据传输的起始位。具体来说,SPI_FirstBit_MSB 表示数据传输的起始位是最高有效位(Most Significant Bit,MSB)。

在 SPI 数据传输中,每个字节都由多个位组成,通常是8位。字节中的最高有效位是二进制表示中的最左边的位,而最低有效位则是最右边的位。

通过设置 SPI_FirstBitSPI_FirstBit_MSB,代码指定了数据传输时先传输最高有效位,然后依次传输剩余的位。这通常符合大多数 SPI 设备和通信协议的约定,但在某些情况下,可能需要根据具体设备的要求进行调整。

发送并接受一个字节

static  uint32_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* Block communication and all processes */
  FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);
  
  return 0;
}
uint8_t SPI_FLASH_Send_Byte(uint8_t data)
{
	SPITimeout = SPIT_FLAG_TIMEOUT;
	//检查并等待至TX缓冲区为空
	while(SPI_I2S_GetFlagStatus(FLASH_SPIx,SPI_I2S_FLAG_TXE) == RESET)
	{
		if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
	}
	
	//程序执行到此处,TX缓冲区已空
	SPI_I2S_SendData (FLASH_SPIx,data);
	SPITimeout = SPIT_FLAG_TIMEOUT;
	//检查并等待至RX缓冲区为非空
	while(SPI_I2S_GetFlagStatus(FLASH_SPIx,SPI_I2S_FLAG_RXNE) == RESET)
	{
		if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
	}	
	//程序执行到此处,说明数据发送完毕,并接收到一字字节	
	return SPI_I2S_ReceiveData(FLASH_SPIx); 
    //返回的数据是他排出的

}

这段代码涉及 SPI 数据的发送和接收,以下是代码的主要步骤解释:

  1. 发送数据:

    SPI_I2S_SendData(FLASH_SPIx, data);
    

    通过调用 SPI_I2S_SendData 函数,将数据 data 发送到 SPI 设备。

  2. 等待接收缓冲区非空:

    SPITimeout = SPIT_FLAG_TIMEOUT;
    while(SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE) == RESET)
    {
        if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
    }
    

    这部分代码在一个循环中检查 SPI 接收缓冲区是否为非空(SPI_I2S_FLAG_RXNE 表示接收缓冲区非空)。循环会一直等待,直到接收缓冲区有数据或超时。

  3. 接收数据:

    return SPI_I2S_ReceiveData(FLASH_SPIx);
    

    一旦接收缓冲区非空,就调用 SPI_I2S_ReceiveData 函数从 SPI 设备接收数据,并将其返回。

通过 SPI 发送数据,然后等待接收缓冲区非空,最后从接收缓冲区中读取数据。在这个过程中,使用了超时机制来处理可能的等待超时情况。这样的代码结构常见于需要同步发送和接收数据的 SPI 通信场景。

读取字节

uint8_t SPI_FLASH_Read_Byte(void)
{
	return SPI_FLASH_Send_Byte(DUMMY); 
}

DUMMY可以是任意值,一般是0x00或0xFF,都出来后flash就没有这个数据了(实验得出)

读取ID号

//读取ID号
uint32_t SPI_Read_ID(void)
{
	uint32_t flash_id;
	
	//片选使能
	FLASH_SPI_CS_LOW;
	SPI_FLASH_Send_Byte(READ_JEDEC_ID);
	
	flash_id = SPI_FLASH_Send_Byte(DUMMY);

	flash_id <<= 8;
	
	flash_id |= SPI_FLASH_Send_Byte(DUMMY); 
	
	flash_id <<= 8;
	
	flash_id |= SPI_FLASH_Send_Byte(DUMMY); 
	
	FLASH_SPI_CS_HIGH;	
	
	return flash_id;
}

在这里插入图片描述

这段代码实现了通过 SPI 读取设备的 ID 号。以下是代码的主要步骤解释:

  1. 片选使能:

    FLASH_SPI_CS_LOW;
    

    通过将片选信号拉低,使能 SPI 设备。

  2. 发送读取 JEDEC ID 的命令:

    SPI_FLASH_Send_Byte(READ_JEDEC_ID);
    

    通过调用 SPI_FLASH_Send_Byte 函数发送读取 JEDEC ID 的命令。

  3. 读取 ID 号的三个字节:

    flash_id = SPI_FLASH_Send_Byte(DUMMY);
    flash_id <<= 8;
    flash_id |= SPI_FLASH_Send_Byte(DUMMY);
    flash_id <<= 8;
    flash_id |= SPI_FLASH_Send_Byte(DUMMY);
    

    通过调用 SPI_FLASH_Send_Byte 函数,依次读取三个字节的 ID 号。每次读取一个字节,然后将其左移相应的位数,最终组成一个 32 位的 ID 号。

  4. 片选失能:

    FLASH_SPI_CS_HIGH;
    

    通过将片选信号拉高,失能 SPI 设备。

  5. 返回读取到的 ID 号:

    return flash_id;
    

    将读取到的 32 位 ID 号作为函数的返回值。

这段代码通过 SPI 通信协议与外部设备进行交互,发送读取 JEDEC ID 的命令,接着读取返回的三个字节,最终组成一个完整的 32 位 ID 号。这样的操作通常用于识别连接的外部设备或验证设备的身份。

FLASH写入使能

在这里插入图片描述

void SPI_Write_Enable(void)
{
		//片选使能
	FLASH_SPI_CS_LOW;//拉低代表被选中
	SPI_FLASH_Send_Byte(WRITE_ENABLE);//写入赋能命令	 
	FLASH_SPI_CS_HIGH;//表示操作完毕	
}

在 SPI (Serial Peripheral Interface) 通信中,CS 通常指的是 Chip Select(芯片选择)信号。Chip Select 是一种用于选择特定从设备的信号,它告诉 SPI 总线上的从设备何时应该响应主设备的通信。

等待FLASH内部时序操作完成

void SPI_WaitForWriteEnd(void)
{
	uint8_t status_reg = 0;
	
	//片选使能
	FLASH_SPI_CS_LOW;
	SPI_FLASH_Send_Byte(READ_STATUS);//读取状态命令
	do
	{	
	status_reg = SPI_FLASH_Send_Byte(DUMMY);//获得Flash上寄存器的数据
	}
	while((status_reg & 0x01) == 1);
	
	FLASH_SPI_CS_HIGH;	
}

擦除FLASH指定扇区

void SPI_Erase_Sector(uint32_t addr)
{	
	SPI_Write_Enable();
		//片选使能
	FLASH_SPI_CS_LOW;
	SPI_FLASH_Send_Byte(ERASE_SECTOR);
	
	SPI_FLASH_Send_Byte((addr>>16)&0xff);
	
	SPI_FLASH_Send_Byte((addr>>8)&0xff); 
	
  	SPI_FLASH_Send_Byte(addr&0xff); 
	
	FLASH_SPI_CS_HIGH;	
	
	SPI_WaitForWriteEnd();
	
}

SPI_FLASH_Send_Byte(ERASE_SECTOR);

写入擦除命令。

	SPI_FLASH_Send_Byte((addr>>16)&0xff);
	
	SPI_FLASH_Send_Byte((addr>>8)&0xff); 
	
  	SPI_FLASH_Send_Byte(addr&0xff); 

地址由三个字节组成所以用这种方法。

读取和写

//读取FLASH的内容
void SPI_Read_Data(uint32_t addr,uint8_t *readBuff,uint32_t numByteToRead)
{
		//片选使能
	FLASH_SPI_CS_LOW;
	SPI_FLASH_Send_Byte(READ_DATA);
	
	SPI_FLASH_Send_Byte((addr>>16)&0xff);
	
	SPI_FLASH_Send_Byte((addr>>8)&0xff); 
	
  SPI_FLASH_Send_Byte(addr&0xff); 
	
	while(numByteToRead--)
	{
        //这段代码是为了激活时钟信号
		*readBuff = SPI_FLASH_Send_Byte(DUMMY);
		readBuff++;
	}
	
	
	FLASH_SPI_CS_HIGH;	
	
}




//向FLASH写入内容
//读取FLASH的内容
//写入数据前都要擦除
void SPI_Write_Data(uint32_t addr,uint8_t *writeBuff,uint32_t numByteToWrite)
{
	SPI_Write_Enable();
		//片选使能
	FLASH_SPI_CS_LOW;
	SPI_FLASH_Send_Byte(WRITE_DATA);
	
	SPI_FLASH_Send_Byte((addr>>16)&0xff);
	
	SPI_FLASH_Send_Byte((addr>>8)&0xff); 
	
 	SPI_FLASH_Send_Byte(addr&0xff); 
	
	while(numByteToWrite--)
	{	
		SPI_FLASH_Send_Byte(*writeBuff);
		writeBuff++;
	}
	
	
	FLASH_SPI_CS_HIGH;	
	SPI_WaitForWriteEnd();
}

写入数据前都要擦除!

写入数据前都要擦除!

写入数据前都要擦除!

因为SPI中数据默认为0xFF,需要自己去擦除,不会在写入时自动擦除!
取FLASH的内容

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

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

相关文章

【Python】paddleocr快速使用及参数详解

文章目录 1. paddleocr快速使用1.1 使用默认模型路径1.2 设定模型路径 2. PaddleOCR其他参数介绍PaddleOCR模型推理参数解释 其它相关推荐&#xff1a; PaddleOCR模型训练及使用详细教程 官方网址&#xff1a;https://github.com/PaddlePaddle/PaddleOCR PaddleOCR是基于Paddle…

【软考问题】-- 3 - 知识精讲 - 项目整合管理

一、基本问题 1&#xff1a;项目章程的内容包括什么&#xff1f;&#xff08;助记&#xff1a;疯木鱼-要进庙里-发神经&#xff09; 疯&#xff1a;项目整体风险木&#xff1a;项目目标鱼&#xff1a;整体预算要&#xff1a;概要设计进&#xff1a;总体里程碑进度庙&#xff1a…

深度学习(4)--Keras安装

目录 Keras安装: 1.1.安装CUDA/cuDDN工具包 1.1.1.安装前准备 1.1.2.安装CUDA 1.1.3.安装cuDDN 1.2.安装Anaconda 1.3.安装tensorflow框架 1.3.1.使用cmd安装 1.3.2.使用Anaconda Prompt安装 1.4.安装Keras框架 1.5.打开jupyter notebook&#xff0c;执行import调用…

Linux/Academy

Enumeration nmap 首先扫描目标端口对外开放情况 nmap -p- 10.10.10.215 -T4 发现对外开放了22,80,33060三个端口&#xff0c;端口详细信息如下 结果显示80端口运行着http&#xff0c;且给出了域名academy.htb&#xff0c;现将ip与域名写到/et/hosts中&#xff0c;然后从ht…

Redis数据结构与底层实现揭秘

在高并发的系统开发中&#xff0c;缓存和高效的数据存储机制对于提升应用性能至关重要。Redis&#xff0c;作为其中的佼佼者&#xff0c;以其卓越的性能和丰富的数据结构赢得了开发者的青睐。本文将深入探讨Redis的数据结构及其底层实现&#xff0c;带领读者走进这个高性能数据…

【云原生】Docker的镜像创建

目录 1&#xff0e;基于现有镜像创建 &#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改 ​编辑&#xff08;2&#xff09;然后将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新镜像 实验 2&#xff0e;基于本地模板创建 3&am…

【网站项目】基于SSM的249作业提交与查收系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【Python爬虫入门到精通】小白也能看懂的知识要点与学习路线

文章目录 1. 写在前面2. 爬虫行业情况3. 学习路线 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋友可以关…

计数指针:shared_ptr (共享指针)与函数 笔记

推荐B站视频&#xff1a; 4.shared_ptr计数指针_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV18B4y187uL?p4&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 5.shared_ptr与函数_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV18B4y187uL?p5&vd_sourcea…

AI引爆算力需求,思腾推出支持大规模深度学习训练的高性能AI服务器

近日人工智能研究公司OpenAI公布了其大型语言模型的最新版本——GPT-4&#xff0c;可10秒钟做出一个网站&#xff0c;60秒做出一个游戏&#xff0c;参加了多种基准考试测试&#xff0c;它的得分高于88%的应试者&#xff1b;随后百度CEO李彦宏宣布正式推出大语言模型“文心一言”…

扫雷游戏——数组和函数实现

扫雷游戏的功能说明 使⽤控制台实现经典的扫雷游戏 游戏可以通过菜单实现继续玩或者退出游戏扫雷的棋盘是9*9的格⼦ 默认随机布置10个雷可以排查雷如果位置不是雷&#xff0c;就显⽰周围有⼏个雷如果位置是雷&#xff0c;就炸死游戏结束把除10个雷之外的所有⾮雷都找出来&…

域名缩短平台搭建

前言 当自己搭建的项目和网站相关文章的链接过长&#xff0c;可以参考一下本文搭建的平台 遵纪守法&#xff0c;不要乱缩网址。 代码&#xff1a; https://github.com/dyanst/shorturlhttps://github.com/dyanst/shorturl shorturl-main.zip官方版下载丨最新版下载丨绿色版…

Linux(linux版本 centos 7) 下安装 oracle 19c详细教程(新手小白易上手)

一、安装前准备 1、下载预安装包 wget http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm预安装包下载成功 2、下载oracle安装包 下载地址如下 https://www.oracle.com/cn/database/technologies…

Maven命令运行单元测试

使用idea开发多模块项目时,有时别的模块编译不通过会导致不能运行单元测试,这是我们可以使用maven命令来运行单元测试 格式 mvn -DtestDingTalkTest#getAllUsers 命令说明 mvn -Dtest 固定格式 DingTalkTest 单元测试类名 getAllUsers 单元测试方法 单元测试类和单元测试方法…

【LUA】mac状态栏添加天气

基于网络上的版本修改的&#xff0c;找不到出处了。第一个摸索的lua脚本&#xff0c;调了很久。 主要修改&#xff1a;如果风速不大&#xff0c;就默认不显示&#xff0c;以及调整为了一些格式 local urlApi http://.. --这个urlApi去申请个免费的就可以了 然后打开对应的json…

云轴科技ZStack成为交通运输业上云用云推进中心首批成员单位

近日&#xff0c;中国信息通信研究院、中国交通运输协会信息专业委员会联合发起成立“交通运输业上云用云推进中心”&#xff0c;上海云轴信息科技有限公司&#xff08;简称云轴科技ZStack&#xff09;凭借优秀的产品技术创新能力和在交通运输领域的实践经验成为首批成员单位并…

《安富莱嵌入式周报》第331期:单片机实现全功能软件无线电,开源电源EEZ升级主控,ARM 汇编用户指南,UDS统一诊断服务解析,半导体可靠性设计手册

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 目录&#xff1a; 1、单片机实现低配版全功能软件无线电&#xff0c;范围0.5-30 MHz&#xff0c;支持SSB、AM、FM和CW …

浅谈电气火灾监控系统应用在某地铁车站

安科瑞电气股份有限公司 上海嘉定201801 摘要&#xff1a;根据国家有关规范对建筑电气火灾监测系统设置的要求&#xff0c;结合当地城市地铁供配电方案的特点&#xff0c;介绍了地铁站电气火灾监测系统设置方案&#xff0c;从电气火灾探测器的选择和位置设置、电气火灾监测设备…

Java项目:SSM框架基于spring+springmvc+mybatis实现的心理预约咨询管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm823基于SSM框架的心理预约咨询管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&am…

WWDG喂狗

3F 是0111111 40 是1000000 0X7F 127 0X5F 95 127-9532 注意:中断是在0x40,在0x40喂狗则程序不会复位 在0x5F之前喂狗会复位,减小到63以下也会复位 在0x5F与0x3F之间喂狗会继续执行,不会复位 WWDG_HandleTypeDef WWDG_Handler; //窗口看门狗句柄//初始化窗口看门狗…