|
STM32F4 使用定时器1触发ADC1采样频率200Hz+DMA双缓存中断,为什么取了1024个数据,前后两次进入DMA中断的时间间隔只有2秒左右
代码如下
#include "bsp.h"
/* define ---------------------------------------------------------------------*/
#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C)
/* 变量 ----------------------------------------------------------------------*/
uint16_t ADC1ConvertedValue_a[1024] = {0};
uint16_t ADC1ConvertedValue_b[1024] = {0};
uint8_t flag_dma = 0;
/* 供本文件使用 --------------------------------------------------------------*/
static void TIM1_Config(void);
/*
*********************************************************************************************************
* 函 数 名: bsp_InitADC
* 功能说明: ADC初始化
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitADC(void)
{
/* 配置GPIO. */
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* 配置ADC引脚为模拟输入模式 ******************************/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; /* 设为输出口 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 设为推挽模式 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* 上下拉电阻不使能 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; /* IO口最大速度 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* 配置ADC引脚为模拟输入模式 ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
{
DMA_InitTypeDef DMA_InitStructure = {0};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* DMA2 Stream0 channel0 配置用于ADC1 **************************************/
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue_a;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1024;
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_PeripheralDataSize_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_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
//双缓冲模式设置
// DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)(u16 *)(ADC1ConvertedValue_b),DMA_Memory_1); //DMA_Memory_0首先被传输
// DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
}
/*DMA2_Stream0 传输完成中断使能 传输一半中断使能*/
{
NVIC_InitTypeDef NVIC_InitStructure = {0};
// 配置DMA中断优先级
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 可以根据需要设置中断优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT); //清除中断标志
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); // 使能DMA传输完成中断
DMA_ITConfig(DMA2_Stream0, DMA_IT_HT, ENABLE); // 使能DMA半传输完成中断
}
/* ADC公共部分初始化**********************************************************/
{
/*
***************************************************************************
PCLK2 = HCLK / 2
下面选择的是2分频
ADCCLK = PCLK2 /2 = HCLK / 4 = 168 / 4 = 42M [手册最大时36M,此时有超频]
ADC采样频率: Sampling Time + Conversion Time = 3 + 12 cycles = 15cyc
Conversion Time = 42MHz / 15cyc = 2.8Mbps.
****************************************************************************
*/
ADC_CommonInitTypeDef ADC_CommonInitStructure = {0};
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInit(&ADC_CommonInitStructure);
}
/* 配置 PC0/ADC1_IN10 ******************************************************************/
{
ADC_InitTypeDef ADC_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2;
/* ADC1 规则通道配置 -------------------------------------------------------*/
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
/* 使能 ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 使能DMA请求 最后一个传输结束后继续使能DMA, 对于循环模式必须使能 -------*/
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 --------------------------------------------------------------*/
ADC_Cmd(ADC1, ENABLE);
}
TIM1_Config();
}
void DMA2_Stream0_IRQHandler(void)
{
// DMA半传输中断标志位
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0))
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0); // 清除中断标志
if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_Memory_1)
{
flag_dma = 1;
}
else
{
flag_dma = 2;
}
}
// DMA传输完成后的处理代码
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); // 清除中断标志
}
}
/*
*********************************************************************************************************
* 函 数 名: TIM1_Config
* 功能说明: 配置定时器1,用于触发ADC, 触发频率1Msps
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void TIM1_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
TIM_OCInitTypeDef TIM_OCInitStructure = {0};
/* 使能定时器1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器1时钟
/* 先禁能再配置 */
TIM_Cmd(TIM1, DISABLE);
/*
********************************************************************************
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
HCLK = SYSCLK / 1 (AHB1Periph)
PCLK2 = HCLK / 2 (APB2Periph)
PCLK1 = HCLK / 4 (APB1Periph)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
TIM6 更新周期是 = TIM1CLK / (TIM_Period + 1)/(TIM_Prescaler + 1)
********************************************************************************
*/
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //初始化定时器1的寄存器为复位值
TIM_TimeBaseStructure.TIM_Period = 50 - 1; //ARR自动重装载寄存器周期的值(定时时间)到设置频率后产生个更新或者中断(也是说定时时间到)
TIM_TimeBaseStructure.TIM_Prescaler = 16800 - 1; //PSC时钟预分频数 例如:时钟频率=TIM1CLK/(时钟预分频+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //CR1->CKD时间分割值
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //CR1->CMS[1:0]和DIR定时器模式 向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000; /* TIM1 和 TIM8 必须设置 */
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/**************ADC1的触发***********************************************/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period - 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; /* only for TIM1 and TIM8. 此处和正相引脚不同 */
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; /* only for TIM1 and TIM8. */
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; /* only for TIM1 and TIM8. */
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
//TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CMR2 设置预装载使能 更新事件产生时写入有效
//TIM_ARRPreloadConfig(TIM1, ENABLE); //CR1 设置ARR自动重装 更新事件产生时写入有效
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE); //使能PWM 输出
} |
|