STM32 多路ADC同时扫描采样

这篇具有很好参考价值的文章主要介绍了STM32 多路ADC同时扫描采样。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

在项目实际应用中,刚好有需求需要使用多路ADC同时采样,这里就选择STM32 ADC多路ADC同时采样,这里简单说明下配置过程,以及使用步骤

原理图

如下图所示,使用四路ADC输入

ADC_Voltage -> 电压信号的采样,外部输入信号,交流电的输入信号,正选信号

ADC_Current -> 电流电流的采样,外部输入信号,交流电的输入信号,正选信号

ADC_Compensation ->      热敏电阻的采样,温度补偿

SCR_NTC ->      同样的热敏电阻的采样,温度补偿

一共使用上述四路ADC输入信号,进入STM32F103C8T6进行采样

STM32 多路ADC同时扫描采样

外部输入电流、电压采用信号,这里做个保护电路

STM32 多路ADC同时扫描采样

 NTC热敏电阻采样电路如下

STM32 多路ADC同时扫描采样

 这里不仔细说明NTC补偿温度的过程,网上也比较多资料,这里侧重说明一下STM ADC的配置

软件设计

采用STM32F103C8T6 使用固件库开发方式

ADC初始化如下

定义DMA搬运ADC采样原始数据的到RAM的地址空间

#define SAMPL_TIMES_PRE_CHANNEL 1000 //每通道采样次数
#define NUM_OF_CHANNEL 4  //供4个通道

uint16_t __IO AD_Value[SAMPL_TIMES_PRE_CHANNEL][NUM_OF_CHANNEL]; //ADC转换结果,DMA目标地址

由于主时钟倍频到72MHZ,这里使用ADC1,首先6分频,主要是不需要特别高的采样率

1路、2路ADC信号,是正选信号,需要匹配其频率,这里经过计算的配置如下

3路、4路ADC信号,无所谓频率,所以只需要匹对1路、2路即可

这里采用独立模式连续多通道扫描模式,针对原理图中设计的

0、1、6、7通道进行扫描

根据需要也可以选择是否打开扫描完成后的中断,实际使用过程中,没有打开,因为感觉没啥用

如果有需要的话也是可以打开的。

打开扫描完成后的中断,需要注意,清除中断标志


void bspNTCAdcInit(void)
{
//	NVIC_InitTypeDef   NVIC_InitStructure;  
	ADC_InitTypeDef ADC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/* Configure ADC   PA1 PA2 PA6 PA7  */
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	/* 配置ADC时钟,为PCLK2的8分频,即72/8=9MHz,ADC最大不超过14MHz */
	//RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);

	/* ADC1 configuration ------------------------------------------------------*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	   /* 独立模式 */
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;			   /* 连续多通道模式 */
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	   /* 连续转换 */
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  /* 转换不受外界决定 */
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;		       /* 右对齐 */
	ADC_InitStructure.ADC_NbrOfChannel = NUM_OF_CHANNEL;					   /* 扫描通道数 */
	ADC_Init(ADC1, &ADC_InitStructure);

	/* ADC1 regular channe0 configuration */ 
	//通过查找数据手册可知,PA5对应的是channel_5        转换时间为:(239.5+12.5)/9 = 28us
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3, ADC_SampleTime_239Cycles5); /*  ADC1,ADC通道x,规则采用顺序值为1,采样时间为239.5周期 */ 
	ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 4, ADC_SampleTime_239Cycles5); /*  ADC1,ADC通道x,规则采用顺序值为2,采样时间为239.5周期 */ 
	/* Enable the temperature sensor and vref internal channel */ 
	//ADC_TempSensorVrefintCmd(ENABLE);
	ADC_DMACmd(ADC1, ENABLE);//开启ADC的DMA支持
	/* Enable ADC1 */
	ADC_Cmd(ADC1, ENABLE);
	/* Enable ADC1 reset calibaration register */ 
	ADC_ResetCalibration(ADC1);
	/* Check the end of ADC1 reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADC1));
	/* Start ADC1 calibaration */
	ADC_StartCalibration(ADC1);
	/* Check the end of ADC1 calibration */
	while(ADC_GetCalibrationStatus(ADC1));  
	/* Start ADC1 Software Conversion */ 
	//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
	DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外设ADC基地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //DMA内存地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地
	DMA_InitStructure.DMA_BufferSize = NUM_OF_CHANNEL * SAMPL_TIMES_PRE_CHANNEL; //DMA通道的DMA缓存大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设寄存器地址不变
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
	DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道x拥有高优先级
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
	DMA_Init(DMA1_Channel1, &DMA_InitStructure); //

