STM32定时TIM2触发ADC采样,使用DMA保存结果

来源:本站
导读:目前正在解读《STM32定时TIM2触发ADC采样,使用DMA保存结果》的相关信息,《STM32定时TIM2触发ADC采样,使用DMA保存结果》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《STM32定时TIM2触发ADC采样,使用DMA保存结果》的详细说明。
简介:ADC的速度由2个参数决定,它是采样时间和转换时间之和:TCONV = 采样时间 +12.5个ADC时钟周期采样时间共有8种选择:1.5、7.5、13.5、28.5、41.5、55.5、71.5和239.5;若ADC的时钟频率=14MHz,则最高ADC的采样频=14/(12.5+1.5)=1MHz;

1.adc.h文件

//ADC-------------------------------------------------------------------------//

#ifndef __EVAL_ADC_H

#define __EVAL_ADC_H

// Includes ------------------------------------------------------------------//

#include "stm32f10x.h"

#include "eval.h"

// Exported types ------------------------------------------------------------//

typedef struct

{

GPIO_TypeDef* io_gpio_port;

const uint16_t io_gpio_pin;

const uint32_t io_gpio_clk;

const uint8_t adc_channel;

const uint8_t adc_sample;

}ADC_CONFIG_STRUCT;

// Exported constants --------------------------------------------------------//

// Exported macro ------------------------------------------------------------//

// Exported define -----------------------------------------------------------//

#define ADC1_DR_Address ((uint32_t)0x4001244C)

//ADC_DR(ADC规则数据寄存器),偏移量=0x4c ADC1(0x40012400-0x400127ff)

//so ADC1_DR_Address=0x40012400+0x4c

#define ADC_USE_DMA 1//仅使用DMA方式,才能同时进行多路采样

#define ADC_USE_TIM 1//=1定时器触发扫描,=0为连续扫描

//ADC输入 PA0

#define ADCn 3

#define ADC_1 IO1 //信号1

#define ADC_2 IO2 //信号2

#define ADC_3 IO3 //信号3

#if PLATFORM_PKT

#define ADC_1_PIN GPIO_Pin_1

#define ADC_1_GPIO_PORT GPIOA

#define ADC_1_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_1_CHANNEL ADC_Channel_1

#define ADC_1_SAMPLE ADC_SampleTime_239Cycles5

#define ADC_2_PIN GPIO_Pin_0

#define ADC_2_GPIO_PORT GPIOA

#define ADC_2_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_2_CHANNEL ADC_Channel_0

#define ADC_2_SAMPLE ADC_SampleTime_239Cycles5

#define ADC_3_PIN GPIO_Pin_2

#define ADC_3_GPIO_PORT GPIOA

#define ADC_3_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_3_CHANNEL ADC_Channel_2

#define ADC_3_SAMPLE ADC_SampleTime_239Cycles5

#define ADC_4_PIN GPIO_Pin_3

#define ADC_4_GPIO_PORT GPIOA

#define ADC_4_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_4_CHANNEL ADC_Channel_3

#define ADC_4_SAMPLE ADC_SampleTime_239Cycles5

#define ADC_5_PIN GPIO_Pin_1

#define ADC_5_GPIO_PORT GPIOA

#define ADC_5_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_5_CHANNEL ADC_Channel_1

#define ADC_5_SAMPLE ADC_SampleTime_239Cycles5

#define ADC_6_PIN GPIO_Pin_1

#define ADC_6_GPIO_PORT GPIOA

#define ADC_6_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_6_CHANNEL ADC_Channel_1

#define ADC_6_SAMPLE ADC_SampleTime_239Cycles5//ADC_SampleTime_7Cycles5//

#else

#define ADC_1_PIN GPIO_Pin_0

#define ADC_1_GPIO_PORT GPIOA

#define ADC_1_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC_1_CHANNEL ADC_Channel_0

#define ADC_1_SAMPLE ADC_SampleTime_239Cycles5//ADC_SampleTime_7Cycles5//

#endif

//----------------------------------------------------------------------------//

/*

#define ADC16_PIN GPIO_Pin_0

#define ADC16_GPIO_PORT GPIOA

#define ADC16_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC16_CHANNEL ADC_Channel_16//通道16(内部温度)

#define ADC16_SAMPLE ADC_SampleTime_239Cycles5

#define ADC17_PIN GPIO_Pin_0

#define ADC17_GPIO_PORT GPIOA

#define ADC17_GPIO_CLK RCC_APB2Periph_GPIOA

#define ADC17_CHANNEL ADC_Channel_17//通道17(内部1.2v参照电压)

#define ADC17_SAMPLE ADC_SampleTime_239Cycles5

*/

// External variables --------------------------------------------------------//

extern volatile uint16_t ADC_Value[ADCn];

extern uint16_t ADC_ConvertedValue[ADCn];

