首页 > 其他分享 >【4】GD32H7xx ADC采样

【4】GD32H7xx ADC采样

时间:2024-11-16 13:18:23浏览次数:3  
标签:采样 dma GD32H7xx adc parameter port channel ADC

目录

1. GD32H7xx ADC

1.1 ADC外设资源

GD32H7xx 有3个ADC外设:

  • ADC0
    • 20个外部通道,1个内部通道(DAC0_OUT0通道)
    • 32位数据寄存器
    • 可配置14位、12位、10位或8位分辨率
      • 14位满量程对应转换值:16383
      • 12位满量程对应转换值:4096
      • 采样值 = 实际电压 / 参考电压 * 16383
    • 采样率:分辨率越低转换越快。 MSPs:(Million Samples Per Second)每秒百万次采样
      • 14位:4MSPs
      • 12位:4.5 MSPs
      • 10位:5.14 MSPs
      • 8位:6 MSPs
    • 时钟最大频率:72MHz
    • 过采样:
      • 32位的数据寄存器
      • 可调整过采样率: 2~1024
      • 高达11位的可编程数据移位
  • ADC1
    • 18个外部通道,3个内部通道(电池电压Vbat、参考电压输入Vrefint、DAC0_OUT1通道)
    • 32位数据寄存器
    • 可配置14位、12位、10位或8位分辨率
    • 采样率与ADC0相同
    • 时钟最大频率:72MHz
    • 过采样特性与ADC0相同
  • ADC2
    • 17个外部通道,4个内部通道(电池电压Vbat、参考电压输入Vrefint、内部温度传感通道Vsense、高精度温度传感器通道Vsense2)
    • 16位数据寄存器
    • 可配置12位、10位、8位或6位分辨率
    • 采样率
      • 12位:5.3 MSPs
      • 10位:6.15 MSPs
      • 8位:7.27 MSPs
      • 6位:8.89 MSPs
    • 时钟最大频率:80MHz
    • 过采样:
      • 16位的数据寄存器
      • 可调整过采样率: 2~256
      • 高达8位的可编程数据移位

1.2 采样时间

ADC使用若干个CK_ADC周期对输入电压采样,采样周期数目通过ADC_REQ0~ADC_RSQ8寄存器的RSMPn[9:0]位进行设置。采样时间寄存器如下图所示:
在这里插入图片描述
说明:
1.10’d0 : 表示 10位宽的数值0
2.根据寄存器描述的规律:采样时间 = 设置值 + 3.5 周期

从User Manual可知,总转换时间 = 采样时间 + 12.5个CK_ADC周期
举例说明:
当MCU的时钟频率为600MHz, HCLK = 300MHz,ADC时钟 = HCLK/6 = 50MHz
若设置的采样时间值为240
总转换时间 = (240 + 3.5)周期 + 12.5 周期 = 256 周期 = 256/50MHz = 5.12us
采样一次的时间为 5.12us。

1.3 片上硬件过采样

  作用:片上硬件过采样单元可以执行数据预处理以减轻CPU负担。能够处理多个转换并将多个转换的结果进行平均。
  14位ADC,片上过采样单元执行2个功能:求和、位右移。过采样率: 2~1024倍。除法系数(即右移位数)最大11位。求和单元能够生成一个多达24位的值。
说明:
1.1024 * 2的14次幂(14位ADC)= 2的24次幂 即 24位的值。 这个结果首先右移然后将数据存储到寄存器中。
2.数据每右移1位,相当于除以2。 16倍过采样率即是 2的4次方,即需要右移4bit。
3.和标准的转换模式相比,过采样转换的采样时间不会改变。

接口函数介绍

