【STM32 HAL库】全双工I2S+双缓冲DMA的使用

1、配置I2S

我们的有效数据是32位的,使用飞利浦格式。

在这里插入图片描述

2、配置DMA

在这里插入图片描述

**这里需要注意:**i2s的DR寄存器是16位的,如果需要发送32位的数据,是需要写两次DR寄存器的,所以DMA的外设数据宽度设置16位,而不是32位。

3、完善I2S文件

i2s.c和i2s.h文件都是MX自动生成的,并且生成MX_I2S3_Init函数进行了初始化,MX_I2S3_Init函数里面其实依次调用了HAL_I2S_Init库函数(和MCU不相关的初始化)和HAL_I2S_MspInit库函数(是个weak函数,和MCU相关的初始化)。所以,我们自己要写的代码也加到这个文件中。

/* USER CODE BEGIN Header */
/********************************************************************************* @file    i2s.c* @brief   This file provides code for the configuration*          of the I2S instances.******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "i2s.h"/* USER CODE BEGIN 0 */
#include "stdio.h"#define  TX_DATA_16                 (0x1234)
#define  TX_DATA_32                 (0x12345678)
#define  HALF_TX_BUFFER_SIZE        (256)
#define  TX_BUFFER_SIZE             (HALF_TX_BUFFER_SIZE*2)
uint32_t tx_buffer[TX_BUFFER_SIZE];/* USER CODE END 0 */I2S_HandleTypeDef hi2s3;
DMA_HandleTypeDef hdma_spi3_tx;/* I2S3 init function */
void MX_I2S3_Init(void)
{/* USER CODE BEGIN I2S3_Init 0 *///这里有一点需要注�???,i2s的DR�???16位的,�???以如果想发�??32位的数据,得写两次,//如果想发�???0x12345678,就得先发�???0x1234,再发�???0x5678(标准飞利浦格式是高位在前)//但是32位数组是小端�???,�???以就�???要重组一�???for(int i=0;i<TX_BUFFER_SIZE;i++){*(tx_buffer+i)= (TX_DATA_32<<16)|(TX_DATA_32>>16);}/* USER CODE END I2S3_Init 0 *//* USER CODE BEGIN I2S3_Init 1 *//* USER CODE END I2S3_Init 1 */hi2s3.Instance = SPI3;hi2s3.Init.Mode = I2S_MODE_MASTER_TX;hi2s3.Init.Standard = I2S_STANDARD_PHILIPS;hi2s3.Init.DataFormat = I2S_DATAFORMAT_32B;hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K;hi2s3.Init.CPOL = I2S_CPOL_HIGH;hi2s3.Init.ClockSource = I2S_CLOCK_PLL;hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;if (HAL_I2S_Init(&hi2s3) != HAL_OK){Error_Handler();}/* USER CODE BEGIN I2S3_Init 2 *//* USER CODE END I2S3_Init 2 */}void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};if(i2sHandle->Instance==SPI3){/* USER CODE BEGIN SPI3_MspInit 0 *//* USER CODE END SPI3_MspInit 0 *//** Initializes the peripherals clock*/PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK){Error_Handler();}/* I2S3 clock enable */__HAL_RCC_SPI3_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**I2S3 GPIO ConfigurationPA4     ------> I2S3_WSPC7     ------> I2S3_MCKPC10     ------> I2S3_CKPC12     ------> I2S3_SD*/GPIO_InitStruct.Pin = WCK_Pin;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;HAL_GPIO_Init(WCK_GPIO_Port, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_7|BCK_Pin|DI_Pin;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* I2S3 DMA Init *//* SPI3_TX Init */hdma_spi3_tx.Instance = DMA1_Stream5;hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0;hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;hdma_spi3_tx.Init.Mode = DMA_CIRCULAR;hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW;hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_spi3_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(i2sHandle,hdmatx,hdma_spi3_tx);/* USER CODE BEGIN SPI3_MspInit 1 *//* USER CODE END SPI3_MspInit 1 */}
}void HAL_I2S_MspDeInit(I2S_HandleTypeDef* i2sHandle)
{if(i2sHandle->Instance==SPI3){/* USER CODE BEGIN SPI3_MspDeInit 0 *//* USER CODE END SPI3_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI3_CLK_DISABLE();/**I2S3 GPIO ConfigurationPA4     ------> I2S3_WSPC7     ------> I2S3_MCKPC10     ------> I2S3_CKPC12     ------> I2S3_SD*/HAL_GPIO_DeInit(WCK_GPIO_Port, WCK_Pin);HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7|BCK_Pin|DI_Pin);/* I2S3 DMA DeInit */HAL_DMA_DeInit(i2sHandle->hdmatx);/* USER CODE BEGIN SPI3_MspDeInit 1 *//* USER CODE END SPI3_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */int I2S_DMA_Start_Transmit()
{return HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)tx_buffer, TX_BUFFER_SIZE);
}int I2S_DMA_Stop()
{return HAL_I2S_DMAStop(&hi2s3);
}/*** @brief  Tx Transfer Half completed callbacks* @param  hi2s pointer to a I2S_HandleTypeDef structure that contains*         the configuration information for I2S module* @retval None*/
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{printf("%s\r\n",__func__);/* Prevent unused argument(s) compilation warning */UNUSED(hi2s);for(int i=0;i<HALF_TX_BUFFER_SIZE;i++){*(tx_buffer+i)+=1;}/* NOTE : This function Should not be modified, when the callback is needed,the HAL_I2S_TxHalfCpltCallback could be implemented in the user file*/
}/*** @brief  Tx Transfer completed callbacks* @param  hi2s pointer to a I2S_HandleTypeDef structure that contains*         the configuration information for I2S module* @retval None*/
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{printf("%s\r\n",__func__);/* Prevent unused argument(s) compilation warning */UNUSED(hi2s);for(int i=0;i<HALF_TX_BUFFER_SIZE;i++){*(tx_buffer+HALF_TX_BUFFER_SIZE+i)-=1;}/* NOTE : This function Should not be modified, when the callback is needed,the HAL_I2S_TxCpltCallback could be implemented in the user file*/
}/*** @brief  I2S error callbacks* @param  hi2s pointer to a I2S_HandleTypeDef structure that contains*         the configuration information for I2S module* @retval None*/
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
{/* Prevent unused argument(s) compilation warning */printf("HAL_I2S_Error\r\n");/* NOTE : This function Should not be modified, when the callback is needed,the HAL_I2S_ErrorCallback could be implemented in the user file*/
}/* USER CODE END 1 */
  1. 其实这里使用了DMA双buffer的思路,但是我没有使用双buffer,而是一个buffer的前后部分。当TxHalfCplt的时候,我们去更新buffer前半部分数据,当TxCplt的时候,我们去更新buffer的后半部分数据。HAL库没有很好封装DMA双buffer的配置函数。
  2. 关于DMA的buffer填充问题,I2S的DR寄存器是15位的,所以配置DMA的数据宽度也是16位的,如果I2S是32位的数据格式,那么需要写两次DR寄存器才能组一帧I2S数据,例如I2S想发送0x12345678,那么就得先发送0x1234,再发送0x5678(I2S飞利浦格式就是这样,高位在前),所以填充buffer的时候,也得按该顺序填充。
  3. 关于全双工DMA的封装,HAL好像也没有很好的支持,等下次再介绍。。。

