第一次写博客,奉献给STM32了,一直以来都是潜水看博客,希望能够自己也能写一点东西,对自己学习和工作的一个总结,希望能够坚持下去。
项目背景:以57.6kbps的速率采集两个通道的数据
芯片:STM32F205VCT6
总体的思路通过57.6kHz的定时器去触发ADC采样,采样后的数据在通过DMA存放于缓冲区定时产生中断。
由于需要产生57.6KHz的频率,晶振选择9.6MKHz,CPU主频为115.2MHz。
STEP1:配置定时器
通过TIM2去触发两路ADC,详见配置如下
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM2 , ENABLE );
TIM_DeInit ( TIM2 );
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_Period = (57600000/(ADC_SAMPLING_MUL*AIS_MODUL_RATE) - 1 ); //28.8M*2/100/10 = 57.6kHz
TIM_TimeBaseStructure.TIM_Prescaler = ( 1 - 1 );//28.8M*2 = 57.6MHz
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
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_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
//TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE); //开定时器中断测试使用
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
// TIM_ITConfig(TIM2,TIM_IT_CC3,ENABLE); //开定时器中断测试使用
TIM_Cmd ( TIM2, ENABLE );
TIM_InternalClockConfig(TIM2);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_UpdateDisableConfig(TIM2, DISABLE);
}
STEP2:配置ADC
首先需要配置GPIO复用
//GPIO -PB0 PB1 -ADC1 ADC2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( GPIOB, &GPIO_InitStructure );
然后配置ADC
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 , ENABLE);
//ADC Common Init
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
//ADC1 Init
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_CC2;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// ADC1 regular channel 8 configuration
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_144Cycles);
//Enable DMA request after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
//Enable ADC1 DMA
ADC_DMACmd(ADC1, ENABLE);
// Enable ADC1
ADC_Cmd(ADC1, ENABLE);
// ADC2 Init
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_CC3;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC2, &ADC_InitStructure);
// ADC2 regular channel 9 configuration
ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_144Cycles);
// Enable DMA request after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
// Enable ADC2 DMA
ADC_DMACmd(ADC2, ENABLE);
// Enable ADC2
ADC_Cmd(ADC2, ENABLE);
}
STEP3 配置DMA
首先定义DMA中断标志和缓冲区的定义,其中DMA采用乒乓BUF的方式存储和读取数据。
#define DMA_ADC_BUF_BIT = 96 //该数据定义了多长时间产生一次DMA中断
Uint8 Dma2Stream0Flag = 0;//ADC1 接收 数据标志位1--表示有数据 0--表示无数据
Uint8 Dma2Stream2Flag = 0;//ADC2 接收 数据标志位1--表示有数据 0--表示无数据
Uint16 Adc1Buf0[DMA_ADC_BUF_BIT] = {0};//ADC1接收缓存区0
Uint16 Adc1Buf1[DMA_ADC_BUF_BIT] = {0};//ADC1接收缓存区1
Uint16 Adc2Buf0[DMA_ADC_BUF_BIT] = {0};//ADC2接收缓存区0
Uint16 Adc2Buf1[DMA_ADC_BUF_BIT] = {0};//ADC2接收缓存区1
然后对DMA进行参数配置
void DMA2_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
//DMA2 Stream0 channel0 configuration------ADC1
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (Uint32)&ADC1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (Uint32)Adc1Buf0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = DMA_ADC_BUF_BIT;
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_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//DMA double buffer mode
DMA_DoubleBufferModeConfig(DMA2_Stream0,(Uint32)Adc1Buf1,DMA_Memory_0);//DMA_Memory_0首先被传输
DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_ITConfig( DMA2_Stream0, DMA_IT_TC, ENABLE );
DMA_ClearITPendingBit ( DMA2_Stream0, DMA_IT_TCIF0 );
DMA_Cmd(DMA2_Stream0, ENABLE);
//DMA2 Stream2 channel1 configuration------ADC2
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (Uint32)&ADC2->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (Uint32)Adc2Buf0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = DMA_ADC_BUF_BIT;
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_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_DoubleBufferModeConfig(DMA2_Stream2,(Uint32)Adc2Buf1,DMA_Memory_0);//DMA_Memory_0首先被传输
DMA_DoubleBufferModeCmd(DMA2_Stream2,ENABLE);
DMA_Init(DMA2_Stream2, &DMA_InitStructure);
DMA_ITConfig( DMA2_Stream2, DMA_IT_TC, ENABLE );
DMA_ClearITPendingBit ( DMA2_Stream2, DMA_IT_TCIF2 );
DMA_Cmd(DMA2_Stream2, ENABLE);
}
最后再去定义DMA的中断优先级,中断入口函数以及数据的使用
void NVIC_Configuration ( void )
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 );
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void DMA2_Stream0_IRQHandler( void )
{
if( DMA_GetITStatus( DMA2_Stream0, DMA_IT_TCIF0 ) != RESET )
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
Dma2Stream0Flag = 1;
}
}
void DMA2_Stream2_IRQHandler( void )
{
if( DMA_GetITStatus( DMA2_Stream2, DMA_IT_TCIF2 ) != RESET )
{
DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
Dma2Stream2Flag = 1;
}
}
void RECV_Schedule( void )
{
Uint16 i = 0;
Uint16 j = 0;
Uint16 Din[DMA_ADC_BUF_BIT] = {0};
//处理ADC1采样通道A的数据
if( Dma2Stream0Flag == 1 )
{
Dma2Stream0Flag = 0;
if( DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_MEMORY_NO_0 )
{
for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
{
Din[i] = Adc1Buf1[i];
}
}
else
{
for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
{
Din[i] = Adc1Buf0[i];
}
}
}
//处理ADC2采样通道B的数据
if( Dma2Stream2Flag == 1 )
{
Dma2Stream2Flag = 0;
if( DMA_GetCurrentMemoryTarget(DMA2_Stream2) == DMA_MEMORY_NO_0 )
{
for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
{
Din[i] = Adc2Buf1[i];
}
}
else
{
for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
{
Din[i] = Adc2Buf0[i];
}
}
}
}
至此,第一篇博客完成了,写的好粗糙,编辑工具也不会~~~~~~~~还是要多写些~