/*!
    \brief      configure ADC 过采样
    \param[in]  adc_periph: ADCx, x=0,1,2
    \param[in]  mode: ADC 过采样模式
                only one parameter can be selected which is shown as below:
      \arg        ADC_OVERSAMPLING_ALL_CONVERT: 通道的所有过采样转换都是在触发后连续完成的
      \arg        ADC_OVERSAMPLING_ONE_CONVERT: 通道的每个过采样转换都需要一个触发
    \param[in]  shift: ADC oversampling shift
                only one parameter can be selected which is shown as below:
      \arg        ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_4B: 4-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift
      \arg        ADC_OVERSAMPLING_SHIFT_9B: 9-bit oversampling shift, available for ADC0/ADC1
      \arg        ADC_OVERSAMPLING_SHIFT_10B: 10-bit oversampling shift, available for ADC0/ADC1
      \arg        ADC_OVERSAMPLING_SHIFT_11B: 11-bit oversampling shift, available for ADC0/ADC1
    \param[in]  ratio: ADC oversampling ratio, 0..1023 for ADC0/ADC1, 0..255 for ADC2
    \param[out] none
    \retval     none
*/
void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint16_t ratio)


/*!
    \brief      enable ADC oversample mode
    \param[in]  adc_periph: ADCx, x=0,1,2
    \param[out] none
    \retval     none
*/
void adc_oversample_mode_enable(uint32_t adc_periph)
{
    ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_OVSEN;
}

/*!
    \brief      disable ADC oversample mode
    \param[in]  adc_periph: ADCx, x=0,1,2
    \param[out] none
    \retval     none
*/
void adc_oversample_mode_disable(uint32_t adc_periph)
{
    ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN);
}

2. ADC DMA规则多通道采样程序

usr_adc.h

#ifndef _USR_ADC_H_
#define _USR_ADC_H_

#include "gd32h7xx.h"
#include "cmsis_os2.h"
#include "rtx_os.h"
#include "user_log.h"


// ADC IO、Channel parameter
typedef struct 
{
	rcu_periph_enum rcu_port;		// IO CLK
	uint32_t port;					// IO port
	uint32_t pin;					// IO pin
	uint32_t gpio_speed;			// IO speed
	uint8_t  adc_channel;			// ADC channel
	uint32_t sample_time;			// 采样周期
}adc_ch_parameter;


typedef struct
{
	rcu_periph_enum rcu_dma;			// DMA CLK
	uint32_t dma_periph;				// DMA num
	dma_channel_enum dma_channel;		// DMA channel
	uint32_t request;				
	uint32_t dma_number;				// DMA传输个数
	uint32_t dma_priority;				// DMA通道优先级
	EventStatus dma_circulation_mode;	// 循环模式
}adc_dma_parameter;

typedef struct
{
	rcu_periph_enum rcu_adc;			// ADC CLK
	uint32_t adc_psc;					// ADC 时钟分频系数
	uint32_t adc_port;					
	uint32_t adc_mode;					// ADC work mode:ADC_MODE_FREE,ADC_DAUL_REGULAL_PARALLEL
	uint8_t adc_channel_group;			// ADC 工作组:规则组或注入组
	EventStatus adc_scan_function;		// 设置扫描模式
	EventStatus adc_continuous_function;// 设置循环模式
	uint32_t adc_external_trigger_mode;	
	uint8_t ch_count;					// 设置转换通道个数
	adc_dma_parameter dma_parameter;	// dma 参数
	uint32_t trigger_source;			// ADC 触发源
	EventStatus DMA_mode;				// 是否使用DMA
}adc_ch_general;




/********************************************* Function *********************************************/
void usr_adc_test_thread(void);
void usr_adc_software_trigger_enable(adc_ch_general *ADC);





#endif

usr_adc.c

#include "usr_adc.h"

__attribute__((aligned(32))) uint16_t adc2_value[2];
__attribute__((aligned(32))) uint16_t adc0_value[2];