在这里插入图片描述

4、I2S实现DMA双buffer发送

我们如果看过HAL库接口的话,就应该知道。在dma_ex文件中封装了DMA双buffer的接口,但是在i2s文件或者i2s_ex中没有封装双buffer的接口。所以,我们打算仿照HAL_I2S_Transmit_DMA库函数实现一个函数。

/* USER CODE BEGIN 1 */
static void I2S_DMAM0TxHalfCplt(DMA_HandleTypeDef *hdma)
{I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 *//* Call user Tx half complete callback */printf("%s\r\n",__func__);
}static void I2S_DMAM0TxCplt(DMA_HandleTypeDef *hdma)
{I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 *//* Call user Tx complete callback */printf("%s\r\n",__func__);
}static void I2S_DMAM1TxHalfCplt(DMA_HandleTypeDef *hdma)
{I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 *//* Call user Tx half complete callback */printf("%s\r\n",__func__);
}static void I2S_DMAM1TxCplt(DMA_HandleTypeDef *hdma)
{I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 *//* Call user Tx complete callback */printf("%s\r\n",__func__);
}static void I2S_DMA_Error(DMA_HandleTypeDef *hdma)
{I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */printf("%s\r\n",__func__);
}static HAL_StatusTypeDef HAL_I2S_Transmit_DMA_DBuffer(I2S_HandleTypeDef *hi2s, uint16_t *pData0,uint16_t *pData1, uint16_t Size)
{uint32_t tmpreg_cfgr;if ((pData0 == NULL) || (Size == 0U)){return  HAL_ERROR;}/* Process Locked */__HAL_LOCK(hi2s);if (hi2s->State != HAL_I2S_STATE_READY){__HAL_UNLOCK(hi2s);return HAL_BUSY;}/* Set state and reset error code */hi2s->State = HAL_I2S_STATE_BUSY_TX;hi2s->ErrorCode = HAL_I2S_ERROR_NONE;hi2s->pTxBuffPtr = pData0;tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)){hi2s->TxXferSize = (Size << 1U);hi2s->TxXferCount = (Size << 1U);}else{hi2s->TxXferSize = Size;hi2s->TxXferCount = Size;}/* Set the I2S Tx DMA Half transfer complete callback */hi2s->hdmatx->XferHalfCpltCallback = I2S_DMAM0TxHalfCplt;/* Set the I2S Tx DMA transfer complete callback */hi2s->hdmatx->XferCpltCallback = I2S_DMAM0TxCplt;hi2s->hdmatx->XferM1HalfCpltCallback=I2S_DMAM1TxHalfCplt;//callbackhi2s->hdmatx->XferM1CpltCallback=I2S_DMAM1TxCplt;//callback/* Set the DMA error callback */hi2s->hdmatx->XferErrorCallback = I2S_DMA_Error;/* Enable the Tx DMA Stream/Channel */if (HAL_OK != HAL_DMAEx_MultiBufferStart_IT(hi2s->hdmatx,(uint32_t)hi2s->pTxBuffPtr,(uint32_t)&hi2s->Instance->DR,(uint32_t)pData1,hi2s->TxXferSize)){/* Update SPI error code */SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);hi2s->State = HAL_I2S_STATE_READY;__HAL_UNLOCK(hi2s);return HAL_ERROR;}/* Check if the I2S is already enabled */if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)){/* Enable I2S peripheral */__HAL_I2S_ENABLE(hi2s);}/* Check if the I2S Tx request is already enabled */if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_TXDMAEN)){/* Enable Tx DMA Request */SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);}__HAL_UNLOCK(hi2s);return HAL_OK;
}

