Stm32F103 ADC3+DMA中断触发
前言
调试了半天终于正常了,由于之前采用ADC1所以没有问题,最后移植代码的时候在查了函数库手册后完成试验。 原理是比较简单但是配置起来不通过手册一个个去对参数很容易出错,出了错还不知道错了在哪里。二、示例代码
由于移植的很多注释没有改
void TIM1_Config() //定时器TIM1配置,周期为nus
{
uint16_t nus=149;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能TIM1的时钟
TIM_TimeBaseStructure.TIM_Period = nus; //nus=100-1,则周期为0.1ms
TIM_TimeBaseStructure.TIM_Prescaler = 71; //系统主频72M,预分频系数为71,相当于72分频,1MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* TIM1 channel1 configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse =75;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_Cmd(TIM1,ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
//ADC_DMA 初始化
void ADC_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM1_Config(); //ADC触发时钟,触发周期为100us
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOF |RCC_APB2Periph_ADC3, ENABLE ); //使能ADC1通道时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//打开DMA的时钟
//A1->PA0 B1->PA2 C1->PA3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
//A2->PF6 B2->PF7 C2->PF8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA2_Channel5);//复位DAM1寄存器到缺省状态
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC3->DR);//ADC1的数据寄存器作为源
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADCConvertedValue;//目标地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = //根据需要
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不自增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设传输单位16bits
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存传输单位16bits
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环工作
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA传输类型:不是内存到内存
DMA_Init(DMA2_Channel5, &DMA_InitStructure);
//DMA中断初始化
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Channel5, DMA_IT_TC | DMA_IT_HT, ENABLE); //DMA中断配置========================== 通道1传输完成中断 通道1传输过半中断
DMA_Cmd(DMA2_Channel5, ENABLE);//使能DMA通道
/* ADC1 configuration ------------------------------------------------------*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
ADC_DeInit(ADC3); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在多通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3; //转换由外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = //根据需要
ADC_Init(ADC3, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
/* 转换通道与转换次序 */
ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 1, ADC_SampleTime_239Cycles5); //
ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 2, ADC_SampleTime_239Cycles5); //
ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 3, ADC_SampleTime_239Cycles5); //
ADC_DMACmd(ADC3, ENABLE);
ADC_Cmd(ADC3, ENABLE);
ADC_ExternalTrigConvCmd(ADC3, ENABLE);
ADC_ResetCalibration(ADC3);//ADC复位校准
while(ADC_GetResetCalibrationStatus(ADC3)){};//等待完成
ADC_StartCalibration(ADC3);//校准
while(ADC_GetCalibrationStatus(ADC3)){};//等待校准完成
}
/*******************************************************************************
* 函数名称:DMA1_Channel1_IRQHandler
* 函数功能:DMA的数据采集计算
* 输入参数:none
* 输出参数:none
* 使用或影响的全局变量:
* 主要函数过程:
*******************************************************************************/
u8 LedSt=0;
void DMA2_Channel4_5_IRQHandler(void)
{
static u16 BufferOffset=0; // 每一个采样点
static u16 i,j;
if (DMA_GetFlagStatus(DMA2_IT_TE5)) // 当前是通道1传输错误中断
{
DMA_ClearITPendingBit(DMA2_IT_TE5);
}
if( DMA_GetFlagStatus(DMA2_IT_HT5)) // 当前是通道 1 传输过半中断 (半满中断)
{
DMA_ClearITPendingBit(DMA2_IT_HT5); // 通道1传输过半中断 清空
BufferOffset=0; // 半满中断数据量
}
if( DMA_GetFlagStatus(DMA2_IT_TC5)) // 通道1传输完成中断(全满中断)
{
DMA_ClearITPendingBit(DMA2_IT_TC5);
BufferOffset = ADC_NUMBER*10; // 全满中断数据量
}
}
小记:
从这个中对于ADC和DMA的使用有了更深的理解,在写驱动的时候尤其是变更了端口的查手册是最好方法。函数库手册和设计参考手册。
STM32固件库库
STM32中文参考手册