adc_ch_general  adc0= {
	.rcu_adc = RCU_ADC0,											
	.adc_psc = ADC_CLK_SYNC_HCLK_DIV6,							// HCLK(300MHz) 6分频					
	.adc_port = ADC0,												
	.adc_mode = ADC_SYNC_MODE_INDEPENDENT,						// 独立模式
	.adc_channel_group = ADC_REGULAR_CHANNEL,					// 规则组
	.adc_scan_function = ENABLE,								// 开启扫描模式
	.adc_continuous_function = ENABLE,							// 开启循环模式
	.ch_count = 2,												// 转换通道个数							
	.adc_external_trigger_mode = EXTERNAL_TRIGGER_DISABLE,		// Disable外部触发
	.dma_parameter = 
	{
		.rcu_dma = RCU_DMA1,									// DMA CLK
		.dma_periph = DMA1,										// 使用DMA1
		.dma_channel = DMA_CH1,									// DMA1 通道0
		.dma_number = 2,										// 传输长度
		.request = DMA_REQUEST_ADC0,
		.dma_priority = DMA_PRIORITY_HIGH,						// 通道优先级
		.dma_circulation_mode = ENABLE							// DMA循环模式使能
	},
	.DMA_mode = ENABLE											// 使能DMA
};

adc_ch_parameter adc0_ch[2] = 
{
	{
	.rcu_port = RCU_GPIOC,											
	.port = GPIOC,													
	.pin = GPIO_PIN_0,										// PC0	
	.gpio_speed = GPIO_OSPEED_12MHZ,						
	.adc_channel = ADC_CHANNEL_10,							
	.sample_time = 240										// 采样周期
	}
	,
	{
	.rcu_port = RCU_GPIOC,									
	.port = GPIOC,										
	.pin = GPIO_PIN_1,										// PC1 
	.gpio_speed = GPIO_OSPEED_12MHZ,						
	.adc_channel = ADC_CHANNEL_11,						
	.sample_time = 240						
	}
};





adc_ch_general  adc2= {
	.rcu_adc = RCU_ADC2,											
	.adc_psc = ADC_CLK_SYNC_HCLK_DIV6,							// HCLK(300MHz) 6分频					
	.adc_port = ADC2,												
	.adc_mode = ADC_SYNC_MODE_INDEPENDENT,						// 独立模式
	.adc_channel_group = ADC_REGULAR_CHANNEL,					// 规则组
	.adc_scan_function = ENABLE,								// 开启扫描模式
	.adc_continuous_function = ENABLE,							// 开启循环模式
	.ch_count = 2,												// 转换通道个数							
	.adc_external_trigger_mode = EXTERNAL_TRIGGER_DISABLE,		// Disable外部触发
	.dma_parameter = 
	{
		.rcu_dma = RCU_DMA1,									// DMA CLK
		.dma_periph = DMA1,										// 使用DMA1
		.dma_channel = DMA_CH0,									// DMA1 通道0
		.dma_number = 2,										// 传输长度
		.request = DMA_REQUEST_ADC2,
		.dma_priority = DMA_PRIORITY_HIGH,						// 通道优先级
		.dma_circulation_mode = ENABLE							// DMA循环模式使能
	},
	.DMA_mode = ENABLE											// 使能DMA
};



adc_ch_parameter adc2_ch[2] = 
{
	{
	.rcu_port = RCU_GPIOC,											
	.port = GPIOC,													
	.pin = GPIO_PIN_2,										// PC2	
	.gpio_speed = GPIO_OSPEED_12MHZ,						
	.adc_channel = ADC_CHANNEL_0,							
	.sample_time = 240// 采样周期
	}
	,
	{
	.rcu_port = RCU_GPIOC,									
	.port = GPIOC,										
	.pin = GPIO_PIN_3,										// PC3 
	.gpio_speed = GPIO_OSPEED_12MHZ,						
	.adc_channel = ADC_CHANNEL_1,						
	.sample_time = 240
	}
};