注意几点:

  1. 这些函数还是写在i2s.c文件中。
  2. 相比原函数,在函数参数上多了一个buffer地址。
  3. 原函数中的回调函数都是本地函数,不供其他文件调用,所以全部重新定义在我们的本文件中。并且多了m1 buffer的回调函数。
  4. DMA_Start函数更换为双buffer函数接口。其他的地方都没有改变。
    在这里插入图片描述
    在这里插入图片描述

5、全双工I2S实现

在这里插入图片描述
配置全双工Master模式,其实看源码就知道,当配置全双工的时候,用到了两个i2s外设。
在这里插入图片描述
如果我们配置i2s为Master_Tx,那么i2s_ex就会自动被配置为Slave_Rx。当然,这些在HAL库中都已经封装好了,我们使用起来还是不麻烦的。
但是,HAL库封装的函数很奇怪,所以我们仿照原库函数自己修改了一下。

static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
{printf("%s\r\n",__func__);
}static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
{printf("%s\r\n",__func__);
}static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
{printf("%s\r\n",__func__);
}static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
{printf("%s\r\n",__func__);
}static HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_DMA_Modify(I2S_HandleTypeDef *hi2s,uint16_t *pTxData,uint16_t *pRxData,uint16_t Size)
{uint32_t *tmp = NULL;uint32_t tmp1 = 0U;HAL_StatusTypeDef errorcode = HAL_OK;if (hi2s->State != HAL_I2S_STATE_READY){errorcode = HAL_BUSY;goto error;}if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)){return  HAL_ERROR;}/* Process Locked */__HAL_LOCK(hi2s);hi2s->pTxBuffPtr = pTxData;hi2s->pRxBuffPtr = pRxData;tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);/* Check the Data format: When a 16-bit data frame or a 16-bit data frame extendedis selected during the I2S configuration phase, the Size parameter means the numberof 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit dataframe is selected the Size parameter means the number of 16-bit data length. */if ((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B)){hi2s->TxXferSize  = (Size << 1U);hi2s->TxXferCount = (Size << 1U);hi2s->RxXferSize  = (Size << 1U);hi2s->RxXferCount = (Size << 1U);}else{hi2s->TxXferSize  = Size;hi2s->TxXferCount = Size;hi2s->RxXferSize  = Size;hi2s->RxXferCount = Size;}hi2s->ErrorCode = HAL_I2S_ERROR_NONE;hi2s->State     = HAL_I2S_STATE_BUSY_TX_RX;/* Set the I2S Rx DMA Half transfer complete callback */hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;/* Set the I2S Rx DMA transfer complete callback */hi2s->hdmarx->XferCpltCallback  = I2S_DMARxCplt;/* Set the I2S Rx DMA error callback */hi2s->hdmarx->XferErrorCallback = NULL;/* Set the I2S Tx DMA Half transfer complete callback as NULL */hi2s->hdmatx->XferHalfCpltCallback  = I2S_DMATxHalfCplt;/* Set the I2S Tx DMA transfer complete callback as NULL */hi2s->hdmatx->XferCpltCallback  = I2S_DMATxCplt;/* Set the I2S Tx DMA error callback */hi2s->hdmatx->XferErrorCallback = NULL;tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG;/* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */if ((tmp1 == I2S_MODE_MASTER_TX) || (tmp1 == I2S_MODE_SLAVE_TX)){/* Enable the Rx DMA Stream */tmp = (uint32_t *)&pRxData;HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, *(uint32_t *)tmp, hi2s->RxXferSize);/* Enable Rx DMA Request */SET_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_RXDMAEN);/* Enable the Tx DMA Stream */tmp = (uint32_t *)&pTxData;HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t *)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize);/* Enable Tx DMA Request */SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);/* Check if the I2S is already enabled */if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE){/* Enable I2Sext(receiver) before enabling I2Sx peripheral */__HAL_I2SEXT_ENABLE(hi2s);/* Enable I2S peripheral after the I2Sext */__HAL_I2S_ENABLE(hi2s);}}else{/* Check if Master Receiver mode is selected */if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX){/* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a readaccess to the SPI_SR register. */__HAL_I2S_CLEAR_OVRFLAG(hi2s);}/* Enable the Tx DMA Stream */tmp = (uint32_t *)&pTxData;HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t *)tmp, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, hi2s->TxXferSize);/* Enable Tx DMA Request */SET_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_TXDMAEN);/* Enable the Rx DMA Stream */tmp = (uint32_t *)&pRxData;HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t *)tmp, hi2s->RxXferSize);/* Enable Rx DMA Request */SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);/* Check if the I2S is already enabled */if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE){/* Enable I2Sext(transmitter) before enabling I2Sx peripheral */__HAL_I2SEXT_ENABLE(hi2s);/* Enable I2S peripheral before the I2Sext */__HAL_I2S_ENABLE(hi2s);}}error :__HAL_UNLOCK(hi2s);return errorcode;
}

