STM32基础教程——DMA+ADC多通道

目录

前言

​编辑

技术实现

 连线图

代码实现 

技术要点

实验结果

问题记录


前言

DMA(Direct Memory Access)直接存储器存取,用来提供在外设和存储器 之间或者存储器和存储器之间的高速数据传输。无需CPU干预,数据可以通过DMA快速地移动,这样可以节省CPU的资源进行其他操作。两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自与一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。

DMA的主要特性

  • 12个独立的可配置的通道(请求):DMA1有7个 通道,DMA2有5个通道
  • 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
  • 在同一个DMA模块上多个请求见的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先与请求1,以此类推)。
  • 独立数据源和目标数据区的传输字节宽度(字节、半字、字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
  • 支持循环的缓冲器管理
  • 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这三个事件标志逻辑或成为一个单独的中断请求。
  • 存储器和存储器之间的传输。
  • 外设和存储器、存储器和外设之间的传输。
  • Flash、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。
  • 可编程的数据传输数目。

 ADC(Analog-Digital Converter模拟-数字转换器,ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁.12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和两个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐对齐方式存储在16位数据寄存器中。

逐次逼近型ADC通过二进制搜索算法逐步确定输入模拟信号的数值,具体步骤如下:

  1. 初始化
    • 逐次逼近寄存器(SAR)将最高有效位(MSB)设为1,其余位设为0,形成一个初始猜测值。
    • 该值通过内部DAC(数模转换器)转换为模拟电压,并与输入信号进行比较。
  2. 比较与调整
    • 比较器将DAC输出的电压与输入模拟信号进行比较:
      • 若DAC电压 < 输入电压 → 保持该位为1,继续测试下一位(次高位)。
      • 若DAC电压 > 输入电压 → 将该位清零(设为0),继续测试下一位。
    • 重复上述步骤,逐位确定每一位的值(从MSB到LSB),直到所有位完成判断。
  3. 输出结果
    • 最终,SAR寄存器中保存的二进制数值即为输入模拟信号的数字表示。

ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。

ADC主要特征:

        ● 12位分辨率
        ● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断
        ● 单次和连续转换模式
        ● 从通道0到通道n的自动扫描模式
        ● 自校准
        ● 带内嵌数据一致性的数据对齐
        ● 采样间隔可以按通道分别编程
        ● 规则转换和注入转换均有外部触发选项
        ● 间断模式
        ● 双重模式(带2个或以上ADC的器件)
        ● ADC转换时间:
        ─
        STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
        ─
        STM32F101xx基本型产品:时钟为28MHz时为1μs(时钟为36MHz为1.55μs)
        ─
        STM32F102xxUSB型产品:时钟为48MHz时为1.2μs
        ─
        STM32F105xx和STM32F107xx产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
        ● ADC供电要求:2.4V到3.6V
        ● ADC输入范围:VREF- ≤ VIN ≤ VREF+
        ● 规则通道转换期间有DMA请求产生。

ADC功能描述:

        

        

技术实现

 连线图

代码实现 

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"						//延时函数
#include "OLED.h"
#include "AD.h"int main(void)
{/*OLED初始化*/OLED_Init();AD_Init();OLED_ShowString(1,1,"AD0:");OLED_ShowString(2,1,"AD1:");OLED_ShowString(3,1,"AD2:");OLED_ShowString(4,1,"AD3:");while(1){	AD_GetValue();OLED_ShowNum(1,5,AD_Value[0],4);OLED_ShowNum(2,5,AD_Value[1],4);OLED_ShowNum(3,5,AD_Value[2],4);OLED_ShowNum(4,5,AD_Value[3],4);}
}

 AD.h

#ifndef AD_H
#define AD_H#include "stm32f10x.h"extern uint16_t AD_Value[4];void AD_Init(void);
void AD_GetValue(void);#endif

 AD.c

#include "AD.h"uint16_t AD_Value[4];										//将数据存储在SRAM								/*** @brief  AD Initialization * @param  None* @retval None* @note   Initialize AD basic structure*/
void AD_Init(void)
{//开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);					//开启DMA时钟//配置ADC时钟 12MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AIN;                         //模拟输入GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);//配置ADC规则组输入通道ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_55Cycles5);//初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode                 = ADC_Mode_Independent;ADC_InitStruct.ADC_ScanConvMode         = ENABLE;                   		//扫描模式ADC_InitStruct.ADC_ContinuousConvMode   = DISABLE;                  		//单次转换ADC_InitStruct.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;		//软件触发,非外部触发ADC_InitStruct.ADC_DataAlign            = ADC_DataAlign_Right;      		//数据右对齐ADC_InitStruct.ADC_NbrOfChannel         = 4;                        		//共4个序列ADC_Init(ADC1,&ADC_InitStruct);//初始化DMA DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_BufferSize			= 4;								//缓冲区的大小,由于CNDTR寄存器的高16位保留,这里缓冲区大小的变量的大小使用//uint16_t即可DMA_InitStruct.DMA_DIR  				= DMA_DIR_PeripheralSRC; 			//外设站点是数据源DMA_InitStruct.DMA_MemoryBaseAddr 		= (uint32_t)AD_Value;				//存储器站点的基地址,将数据转运到SRAMDMA_InitStruct.DMA_MemoryDataSize		= DMA_MemoryDataSize_HalfWord;		//接收的数据以半字形式传输DMA_InitStruct.DMA_Mode					= DMA_Mode_Normal;				    //DAM传输计数器不使用自动重装模式DMA_InitStruct.DMA_M2M					= DMA_M2M_Disable;					//DMA为外设到存储器传输的方式,使用硬件触发DMA_InitStruct.DMA_MemoryInc			= DMA_MemoryInc_Enable;				//存储器站点自增DMA_InitStruct.DMA_PeripheralInc		= DMA_PeripheralInc_Disable;		//外设站点地址不自增DMA_InitStruct.DMA_PeripheralBaseAddr 	= (uint32_t)&ADC1->DR;				//ADC规则数据寄存器(ADC_DR)的地址为要传输的数据的基地址DMA_InitStruct.DMA_PeripheralDataSize	= DMA_PeripheralDataSize_HalfWord;	//传输的数据以半字节形式传输DMA_InitStruct.DMA_Priority				= DMA_Priority_VeryHigh;			//只有一个通道,DMA优先级随便选DMA_Init(DMA1_Channel1,&DMA_InitStruct);									//使用硬件触发,通道为固定的通道1,不可更改DMA_Cmd(DMA1_Channel1,ENABLE);ADC_DMACmd(ADC1,ENABLE);													//开启ADC的DMA触发源//关闭ADC电源ADC_Cmd(ADC1,DISABLE);//维持ADC处于掉电状态至少两个周期Delay_us(1);//ADC校准ADC_ResetCalibration(ADC1);                                         	//复位校准,将ADC_CR2寄存器中的RSTCAL位置1,初始化校准寄存器while(ADC_GetResetCalibrationStatus(ADC1));                         	//等待复位校准完成,校准寄存器被初始化后RSTAL位由硬件清零ADC_StartCalibration(ADC1);                                         	//AD校准,将ADC_CR2寄存器中的CAL位置1,开始校准while(ADC_GetCalibrationStatus(ADC1));                              	//等待AD校准完成,校准完成后CAL位由硬件清零//开启ADC电源ADC_Cmd(ADC1,ENABLE);
}/*** @brief  AD触发,DMA计数器赋值* @param  None* @retval None* @note   为DMA计数器重新赋值*/
void AD_GetValue(void)
{DMA_Cmd(DMA1_Channel1,DISABLE);											//DMA失能DMA_SetCurrDataCounter(DMA1_Channel1,4);								//传输计数器赋值,非自动重装模式,若使用自动重装模式,则只需在初始化中进行一次赋值DMA_Cmd(DMA1_Channel1,ENABLE);	ADC_SoftwareStartConvCmd(ADC1,ENABLE);                              	//ADC为单次转换模式,仍需软件触发AD转换。循环转换则只需在初始化时触发一次while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);						//等待DMA转运完成DMA_ClearFlag(DMA1_FLAG_TC1);
}

  OLED部分代码参照文章《STM32基础教程——OLED显示》http://【STM32基础教程 ——OLED显示 - CSDN App】https://blog.csdn.net/2301_80319641/article/details/145837521?sharetype=blog&shareId=145837521&sharerefer=APP&sharesource=2301_80319641&sharefrom=link

技术要点

//开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);					//开启DMA时钟

本实验设计到DMA和ADC1,而GPIO作为ADC1的通道,故应分别开启他们的时钟,ADC1和GPIO隶属于APB2外设,DMA隶属AHB外设。

//配置ADC时钟 12MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);

系统时钟为72MHz,这里分频因子选择6分频,经分频后ADC时钟为12MHz 。

ADC输入时钟有PCLK2分频得到,最大不得超过14MHz。

GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AIN;                         //模拟输入GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);

 由于进行AD转换,GPIO的输入量为模拟量,故应将GPIO的输入模式配置为模拟输入模式, 由于使用AD转换通道0,通道1,通道2,通道3,这里GPIO配置PA0、PA1、PA2、PA3引脚。AD通道与GPIO引脚对应见下图:

//配置ADC规则组输入通道ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_55Cycles5);

配置ADC多个输入通道。之前的ADC多通道是单次转换,非扫描模式,利用了多个通道,但是只利用了转换序列1.这里ADC使用单次转换,扫描模式。每次转换可以扫描多个通道,利用DMA,可以防止只有一个数据寄存器而数据无法及时运出导致多个通道转换后数据被覆盖。

//初始化ADCADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode                 = ADC_Mode_Independent;ADC_InitStruct.ADC_ScanConvMode         = ENABLE;                   //扫描模式ADC_InitStruct.ADC_ContinuousConvMode   = DISABLE;                  //单次转换ADC_InitStruct.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//软件触发,非外部触发ADC_InitStruct.ADC_DataAlign            = ADC_DataAlign_Right;      //数据右对齐ADC_InitStruct.ADC_NbrOfChannel         = 4;                        //共4个序列ADC_Init(ADC1,&ADC_InitStruct);

初始化ADC,将ADC设置为单次转换,扫描模式。同样触发方式选择软件触发,数据右对齐,要转换的ADC的通道的数量为4。

//初始化DMA DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_BufferSize			= 4;								//缓冲区的大小,由于CNDTR寄存器的高16位保留,这里缓冲区大小的变量的大小使用//uint16_t即可DMA_InitStruct.DMA_DIR  				= DMA_DIR_PeripheralSRC; 			//外设站点是数据源DMA_InitStruct.DMA_MemoryBaseAddr 		= (uint32_t)AD_Value;				//存储器站点的基地址,将数据转运到SRAMDMA_InitStruct.DMA_MemoryDataSize		= DMA_MemoryDataSize_HalfWord;		//接收的数据以半字形式传输DMA_InitStruct.DMA_Mode					= DMA_Mode_Normal;				    //DAM传输计数器不使用自动重装模式DMA_InitStruct.DMA_M2M					= DMA_M2M_Disable;					//DMA为外设到存储器传输的方式,使用硬件触发DMA_InitStruct.DMA_MemoryInc			= DMA_MemoryInc_Enable;				//存储器站点自增DMA_InitStruct.DMA_PeripheralInc		= DMA_PeripheralInc_Disable;		//外设站点地址自增DMA_InitStruct.DMA_PeripheralBaseAddr 	= (uint32_t)&ADC1->DR;				//ADC规则数据寄存器(ADC_DR)的地址为要传输的数据的基地址DMA_InitStruct.DMA_PeripheralDataSize	= DMA_PeripheralDataSize_HalfWord;	//传输的数据以半字节形式传输DMA_InitStruct.DMA_Priority				= DMA_Priority_VeryHigh;			//只有一个通道,DMA优先级随便选DMA_Init(DMA1_Channel1,&DMA_InitStruct);									//使用硬件触发,通道为固定的通道1,不可更改

将数据缓冲区(DMA通道的DMA缓存的大小)的大小设置为4。本实验是读取AD转换后的值,DMA转运的方向应为外设到存储器。结构体成员DMA_DIR指示数据传输方向,故其值设置为DMA_DIR_PeripheralSRC,即从存储器读。实验使用数组存储AD转换的值,故存储器地址设置为AD_Value,AD_Value为指向数组首地址的指针,其值为数组的地址,应强转为uint32_t类型。同时存储器站点自增。

ADC_DR寄存器为规则组转换的数据寄存器,存储的数据宽度为半字,故外设基地址设置为&ADC->DR外设和存储器的数据宽度都设置为半字。

DMA数据传输由外设到存储器,故结构体成员DMA_M2M的值应设置为DMA_M2M_Disable,且DMA由硬件触发(因为数据传输方向是外设到存储器)。

ADC_DMACmd(ADC1,ENABLE);													//开启ADC的DMA触发源

开启ADC的DMA触发源,通过ADC进行硬件触发DMA数据转运。

void AD_GetValue(void)
{DMA_Cmd(DMA1_Channel1,DISABLE);											//DMA失能DMA_SetCurrDataCounter(DMA1_Channel1,4);								//传输计数器赋值,非自动重装模式,若使用自动重装模式,则只需在初始化中进行一次赋值DMA_Cmd(DMA1_Channel1,ENABLE);	ADC_SoftwareStartConvCmd(ADC1,ENABLE);                              	//ADC为单次转换模式,仍需软件触发AD转换。循环转换则只需在初始化时触发一次while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);						//等待DMA转运完成DMA_ClearFlag(DMA1_FLAG_TC1);
}

ADC为单次转换模式,故每次循环开始转换前都应使用软件触发的方式触发ADC转换。

实验结果

DMA+ADC多通道

问题记录

1.江科大的教学视频中ADC校验是在开启ADC电源后开始校验,ADC校准应先关闭ADC电源并维持两个周期以上,然后开启ADC电源。

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

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

相关文章

23黑马产品经理Day01

今天过了一遍23黑马产品经理的基础视频 问题思考维度 抓住核心用户 为什么需要抓住核心用户&#xff1f; 主要原因&#xff1a;用户越来越细分&#xff0c;保持市场竞争力&#xff0c;产品开发推广更聚焦 做产品为什么要了解用户&#xff1a;了解用户的付费点&#xff0c;…

C/C++ 通用代码模板

✅ C 语言代码模板&#xff08;main.c&#xff09; 适用于基础项目、算法竞赛或刷题&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <math.h>// 宏定义区 #define MAX_N 1000 #defi…

【数据结构_7】栈和队列(上)

一、概念 栈和队列&#xff0c;也是基于顺序表和链表实现的 栈是一种特殊的线性表&#xff0c;其只允许在固定的一段进行插入和删除元素操作。 遵循后进先出的原则 此处所见到的栈&#xff0c;本质上就是一个顺序表/链表&#xff0c;但是&#xff0c;实在顺序表/链表的基础…

git UserInterfaceState.xcuserstate 文件频繁更新

1> 退出 Xcdoe&#xff0c;打开终端&#xff08;Terminal&#xff09;&#xff0c;进入到你的项目目录下。 2> 在终端键入 git rm --cached <YourProjectName>.xcodeproj/project.xcworkspace/xcuserdata/<YourUsername>.xcuserdatad/UserInterfaceState.x…

【Ai】MCP实战:手写 client 和 server [Python版本]

什么是mcp MCP 是一个开放协议&#xff0c;它为应用程序向 LLM 提供上下文的方式进行了标准化。你可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化的方式一样&#xff0c;MCP 为 AI 模型连接各种数据源和工具提供了标准化的接口…

ESP8266/32作为AVR编程器(ISP programmer)的使用介绍

ESP8266作为AVR编程器( ISP programmer)的使用介绍 &#x1f33f;ESP8266自带库例程&#xff1a;https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266AVRISP&#x1f4cd;支持ESP8266/32的ESP_AVRISP其它开源工程&#xff08;个人没有再去验证&#xff09;&…

08-JVM 面试题-mk

文章目录 1.JVM 的各部分组成2.运行时数据区2.1.什么是程序计数器?2.2.你能给我详细的介绍Java堆吗?2.3.能不能解释一下方法区?2.3.1常量池2.3.2.运行时常量池2.4.什么是虚拟机栈?2.4.1.垃圾回收是否涉及栈内存?2.4.2.栈内存分配越大越好吗?2.4.3.方法内的局部变量是否线…

Vue3 nextTick

nextTick 是 Vue 中非常重要的一个 API&#xff0c;它允许你在 DOM 更新周期后执行延迟回调。 核心源码位置 Vue3 的 nextTick 实现主要在 packages/runtime-core/src/scheduler.ts 文件中。 基本实现 const resolvedPromise Promise.resolve() as Promise<any> let …

DISCO:利用大型语言模型提取反事实

DISCO: Distilling Counterfactuals with Large Language Models - ACL Anthologyhttps://aclanthology.org/2023.acl-long.302/ 1. 概述 尽管在自然语言处理(NLP)领域针对各种推理任务取得了巨大进展(Wang 等, 2018, 2019a;Xu 等, 2020),但数据集偏差仍然是构建鲁棒模型…

【Django】框架-路由系统核心概念解析

1. 最基本路由关系 路由是URL地址与处理逻辑&#xff08;视图函数&#xff09;的对应关系。 本质&#xff1a;将用户请求的URL路径映射到具体的处理程序&#xff08;如Django视图函数&#xff09;。 示例&#xff1a; # urls.py urlpatterns [ path(home/, views.home_…

理解 results = model(source, stream=True) 的工作原理和优势

1. 核心概念解析 (1) streamTrue 的作用 生成器模式&#xff1a;当处理视频或图像序列时&#xff0c;streamTrue 会将结果包装成一个 生成器&#xff08;Generator&#xff09;&#xff0c;逐帧生成 Results 对象&#xff0c;而不是一次性返回所有结果。内存优化&#xff1a;…

重新定义“边缘”:边缘计算如何重塑人类与数据的关系

在数字化浪潮中&#xff0c;云计算曾是科技界的宠儿&#xff0c;但如今&#xff0c;边缘计算正在悄然改变游戏规则。它不仅是一种技术进步&#xff0c;更是对人类与数据关系的一次深刻反思。本文将探讨边缘计算如何从“中心化”走向“分布式”&#xff0c;以及它如何在效率、隐…

MCP 协议知识分享

MCP 协议知识分享 一、MCP 协议概述1.1 定义与背景1.2 核心价值1.3 与传统 API 的对比 二、技术架构与工作原理2.1 核心组件2.2 通信机制2.3 典型工作流程 三、关键技术与应用场景3.1 核心技术3.2 典型应用场景 四、与微软技术的集成4.1 Azure OpenAI 服务4.2 Playwright MCP 服…

策略模式实现 Bean 注入时怎么知道具体注入的是哪个 Bean?

Autowire Resource 的区别 1.来源不同&#xff1a;其中 Autowire 是 Spring2.5 定义的注解&#xff0c;而 Resource 是 Java 定义的注解 2.依赖查找的顺序不同&#xff1a; 依赖注入的功能&#xff0c;是通过先在 Spring IoC 容器中查找对象&#xff0c;再将对象注入引入到当…

Linux》》bash 、sh 执行脚本

通常使用shell去运行脚本&#xff0c;两种方法 》bash xxx.sh 或 bash “xxx.sh” 、sh xxx.sh 或 sh “xxx.sh” 》bash -c “cmd string” 引号不能省略 我们知道 -c 的意思是 command&#xff0c;所以 bash -c 或 sh -c 后面应该跟一个 command。

【解析】ReentrantLock锁、Syschronized锁面试点解析

面试官提问 ● 公平锁与非公平锁的区别是什么&#xff1f; ● 什么是可重入锁&#xff1f; ● 什么是死锁&#xff0c;怎样避免死锁&#xff1f; ● ReentrantLock与Syschronized实现原理是什么&#xff1f;两者有什么区别&#xff1f; ● 请说明ReentrantLock获取锁与释放…

04.Python代码NumPy-通过索引或切片来访问和修改

04.Python代码NumPy-通过索引或切片来访问和修改 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是Python基础语法。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性&#xff0c;希望对您有用~ python语法…

跨平台数据采集如何解决不同平台之间的数据兼容性问题?

在数字化时代&#xff0c;企业越来越依赖多个信息系统来管理业务&#xff0c;例如ERP&#xff08;企业资源计划&#xff09;、CRM&#xff08;客户关系管理&#xff09;、财务管理系统、电商平台等。然而&#xff0c;在进行跨平台数据采集时&#xff0c;不同系统之间的数据格式…

解决 vite.config.ts 引入scss 预处理报错

目录 报错1&#xff1a;[plugin:vite:css] [SASS] Error&#xff1a;Cant find stylesheet to import 报错2&#xff1a;[plugin:vite:css] [sass] Error: Undefined variable 版本号&#xff1a; "sass": "^1.86.3","sass-loader": "^1…

C++笔记,数学函数

参考链接&#xff1a;C中数学函数的使用方法_cpp里指数函数-CSDN博客 头文件 <cmath> 1. 基本的算数运算函数 1.1 sqrt() - 计算平方根 功能&#xff1a;计算一个非负实数的平方根。原型&#xff1a;double sqrt(double x);示例代码&#xff1a; #include <iostr…