/*
    \brief      adc_regular_ch_dma_config
    \param[in]  ADC:ADC  para
    			ADC_CH: channel para
    \retval		none
*/
void driver_adc_config(adc_ch_general *ADC, adc_ch_parameter *ADC_CH)
{	 
	uint8_t i;
    adc_idx_enum idx_adc;
	adc_deinit(ADC->adc_port);
    /* ADC clock config */
    
    if(ADC->adc_port==ADC0){
        idx_adc=IDX_ADC0;    
    }else if(ADC->adc_port==ADC1){
        idx_adc=IDX_ADC1;    
    }else{
        idx_adc=IDX_ADC2;    
    }   
    rcu_adc_clock_config(idx_adc, RCU_ADCSRC_PER);    
    
	adc_clock_config(ADC->adc_port, ADC->adc_psc); 		
	rcu_periph_clock_enable(ADC->rcu_adc); 				
    
	for(i=0 ;i<ADC->ch_count; i++)
	{
		if(ADC_CH[i].adc_channel < ADC_CHANNEL_17)
		{
			rcu_periph_clock_enable(ADC_CH[i].rcu_port);
			gpio_mode_set(ADC_CH[i].port, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_CH[i].pin);					
		}
		else
		{
			if(ADC->adc_port==ADC2)
			{
				if(ADC_CH[i].adc_channel == ADC_CHANNEL_17)
				{
					adc_internal_channel_config(ADC_CHANNEL_INTERNAL_VBAT, ENABLE);
				}
				else if(ADC_CH[i].adc_channel == ADC_CHANNEL_18)
				{
					adc_internal_channel_config(ADC_CHANNEL_INTERNAL_TEMPSENSOR, ENABLE);
				}
				else if(ADC_CH[i].adc_channel == ADC_CHANNEL_19)
				{
					adc_internal_channel_config(ADC_CHANNEL_INTERNAL_VREFINT, ENABLE);
				}
				else if(ADC_CH[i].adc_channel == ADC_CHANNEL_20)
				{
					adc_internal_channel_config(ADC_CHANNEL_INTERNAL_HP_TEMPSENSOR, ENABLE);
				}				
			}
			else
			{
				rcu_periph_clock_enable(ADC_CH[i].rcu_port);
				gpio_mode_set(ADC_CH[i].port, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_CH[i].pin);					
			}
		}		

	}
	adc_sync_mode_config(ADC->adc_mode);								
	adc_special_function_config(ADC->adc_port, ADC_SCAN_MODE, ADC->adc_scan_function);
	if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL)
	{
		adc_special_function_config(ADC->adc_port, ADC_CONTINUOUS_MODE, ADC->adc_continuous_function);	
	}
	adc_data_alignment_config(ADC->adc_port, ADC_DATAALIGN_RIGHT);	
	adc_channel_length_config(ADC->adc_port, ADC->adc_channel_group, ADC->ch_count);
	if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL)																	
	{
		for(i = 0;i< ADC->ch_count;i++)
		{
			adc_regular_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time);
		}
	}
	else if(ADC->adc_channel_group == ADC_INSERTED_CHANNEL)
	{
		for(i = 0;i< ADC->ch_count;i++)
		{
			adc_inserted_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time);
		}	
	}

	adc_external_trigger_config(ADC->adc_port, ADC->adc_channel_group, ADC->adc_external_trigger_mode);

	if(ADC->DMA_mode == ENABLE)
	{
		adc_dma_request_after_last_enable(ADC->adc_port);
		adc_dma_mode_enable(ADC->adc_port);
	}

	adc_enable(ADC->adc_port);
	osDelay(1);

	adc_calibration_mode_config(ADC->adc_port, ADC_CALIBRATION_OFFSET_MISMATCH);
	/* ADC calibration number config */
	adc_calibration_number(ADC->adc_port, ADC_CALIBRATION_NUM32);
	adc_calibration_enable(ADC->adc_port);
}



