STM32F4实现ADC同步采样的方法

方法一:双ADC+DMA采样

基础配置

此方法是基于双ADC+DMA同时搬运实现,配置时先打开TIM定时器
将TIM配置为你需要的采样频率,并且开启Update Event,详细原因请参考往期博客:
[https://www.cnblogs.com/LuvRene-blog/articles/18289670/LuvRene-blog-ADC_DMA_TIM-01]

之后打开两个ADC通道,关闭扫描模式、连续转换,并使能DMA请求连续搬运
之后分别为两个ADC配置为独立模式,触发方式改为TIM触发
开启DMA采样,将DMA模式设置为Normal(Normal和Circle的采样值会有不同)

代码逻辑

分别分配两个ADC采样的储存空间,分别打开ADC的DMA,之后启动TIM,此时双ADC同时开始工作,实现同步采样;

方法二:使用HAL库自带的双ADC同步采样模式配置

基础配置

还是同上配置时钟,将ADC1的模式从Imdependent Mode更改为Dual regular simultaneous Mode only

之后配置同上,关闭扫描模式、连续转换,并使能DMA请求连续搬运,触发方式改为TIM触发
之后你会发现,当你配置了自带的双ADC模式时,ADC2对应的选项会变灰且无法选中

重点是,配置DMA时一定要配置Memory大小为Word,原因是该模式下的采样是存储到同一个数组

代码逻辑

在所有的外设模块初始化后,将ADC2直接打开 HAL_ADC_Staert(&hadc2)
之后调用 HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Raw_Data, FFT_LENGTH);
传递的参数分别是ADC的权柄、32位数据的储存数组、数组的长度;

之后在你提供的存储数据的Buffer里面,因为是Word-32位的数据大小,而ADC设置的数据大小为12位
那么在Buffer里面是将ADC采样的值在高四位填上0
然后将ADC1的值放在低16位,ADC2的值相同处理后放在高16位(谁低谁高可能取决于ADC的通道优先级)

需要使用数据时需要用到与运算**&和移位运算右移:>>**

点击查看代码
// 双ADC同步采样结果提取
for (int i = 0; i < FFT_LENGTH; i++)
{
  ch1.adc_buf[i] = ADC_Raw_Data[i] & 0xffff;\\ 提取低16位的数据
  ADC_Raw_Data[i] >>= 16;\\ 将高16位的数据移到低16位
  ch2.adc_buf[i] = ADC_Raw_Data[i] & 0xffff;
}

以上就是针对ADC同步采样的两种处理方式,方法一主要是在于代码的顺序
一定要先将两个ADC的DMA搬运打开,再打开TIM定时器

而方法二则是在于对于数据的处理,存储的数组大小一定要设置为Word和uint32_t
才能保证一个数据存放为可以保存两个ADC的采样值

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于STM32F4ADC采样代码的示例: ```c #include "stm32f4xx.h" void ADC_Init(void) { ADC_InitTypeDef ADC_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; // 使能 ADC1 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 使能 GPIOA 时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 配置 ADC1 的输入引脚(PA0) GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStruct); // ADC1 初始化配置 ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; ADC_InitStruct.ADC_ScanConvMode = DISABLE; ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStruct.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStruct); // 配置 ADC1 的通道 0 ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_15Cycles); // 使能 ADC1 ADC_Cmd(ADC1, ENABLE); } uint16_t ADC_Read(void) { // 启动 ADC1 转换 ADC_SoftwareStartConv(ADC1); // 等待转换完成 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 读取转换结果 return ADC_GetConversionValue(ADC1); } int main(void) { ADC_Init(); while(1) { uint16_t adcValue = ADC_Read(); // 对采样值进行处理 // ... } } ``` 这段代码使用了ADC1通道0对PA0引脚进行采样,并将采样结果保存在`adcValue`变量中。你可以根据需要在while循环中对采样值进行处理。请根据自己的需求修改代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值