// extern uint16_t ADC_ConvertedValue[3];

// extern volatile uint8_t adc_dma_simple_ok;

// Exported functions ------------------------------------------------------- //

void ADC_Configuration(void);

uint16_t Get_ADC_Converted_Values(uint8_t channel);

void ADC_Sample_Frequency_Set(u32 Frequency);

#endif

//----------------------------------------------------------------------------//

2.adc.c

/*

规则组采集多路电压时,使用DMA方式,且必须启用扫描模式,否则只能单路采样;

ADC时钟,必须<14MHz;

ADC的速度由2个参数决定,它是采样时间和转换时间之和:

TCONV = 采样时间 + 12.5个ADC时钟周期

采样时间共有8种选择:1.5、7.5、13.5、28.5、41.5、55.5、71.5和239.5;

若ADC的时钟频率=14MHz,则最高ADC的采样频率=14/(12.5+1.5)=1MHz;最低=14/(12.5+239.5)=55.56kHz

若ADC的时钟频率=12MHz,则最低ADC的采样频率=12/(12.5+239.5)=47.62kHz;

*/

// Includes ------------------------------------------------------------------//

#include "adc.h"

#include "ucos_ii.h"

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

#ifdef OS_uCOS_II_H

OS_EVENT* adc_dma_simple_ok;//信号量

#else

volatile uint8_t adc_dma_simple_ok = 0;

#endif