//	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;	  
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;// 设置抢占优先级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//	NVIC_Init(&NVIC_InitStructure);

	DMA_Cmd(DMA1_Channel1, ENABLE); //启动DMA通道	
//	DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

对采样的数据进行均值滤波

这里根据自己的需要,对采样的数据进行均值滤波

可以一起计算滤波,也可以分开计算,这个计算过程比较消耗资源,所以,我这里分开计算了

使用哪一路的ADC进行计算哪一路

只有需要更新ADC时才计算实际ADC的数值



void filter_0_1(void)
{
	uint64_t sum = 0;
	uint16_t count , i;
	
	i = 0;
	for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1)
	{
		sum += AD_Value[count][i] * AD_Value[count][i];
		//sum += AD_Value[count][i];
	}
	after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL;
	sum=0;
	//printf("i:%d,%4.2fv\r\n", i,((float)after_filter[i]/4095)*3.3);

	i = 1;
	for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1)
	{
		sum += AD_Value[count][i] * AD_Value[count][i];
		//sum += AD_Value[count][i];
	}
	after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL;
	//printf("i:%d,%4.2fv\r\n", i,((float)after_filter[i]/4095)*3.3);
}
//static u8 ntct_fresh = 1;
void filter_2_3(void)
{
	uint32_t sum = 0;
	uint16_t count , i;
	

	i = 2;
	//if(ntct_fresh == 1)
	{
		for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1)
		{
			sum += AD_Value[count][i];
		}
		after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL;
	}
	sum=0;
	//printf("i:%d,%4.3fv\r\n", i,((float)after_filter[i]/4095)*3.3);	
	
//	i = 3;
//	for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1)
//	{
//		sum += AD_Value[count][i];
//	}
//	after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL;
//	//printf("i:%d,%4.3fv\r\n", i,((float)after_filter[i]/4095)*3.3);	
}

如果打开DMA中断标识,需要清除中断标志文章来源地址https://www.toymoban.com/news/detail-462763.html