相比原函数,我们就修改了一个地方,那就是把TX的回调函数也赋值了,其实这里不理解的地方有两个:

  1. 为什么不给TX的回调函数赋值
  2. 为什么RX的回调函数命名TxRx的回调函数
    我们在实验中直接将DI接在DO上了,最后看看调试结果
    在这里插入图片描述
    最后,如果想在全双工中使用DMA双buffer,可以仿照上文中函数的修改即可,这里就不做示范了。

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

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

相关文章

一文带你读懂MLIR论文,理解MLIR设计准则.

论文MLIR: Scaling Compiler Infrastructure for Domain Specific Computation MLIR&#xff1a;针对特定领域计算扩展编译器基础设施 文章目录 论文MLIR: Scaling Compiler Infrastructure for Domain Specific Computation1. 论文下载2. TVM关于MLIR的讨论3. 论文正文0. 摘要…

02互联网行业的产品方向(2)

数字与策略产品 大数据时代&#xff0c;数据的价值越来越重要。大多数公司开始对内外全部数据进行管理与挖掘&#xff0c;将业务数据化&#xff0c;数据资产化&#xff0c;资产业务化&#xff0c;将数据产品赋能业务&#xff0c;通过数据驱动公司业务发展&#xff0c;支撑公司战…

Unity VR开发入门:探索虚拟现实世界的无限可能