/* Extern variables ----------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//

ADC_CONFIG_STRUCT adc_struct[ADCn] =

{

{ADC_1_GPIO_PORT, ADC_1_PIN, ADC_1_GPIO_CLK, ADC_1_CHANNEL, ADC_1_SAMPLE},

{ADC_1_GPIO_PORT, ADC_1_PIN, ADC_1_GPIO_CLK, ADC_Channel_Vrefint, ADC_1_SAMPLE},

{ADC_1_GPIO_PORT, ADC_1_PIN, ADC_1_GPIO_CLK, ADC_Channel_TempSensor, ADC_1_SAMPLE},

#if 0

{ADC_2_GPIO_PORT, ADC_2_PIN, ADC_2_GPIO_CLK, ADC_2_CHANNEL, ADC_2_SAMPLE},

{ADC_3_GPIO_PORT, ADC_3_PIN, ADC_3_GPIO_CLK, ADC_3_CHANNEL, ADC_3_SAMPLE},

{ADC_4_GPIO_PORT, ADC_4_PIN, ADC_4_GPIO_CLK, ADC_4_CHANNEL, ADC_4_SAMPLE},

{ADC_5_GPIO_PORT, ADC_5_PIN, ADC_5_GPIO_CLK, ADC_5_CHANNEL, ADC_5_SAMPLE},

{ADC_6_GPIO_PORT, ADC_6_PIN, ADC_6_GPIO_CLK, ADC_6_CHANNEL, ADC_6_SAMPLE},

#endif

};

uint16_t ADC_ConvertedValue[ADCn] =

{

0

};

//----------------------------------------------------------------------------//

void ADC_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

ADC_InitTypeDef ADC_InitStructure;

uint8_t i;

// Enable ADC1 clock

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE);

//ADC管脚GPIO配置

for(i = 0; i < ADCn; i++)

{

RCC_APB2PeriphClockCmd(adc_struct[i].io_gpio_clk, ENABLE);

GPIO_InitStructure.GPIO_Pin = adc_struct[i].io_gpio_pin;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_Init(adc_struct[i].io_gpio_port, &GPIO_InitStructure);

}

//

#if ADC_USE_DMA

{

DMA_InitTypeDef DMA_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //Enable DMA1 clock

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

DMA_DeInit(DMA1_Channel1);

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //指定外设基址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ADC_ConvertedValue; //指定内存基址

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设为源(外设->内存)

DMA_InitStructure.DMA_BufferSize = ADCn; //设置缓冲区大小

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定(ADC结果)

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增(存储)

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设传输单位:16bit

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存传输单位:16bit

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环模式

DMA_InitStructure.DMA_Priority = DMA_Priority_High; //选择DMA优先级

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //MA传输类型,不是内存到内存

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

DMA_Cmd(DMA1_Channel1, ENABLE);

}

#endif

//内部温度对应16通道,无引脚,只需开启adc时钟即可.

//内部参考电压对应17通道,无引脚,只需开启时钟.

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC独立模式

ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐

ADC_InitStructure.ADC_NbrOfChannel = 1; //转换组的通道数目

#if ADC_USE_DMA

ADC_InitStructure.ADC_ScanConvMode = ENABLE; //必须启用扫描模式

ADC_InitStructure.ADC_NbrOfChannel = ADCn; //转换组的通道数目

#endif

#if ADC_USE_TIM//使用定时器触发

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //不使用连续转换

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//定时器2触发

#endif

ADC_Init(ADC1, &ADC_InitStructure);

RCC_ADCCLKConfig(RCC_PCLK2_Div8);//配置ADC时钟,为PCLK2的6分频,即12MHz,时钟必须<14MHz;

ADC_TempSensorVrefintCmd(ENABLE);//使能温度传感器

#if ADC_USE_DMA

for(i = 0; i < ADCn; i++)

{

ADC_RegularChannelConfig(ADC1, adc_struct[i].adc_channel, i + 1, adc_struct[i].adc_sample);

}

DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

ADC_DMACmd(ADC1, ENABLE);

#else

ADC_RegularChannelConfig(ADC1, adc_struct[0].adc_channel, 1, adc_struct[0].adc_sample);

#endif

ADC_Cmd(ADC1, ENABLE);

//使能ADC1的复位校准寄存器

ADC_ResetCalibration(ADC1);

while(ADC_GetResetCalibrationStatus(ADC1));

//开始校准ADC1

ADC_StartCalibration(ADC1);

while(ADC_GetCalibrationStatus(ADC1));

#if ADC_USE_TIM

ADC_ExternalTrigConvCmd(ADC1, ENABLE);//使能ADC经外部触发启动转换功能

#endif

#if !ADC_USE_TIM

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //启动上面设置好的一个通道,进行转换

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待EOC置位

#endif

}

//----------------------------------------------------------------------------//

void ADC_Sample_Frequency_Set(u32 Frequency)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_Cmd(TIM2, DISABLE); //先停止TIM2时钟

TIM_TimeBaseStructure.TIM_Period = 3599; //APR寄存器

TIM_TimeBaseStructure.TIM_Prescaler = 3999;//3;//(20,000 / Frequency - 1);//预分频值,用来调整频率,分频系数=1000khz/(prescaler+1)

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x00; //溢出指定(+1)次数后产生中断

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = 1; //!!必须<=TIM_Period!!

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//

TIM_OC2Init(TIM2, &TIM_OCInitStructure);

TIM_Cmd(TIM2, ENABLE);

}

//----------------------------------------------------------------------------//

#if !ADC_USE_TIM

#define VOLTAGE_OVER_SAMPLING 0//过采样2^N次

uint16_t Get_ADC_Converted_Values(uint8_t channel)//提取通道电压

{

uint32_t adc_value = 0;

uint16_t i = 0;

//通道n,规则组序号1,。。。

ADC_RegularChannelConfig(ADC1, adc_struct[channel].adc_channel, 1, adc_struct[channel].adc_sample);

ADC_Cmd(ADC1, ENABLE); //使能ADC1

for(i = 0; i < (1<<VOLTAGE_OVER_SAMPLING); i++)

{

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //启动上面设置好的一个通道,进行转换

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待EOC置位

adc_value += ADC_GetConversionValue(ADC1); //把数据寄存器的值读走

}

return (adc_value>>VOLTAGE_OVER_SAMPLING);

}

#endif

//----------------------------------------------------------------------------//

uint16_t Get_ADC_Converted_Values0(uint8_t channel)//提取指定通道电压

{

ADC_RegularChannelConfig(ADC1, adc_struct[channel].adc_channel, 1, adc_struct[channel].adc_sample);

ADC_Cmd(ADC1, ENABLE);

#if !ADC_USE_DMA

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //启动上面设置好的一个通道,进行转换

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待EOC置位

#endif

return ADC_GetConversionValue(ADC1); //把数据寄存器的值读走

}

//----------------------------------------------------------------------------//

void DMA1_Channel1_IRQHandler()

{

if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)

{

#ifdef OS_uCOS_II_H

OSSemPost(adc_dma_simple_ok);

#else

adc_dma_simple_ok = 1;

#endif

DMA_ClearITPendingBit(DMA1_IT_TC1);

}

}

//----------------------------------------------------------------------------//

3.主程序中调用

extern OS_EVENT* adc_dma_simple_ok; //定义信号量

3.1.信号量初始化

adc_dma_simple_ok = OSSemCreate(0);

3.2.等待DMA中断,接收信号量

OSSemPend(adc_dma_simple_ok, 0, &err);

if(err == OS_NO_ERR)

{

//adc_dma_simple_ok = 0;

sprintf(tmp_str, "电压=%d,%d,%d,%drn", ADC_ConvertedValue[0],ADC_ConvertedValue[1],ADC_ConvertedValue[2],adc_tmp);

USB_Put_Str_PC((uint8_t *)tmp_str);

}

提醒:《STM32定时TIM2触发ADC采样,使用DMA保存结果》最后刷新时间 2024-03-14 00:54:10,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《STM32定时TIM2触发ADC采样,使用DMA保存结果》该内容的真实性请自行鉴别。