void DMA1_Channel1_IRQHandler(void)
{
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
//	uint16_t msg = MSG_SYS_ADC;
	
	if(DMA_GetFlagStatus(DMA1_FLAG_TC1)==SET)
	{
		DMA_ClearFlag(DMA1_FLAG_TC1);

		//xQueueSendFromISR( tempctrlxQueue, &msg, &xHigherPriorityTaskWoken );
	}
	portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

到了这里,关于STM32 多路ADC同时扫描采样的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32-ADC过采样实验

    我们之前已经有过一些关于STM32-ADC的笔记和实验代码了,链接如下: 关于ADC的笔记1_Mr_rustylake的博客-CSDN博客 STM32-ADC单通道采集实验_Mr_rustylake的博客-CSDN博客 STM32-单通道ADC采集(DMA读取)实验_Mr_rustylake的博客-CSDN博客 STM32-ADC多通道输入实验_Mr_rustylake的博客-CSDN博客 首先简单

    2024年02月10日
    浏览(29)
  • stm32教程之三重ADC交错采样

    ps:本文基于stm32F407ZGT6单片机         stm32F4单片机单通道采集的最大采样率为2.4M,所以有时会难以满足较高频率的采样,于是查阅芯片手册,发现stm32F4支持多重ADC采集,利用每个通道的转换时间,错位采样,从而提高采样率,最大把采样率开到2.4*3=7.2M.  (去年初学AD

    2024年02月12日
    浏览(31)
  • 基于STM32的ADC采样序列频谱分析

      本文主要介绍对ADC采集得到的数字序列进行FFT频谱分析。   确定采样率除了要遵守奈奎斯特采样定律意外还需要考虑一些问题。在数字系统中,我们只能进行一些有限的离散的运算,对于有限长的序列,我们不可能拿它去做DTFT,只能做DFT。这就需要 把有限长序列也当

    2024年02月13日
    浏览(33)
  • STM32--ADC数值采样/附ADC采集热敏传感器使用

    目录 一丶ADC介绍 二丶ADC工作原理及管脚分布 三丶代码部分详解 (一)库函数介绍 (二)代码部分整合         ADC模块中文名为模拟/数字转换器,是12位逐次逼近型的模拟数字转换器,一般用于数值的采样   可以将引脚上连续变化的模拟电压转换为内存中存储的数字变

    2024年02月03日
    浏览(33)
  • 搭建stm32电机控制代码框架(三)——Stm32CubeMx配置ADC采样

    电机控制另一个关键的模块就是ADC采样,这个模块配置的好坏决定了采样电流和电压的精准度,因此有必要对其进行深入学习。 简介: STM32 在片上集成的ADC 外设非常强大。STM32F103xC、STM32F103xD 和STM32F103xE增强型产品内嵌3个12位的ADC,每个ADC 共用多达 21 个外部通道,可以实现

    2024年02月13日
    浏览(33)
  • STM32-ADC电压采样实验(寄存器版)

    STM32F10X系列支持三路ADC,其ADC通道及对应IO口如下表所示: 其能接受的电压输入范围一般为0-3.3V(V REF- ≤ V IN ≤ V REF+ ),因此,如果需要测量超出0-3.3v量程范围的电压数据,需要在外围硬件增加分压电阻,将电路转换到0-3.3V量程范围内再进行采集。 这里用于做ADC采集的引脚使

    2024年02月15日
    浏览(40)
  • STM32 ADC单/多通道采样+DMA搬运

    通过介绍我们可以了解到,ADC是12位的转换器,所以采样值范围是0~4095。18个通道可同时进行转换,也可以单独转换某个通道。 使用ADC的流程应为: 初始化IO口。 我这里使用的是PA1进行采样,也就是ADC1的通道1 初始化ADC。 转换、获取采样值。 多通道的时候我们一般用DMA来搬

    2024年02月14日
    浏览(36)
  • STM32双路ADC注入通道和规则通道采样

    电机控制使用四路注入通道采集,参考ST官方库,使用定时器10us触发一次,使用ADC1和ADC2各2路注入通道。 需要一路ADC进行规则采样油门信号,使用中断的话会和注入通道中断放在同一个函数里面 ,我不喜欢,所以使用了DMA中断。 PreKnowledge: 规则通道:最多16个规则通道,采样

    2024年04月14日
    浏览(32)
  • STM32CubeMX配置ADC采样(轮询、中断、DMA)

    STM32CubeMX能够极大减小STM32外设配置的工作量,因此作者也借助空闲时间对STM32CubeMX相关配置进行了学习,本文介绍如何利用STM32CubeMX配置ADC采样,记录了作者学习过程中遇到的问题及解决办法,使大家少走弯路,并方便以后复习 先选择所使用的MCU,这里我使用的是STM32F407ZGT系

    2024年02月03日
    浏览(40)
  • STM32F3系列 ADC采样单端采样模式(基于LL库)

    芯片型号:STM32f303RBT6 开发软件:MDK5 CubeMX VS Code 目录 STM32F3系列 ADC 单端采样(基于LL库) 目录 引言 1 基础知识 1.1ADC转换基本流程 1.2 时钟树 1.3 关键参数 1.3.1 位数 1.3.2 触发信号 1.3.3 采样时间 1.3.4 转换时间 2 CubeMx 配置步骤 2.1 确定输入通道 2.2 配置ADC 2.3 输出设置 2.4 MD5 设置

    2024年02月08日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包