/*
    \brief      adc_regular_ch_dma_config
    \param[in]  ADC:ADC  para
    			ADC_CH: channel para
    			buffer: ADC数据缓存buf
    \retval		none
*/
void adc_channel_dma_config(adc_ch_general *ADC, adc_ch_parameter *ADC_CH,void *buffer)
{	
	dma_single_data_parameter_struct dma_single_data_parameter;
	rcu_periph_clock_enable(ADC->dma_parameter.rcu_dma);									
	rcu_periph_clock_enable(RCU_DMAMUX);	
	dma_deinit(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);		
	
	dma_single_data_parameter.request = ADC->dma_parameter.request;
	dma_single_data_parameter.periph_addr  = (uint32_t)(&ADC_RDATA(ADC->adc_port));
	dma_single_data_parameter.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
	dma_single_data_parameter.memory0_addr  = (uint32_t)(buffer);
	dma_single_data_parameter.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
	if(ADC->adc_mode == ADC_DAUL_REGULAL_PARALLEL)
	{
		dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
	}
	else
	{
		dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
	}
	dma_single_data_parameter.direction    = DMA_PERIPH_TO_MEMORY;
	dma_single_data_parameter.number       = ADC->dma_parameter.dma_number;
	dma_single_data_parameter.priority     = ADC->dma_parameter.dma_priority;
	dma_single_data_mode_init(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel, &dma_single_data_parameter);

	if(ADC->dma_parameter.dma_circulation_mode == ENABLE)
	{
		dma_circulation_enable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);
	}
	else
	{
		dma_circulation_disable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);
	}
	dma_channel_enable(ADC->dma_parameter.dma_periph, ADC->dma_parameter.dma_channel);	
	driver_adc_config(ADC,ADC_CH);	

	// 过采样
#if 0
	adc_oversample_mode_config(ADC->adc_port, ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, 16);
	adc_oversample_mode_enable(ADC->adc_port);
#endif
}


/*
    \brief      adc_software_trigger_enable
    \param[in]  ADC:ADC  para
    \retval		none
*/
void usr_adc_software_trigger_enable(adc_ch_general *ADC)
{
    adc_software_trigger_enable(ADC->adc_port, ADC->adc_channel_group);
}


void usr_adc_init(void)
{
	//adc_channel_dma_config(&adc2, adc2_ch, (uint16_t*)adc2_value);
	//usr_adc_software_trigger_enable(&adc2);

	adc_channel_dma_config(&adc0, adc0_ch, (uint16_t*)adc0_value);
	usr_adc_software_trigger_enable(&adc0);

	
}



void usr_adc_test_thread(void)
{
	LogI("%s run...\r\n",__FUNCTION__);

	uint32_t ticks;
	const uint16_t sleep_ms = 200;
	uint32_t Vin1, Vin2;

	usr_adc_init();

	
	

	ticks = osKernelGetTickCount();
	while(1)
	{
		SCB_InvalidateDCache_by_Addr ((uint32_t *)adc0_value, sizeof(adc0_value)); 
		Vin1 = (3300*adc0_value[0]*2)/16383 - 3300;
		Vin2 = (3300*adc0_value[1]*2)/16383 - 3300;
		LogI("Vin1= [%d]mv, Vin2= [%d]mv, ADC0 val[0]= %d, val[1]= %d\r\n", Vin1, Vin2, adc0_value[0], adc0_value[1]);

		ticks += sleep_ms;
		osDelayUntil(ticks);  
	}
}

3. 程序测试

输入电压Vin 为2v,采样成功。
在这里插入图片描述


To Be Continue …

标签:采样,dma,GD32H7xx,adc,parameter,port,channel,ADC
From: https://blog.csdn.net/madao1234/article/details/143568274

