STM32之ADC多路采样开发踩过的坑

您所在的位置:网站首页 尝试读取的采样已不存在 STM32之ADC多路采样开发踩过的坑

STM32之ADC多路采样开发踩过的坑

2024-03-13 23:27| 来源: 网络整理| 查看: 265

最近开发基于PH、ORP数据采集项目,两路PH,两路ORP所以用到了STM32ADC多路采样,

不足之处望指正。

一、存在问题

1、采样数据不准确,几路数据相同。

2、通道间数据互相影响,不准确等。

二、开发过程

非DMA模式

最开始只是在单通道非DMA模式下增加多路通道,结果AD采样数据显示都一样,经过各种修改未发现问题。

 DMA模式

在思绪百般无果下,想了下会不会是多路采样导致CPU负担过重,于是想起了DMA(个人理解DMA就是一个中转站,起到存数据,取数据的过程,这个存取过程不需要CPU直接参与,采样数据过大、过多时利用DMA收集数据,再处理,减轻了CPU负担),资源查询过程中又发现了一个问题,在非DMA模式下,多路ADC采集的数据储存位置是相同的,出现了数据覆盖,所以才会有互相影响,数据相同的奇怪现象。然而,开启ADC多通道DMA模式后采集数据还是存在互相干扰,最后查询资料得到的结论是,未连接的端口处于浮空状态,会受干扰,最后将每个采样口接通,恢复正常。

三、下面分享一下源码以及细节部分吧

1、ADC采样GPIO端口配置,这里配置六个PA端口

void ADC1_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6); }

2、ADC和DMA一起配置

void ADC1_Mode_Config(void) { ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCDAT; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 6; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 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 =6; ADC_Init(ADC1, &ADC_InitStructure); RCC_ADCCLKConfig(RCC_PCLK2_Div8); 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_2, 3, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }

3、注意细节

DMA_InitStructure.DMA_BufferSize = 6;这是配置DMA数据储存大小,由于STM32内置ADC采样为12位,所以一个IO口采集的数据咱们用16来储存,所以六个IO口填6。

ADC_DMACmd(ADC1, ENABLE);    这句是ADC请求DMA关键使能句,也就是ADC与DMA的桥梁。

其他区别对比单路ADC采样修改即可, DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCDAT,这里ADCDAT定义为u16ADCDAT[5]数组,刚好储存六个IO口ADC值,为了储存数据强制转化为32位,在主函数中直接读取读取数组即为对应ADC值。

 

    



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3