目录 引言 Unity VR开发基础 1. 安装Unity与VR SDK 2. 创建VR项目 3. 理解VR场景结构 Unity VR开发实战 1. 场景搭建 2. 交互设计 创建C#脚本 编写VRInteractor脚本 应用脚本到场景 注意 修改VRInteractor脚本 3. 用户体验优化 4. 测试与调试 引言 随着科技的飞速…

docker: No space left on device处理与迁移目录

简介&#xff1a;工作中当遇到Docker容器内部的磁盘空间已满。可能的原因包括日志文件过大、临时文件过多或者是Docker容器的存储卷已满&#xff0c;需要我们及时清理相关文件&#xff0c;并对docker的路径进行迁移。 历史攻略&#xff1a; centos&#xff1a;清理磁盘空间 …

记录些MySQL题集(17)

一、MySQL索引为何使用B树结构&#xff1f; MySQL的索引机制中&#xff0c;默认使用BTree作为底层的数据结构&#xff0c;但为什么要选择B树呢&#xff1f;有人会说树结构是以二分法查找数据&#xff0c;所以会在很大程度上提升检索性能&#xff0c;这点确实没错&#xff0c;但…

C++初学者指南-5.标准库(第一部分)--标准库查询存在算法

C初学者指南-5.标准库(第一部分)–标准库查询存在算法 文章目录 C初学者指南-5.标准库(第一部分)--标准库查询存在算法any_of / all_of / none_ofcountcount_if相关内容 不熟悉 C 的标准库算法&#xff1f; ⇒ 简介 any_of / all_of / none_of 如果在输入范围(所有元素…

解决django与sqlite3不兼容报SQLite 3.9.0 or later is required错的问题

今天在尝试用pytest进行django的单元测试&#xff0c;pytest用的数据库是sqlite3&#xff0c;在window环境下测试得好好的&#xff0c;但是放到linux环境下就报错&#xff0c;具体是报django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found …

GPT-LLM

本心、输入输出、结果 文章目录 GPT-LLM前言国际公司AI发展概览国内公司AI发展概览GPT-LLM 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 如果觉得本文对你有帮助,欢迎点赞、收藏、评论 前言 国际公司AI发展概览 公司主要AI贡献与产品特点OpenAI…

【LeetCode】day17:654 - 最大二叉树, 617 - 合并二叉树, 700 - 二叉树搜索树中的搜索, 98 - 验证二叉搜索树

LeetCode 代码随想录跟练 Day17 654.最大二叉树617.合并二叉树700.二叉搜索树中的搜索98.验证二叉搜索树 654.最大二叉树 题目描述&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的…

SpringBoot整合SSE,实现后端主动推送DEMO

前言 说起服务端主动推送&#xff0c;大家第一个想到的一定是WEBSOCKET 。 作为软件工程师&#xff0c;不能无脑使用一种技术&#xff0c;要结合实际情况&#xff0c;择优选取。 SSE&#xff08;Server-Sent Events&#xff09;相比于WEBSOCKET 1、轻量化、兼容性 基于传统…

pytorch学习(十二)c++调用minist训练的onnx模型