相关文章

  • 【FMC128D】基于VITA57.1标准的8通道250MSPS采样率16位AD采集FMC子卡(直流耦合)
    ​ 产品概述FMC128D是一款8通道250MHz采样率16位分辨率直流耦合AD采集FMC子卡,符合VITA57.1规范,可以作为一个理想的IO模块耦合至FPGA前端,8通道AD将模拟信号数字化后通过高带宽的FMC连接器(HPC)连接至FPGA,从而大大降低了系统信号延迟。该板卡支持板上可编程采样时钟和外部参考时钟......
  • 【VMware by Broadcom】新闻:VMware Workstation 和 Fusion 产品商业使用免费。
    VMwareWorkstationPro和VMwareFusionPro是VMwareDesktopHypervisor产品,允许用户在Windows、Linux或Mac计算机上运行虚拟机、容器和Kubernetes集群。我相信绝大部分人使用VMware的产品都是从这里开始的,我也不例外。前段时间,VMware宣布将这两款产品永久免费提供......
  • 数字信号处理--采样环节
    前言对于一个信号来说,如果需要借助计算机对其处理,首先需要进行采样。采样有三个概念,参考信号,量化等级,采样频率和采样时间(或采样点数)。采样频率对于信号样本,一般来说关心的频率范围是固定。例如,人类听觉范围20Hz~20kHz。那么根据采样定理,采样频率应该至少为最高频率的2......
  • OpenGL 纹理采样 在GPU中哪个部件完成
    OpenGL纹理采样主要在GPU的流式多处理器(StreamingMultiprocessor,SM)中完成。SM内部包含多个用于执行计算的核心(Core)以及纹理缓存(TextureCache)等部件,这些部件协同工作来实现纹理采样。具体过程如下:纹理数据获取:当需要进行纹理采样时,首先会从纹理内存(通常是显存中的一块区......
  • 【2】GD32H7xx 串口Idle + DMA接收不定长数据
    目录1.IDLE中断相关介绍2.D-Cache与DMA同时使用2.1I-Cache与D-Cache2.2D-Cache与DMA同时使用时的数据一致性问题2.2.1CPU读取DMA写入到SRAM的数据2.2.2DMA读取CPU写入到SRAM的数据3.UartIdle+DMA收发程序4.程序测试1.IDLE中断相关介绍在GD32H7xxMCU......
  • 芯海科技最新产品选型(MCU、单相电能计量ADC免校准、SAR ADC......
    芯海专注于高精度ADC、高可靠性MCU、测量算法等芯片产品研发设计,广泛应用于工业测量与工业控制、通信与计算机、锂电管理、消费电子、汽车电子、智慧家居、智能仪表、智慧健康等领域。32位MCU系列,高可靠低功耗高精度应用于:消费电子生活电器电池管理通信工业控制工业测量......
  • YoloV10改进策略:上采样改进|CARAFE,轻量级上采样|即插即用|附改进方法+代码
    论文介绍CARAFE模块概述:本文介绍了一种名为CARAFE(Content-AwareReAssemblyofFEatures)的模块,它是一种用于特征上采样的新方法。应用场景:CARAFE模块旨在改进图像处理和计算机视觉任务中的上采样过程,特别适用于目标检测、实例分割、语义分割和图像修复等任务。目标:通过......
  • 终于搞全了:GPIO/ADC/LED/I2C/SPI/USB…
    合宙低功耗4G模组经典型号Air780E,支持两种软件开发方式:一种是传统的AT指令;一种是基于模组做Open开发。传统AT指令的开发方式,合宙模组与行业内其它模组品牌在软件上区别不大,在硬件功耗上更有优势;模组Open开发,合宙采用的是LuatOS方式,相对C-SDK入门更简单,开发更方便,开发时间上也更......
  • 定时器(PWM输出)触发ADC采样(DMA)——STM32CubeMX
    在STM32微控制器中,使用定时器(PWM输出)触发ADC采样是一种常见的应用场景,尤其是在需要精确控制采样时刻和频率的场合。本文将详细介绍如何使用STM32CubeMX配置定时器产生PWM波形,并使用DMA传输ADC采样结果。1.定时器PWM输出配置首先,我们需要在STM32CubeMX中配置定时器以产......
  • Pandas进行时间重采样与聚合
    在数据分析中,时间序列数据是一类非常常见的数据类型,通常需要对其进行频率变换或聚合操作,以便更好地分析和展示数据趋势。Python中的pandas库提供了丰富的工具来处理时间序列数据,尤其是resample()和groupby()这两个功能。它们不仅可以对时间序列进行重采样,还能结合聚合......