IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F407 ADC+DMA+定时器 定时采样模拟量 -> 正文阅读

[嵌入式]STM32F407 ADC+DMA+定时器 定时采样模拟量

STM32F407 ADC+DMA+定时器 定时采样模拟量


前言

项目中需要对多个通道的电压进行一定频率的AD采样,由于采样过程贯穿整个任务,为了使采样过程尽可能不占用CPU资源,采用定时器触发的多通道ADC扫描采样,且采样数据由DMA传到RAM中的缓存。
这样做有以下几个好处:1、由定时器触发ADC采样,这样采样的频率可控,且定时器触发不会占用任何CPU资源;2、DMA进一步降低了任务对CPU的占有率。


提示:以下是本篇文章正文内容,下面案例可供参考

一、硬件原理

1.1 ADC

STM32F 407的ADC的规则通道扫描采样,配置好规则通道后,可以采用软件触发的方式开启AD转换,也可通过外部触发,如下图所示。可以通过定时器以及外部中断方式触发:
如下图为ADC 内部使用框图:

在这里插入图片描述

1.2 定时器

在这里插入图片描述
如上图所示是定时器的内部硬件原理框图,在此使用定时器的TIMER3 的TRGO信号作为ADC转换的触发信号,当接收到一次中断信号后,ADC通道进行转换一次.

3. DMA

在这里插入图片描述
如上图所示,ADC1 使用的是DMA 的stream0 数据流,ADC2使用DMA2 的Stream2数据流.

二、代码实现

2.1初始化

global 数据

__IO uint16_t g_Adc2ConvertedValues[10][6];//6 个通道每个通道采样10次

2.1.1 PIN initial

	static void BspGpioConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_0    
                                   | GPIO_Pin_4   
                                   | GPIO_Pin_7;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0  
                                 | GPIO_Pin_1;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0    
                                 | GPIO_Pin_1 ; 

    GPIO_Init(GPIOC, &GPIO_InitStructure);

    return;
}

2.2 ADC 初始化 代码

static void BspAdcConfig(void)
{
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_InitTypeDef       ADC_InitStructure;

    ADC_CommonInitStructure.ADC_Mode             = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler        = ADC_Prescaler_Div8;
    ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    ADC_InitStructure.ADC_Resolution           = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode         = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode   = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStructure.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_T2_TRGO;
    ADC_InitStructure.ADC_DataAlign            = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion      = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_480Cycles);     // PA0_AD0_AC

    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    ADC_DMACmd(ADC1, ENABLE);
    ADC_Cmd(ADC1, ENABLE);

    ADC_InitStructure.ADC_ScanConvMode         = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_T3_TRGO;
    ADC_InitStructure.ADC_NbrOfConversion      = ADC2_NbrofChannel;
    ADC_Init(ADC2, &ADC_InitStructure);


    ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_480Cycles);     // PA4_AD4_24V_2
    ADC_RegularChannelConfig(ADC2, ADC_Channel_7, 2, ADC_SampleTime_480Cycles);     // PA7_AD7_GNDF
    ADC_RegularChannelConfig(ADC2, ADC_Channel_8, 3, ADC_SampleTime_480Cycles);     // PB0_AD8_24V_OCP_C1
    ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 4, ADC_SampleTime_480Cycles);     // PB1_AD9_24V_OCP_C2
    ADC_RegularChannelConfig(ADC2, ADC_Channel_10,5, ADC_SampleTime_480Cycles);     // PC0_AD10_HOUSING
    ADC_RegularChannelConfig(ADC2, ADC_Channel_11,6, ADC_SampleTime_480Cycles);     // PC1_AD11_24V_1

    ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
    ADC_DMACmd(ADC2, ENABLE);
    ADC_Cmd(ADC2, ENABLE);

    return;
}

2.3 DMA 初始化 代码


static void BspDmaConfig(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    DMA_InitStructure.DMA_Channel            = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)&g_Adc1ConvertedValues;
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize         = 1024 * 2;
    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_FIFOMode           = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    DMA_ITConfig(DMA2_Stream0, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream0, ENABLE);

    DMA_InitStructure.DMA_Channel            = DMA_Channel_1;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)&g_Adc2ConvertedValues;
    DMA_InitStructure.DMA_BufferSize         = ADC2_NbrofChannel * SamplingNumber;//N*M N: channel number M:sampling number
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);

    DMA_Cmd(DMA2_Stream2, ENABLE);

    return;
}

static void BspNvicConfig(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel                   = DMA2_Stream0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return;
}

在调用这几个函数之前必须设置RCC时钟如下代码设置RCC时钟:

static void BspRccConfig(void)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA
                         | RCC_AHB1Periph_GPIOB
                         | RCC_AHB1Periph_GPIOC
                         | RCC_AHB1Periph_DMA2, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2
                         | RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1
                         | RCC_APB2Periph_ADC2, ENABLE);

    return;
}

3.1 定时器初始化

static void BspTimConfig(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    // TIM2设置ADC1  1024Hz
    TIM_TimeBaseStructure.TIM_Prescaler     = 0;
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period        = 84000000 / 1024 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

    // TIM3设置ADC2 1000Hz
    TIM_TimeBaseStructure.TIM_Prescaler     = 84000000 / 1000000 - 1;
    TIM_TimeBaseStructure.TIM_Period        = 1000000 / 1000 - 1;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);

    TIM_Cmd(TIM2, ENABLE);
    TIM_Cmd(TIM3, ENABLE);

    return;
}

3.2 函数调用

void BspAdcInit(void)
{
    BspRccConfig();
    BspGpioConfig();
    BspAdcConfig();
    BspDmaConfig();
    BspNvicConfig();
    BspTimConfig();
    return;
}

在调用BspAdcInit()函数后,就配置完成了ADC+DMA+TIMER的配置.会定时完成采集,且不占用CPU资源.采集的数据将会自动存储在定义的g_Adc2ConvertedValues 全局变量中.

总结

以上流程就是使用STM32的ADC+DMA+timer实现自动定时采样模拟电压的配置使用流程,若读者发先任何疑问,妄指出问题…

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 11:01:01  更:2022-07-03 11:02:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:41:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码