在实际使用过程中&#xff0c;使用python速度不够快&#xff0c;并且不太好嵌入到c程序中&#xff0c;因此可以把pytorch训练的模型转成onnx模型&#xff0c;然后使用opencv进行调用。 所需要用到的库有&#xff1a; opencv 1.完整的程序如下 import torch from torch impo…

零基础STM32单片机编程入门(十七)SPI总线详解及RC522-NFC刷卡模块实战含源码

文章目录 一.概要二.SPI总线基本概念1.SPI总线内部框图2.总体特征3.通讯时序 三.RC522介绍1.NFC基本介绍2.RC522模块基本特点3.RC522模块原理图4.RC522模块SPI通讯时序 四.RC522模块读卡实验五.CubeMX工程源代码下载六.小结 一.概要 SPI总线是由Motorola公司提出&#xff0c;是…

05_解封装和解码

1. 基本概念 容器就是一种文件格式&#xff0c;比如flv、mkv、mp4等。包含下面5种流以及文件头信息。 流是一种视频数据信息的传输方式&#xff0c;5种流&#xff1a;音频&#xff0c;视频&#xff0c;字幕&#xff0c;附件&#xff0c;数据。 包在ffmpeg中代表已经编码好的一…

FPGA实验3:D触发器设计

一、实验目的及要求 熟悉Quartus II 的 VHDL 文本设计简单时序电路的方法&#xff1b; 掌握时序电路的描述方法、波形仿真和测试&#xff0c;特别是时钟信号的特性。 二、实验原理 运用Quartus II 集成环境下的VHDL文本设计方法设计简单时序电路——D触发器&#xff0c;依据…

三相PWM整流器滞环电流控制仿真matlab simulink

1、内容简介 略 88-可以交流、咨询、答疑 2、内容说明 略 三相&#xff30;&#xff37;&#xff2d;整流器已广泛应用工业与电气控制领域电流控制技术决定着三相&#xff30;&#xff37;&#xff2d;整流器系统的控制性能。综合比 较了各种电流控制方法应用较多的滞环比较…

C++ 类和对象 构造函数(下)

一 初始化列表&#xff1a; 1.1 构造函数体赋值&#xff1a; 在C中&#xff0c;构造函数用于创建对象并赋予其初始值。通常&#xff0c;我们可以在构造函数体内对成员变量进行赋值&#xff1a; class Date { public:Date(int year, int month, int day) {_year year;_mont…

golang 解压带密码的zip包

目录 Zip文件详解ZIP 文件格式主要特性常用算法Zip格式结构图总览Zip文件结构详解数据区本地文件头文件数据文件描述 中央目录记录区&#xff08;核心目录记录区 &#xff09;中央目录记录尾部区 压缩包解压过程方式1 通过解析中央目录区来解压方式2 通过读取本地文件头来解压两…

[言简意赅] Matlab生成FPGA端rom初始化文件.coe

&#x1f38e;Matlab生成FPGA端rom初始化文件.coe 本文主打言简意赅。 函数源码 function gencoeInitialROM(width, depth, signal, filepath)% gencoeInitialROM - 生成 Xilinx ROM 初始化格式的 COE 文件%% 输入参数:% width - ROM 数据位宽% depth - ROM 数据深度% s…

heic文件怎么转换成jpg?上百份文件转换3秒就能搞定(办公必备)

heic和jpg是两种不同的图片格式&#xff0c;平时整理图片素材时&#xff0c;如果需要将heic转为jpg格式&#xff0c;那么可以使用相关的heic图片转换工具。 ​ 为什么要将heic文件转换成jpg&#xff1f;虽然HEIC格式具有很多优点&#xff0c;但是目前并不是所有设备和应用程序…

好玩模拟游戏推荐:缺氧:眼冒金星 单机游戏分享

《缺氧》 是一款太空殖民模拟游戏。 在外太空岩深处&#xff0c;你手下的勤劳开拓者们需要熟练掌握科技&#xff0c;战胜新的陌生生命形式&#xff0c;以及利用难以置信的太空技术来生存。甚至&#xff0c;还有可能繁荣起来。 建立广阔的基地以及探索生存所需的资源&#xff1…