打印
[其他ST产品]

STM32的DMA2和ADC3搭配使用采集交流信号

[复制链接]
288|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
舒伯特玫瑰|  楼主 | 2022-11-26 23:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AD, ADC, DM, DMA, ST
请教大神,我准备做19年的电赛D题,我想用不同的ADC检测波形,计算峰峰值,我用ADC1和DMA1可以采集到数据,但用ADC3和DMA2就不行,根本就不去DMA3的中断函数,我已经检查了好几天了,就是不知道哪里错了,请大神赐教。
这是我的DMA2的配置
void MYDMA2_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
        DMA_InitTypeDef DMA_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);        //使能DMA传输
        
    DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存//
        DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在循环模式
//        DMA_InitStructure.DMA_Mode =DMA_Mode_Normal;//工作在一次模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA_CHx, &DMA_InitStructure);  //ADC1匹配DMA通道1
        
        DMA_ITConfig(DMA2_Channel5,DMA2_IT_TC5,ENABLE);        //使能DMA传输中断        
        
        //配置中断优先级
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;               
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        
        NVIC_Init(&NVIC_InitStructure);        

        DMA_Cmd(DMA2_Channel5,ENABLE);//使能DMA通道
}

使用特权

评论回复
沙发
舒伯特玫瑰|  楼主 | 2022-11-26 23:05 | 只看该作者
这是我的ADC3的配置
void  Adc3_Init(void)
{         
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC3, ENABLE );          //使能ADC3通道时钟

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA6 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//PC1,通道11
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);        

        ADC_DeInit(ADC3);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在非连续转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC3;        //转换由定时器2的通道2触发(只有在上升沿时可以触发)
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC3, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

        ADC_Cmd(ADC3, ENABLE);        //使能指定的ADC1
        ADC_DMACmd(ADC3, ENABLE);        //ADC的DMA功能使能
        ADC_ResetCalibration(ADC3);        //使能复位校准   
        ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5 );//ADC1通道6,采样时间为239.5周期         
        ADC_ResetCalibration(ADC3);//复位较准寄存器
        while(ADC_GetResetCalibrationStatus(ADC3));        //等待复位校准结束
        ADC_StartCalibration(ADC3);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC3));         //等待校准结束
        ADC_SoftwareStartConvCmd(ADC3, ENABLE);                //使能指定的ADC1的软件转换启动功能

}        

使用特权

评论回复
板凳
舒伯特玫瑰|  楼主 | 2022-11-26 23:09 | 只看该作者
这是我DMA2的中断函数
void DMA2_Channel5_IRQHandler(void)
{
        LED0=!LED0;
        delay_ms(100);
        if(DMA_GetITStatus(DMA2_IT_TC5)!=RESET)
        {
                adcx2[t]=currentadc2;
                t++;
                if(t==NPT)
                {
                        t=0;
                        adc_flag2=1;
                        
                        DMA_Cmd(DMA2_Channel5, DISABLE);        //失能DMA
                }
        }
        DMA_ClearITPendingBit(DMA2_IT_TC5);
}

使用特权

评论回复
地板
舒伯特玫瑰|  楼主 | 2022-11-26 23:10 | 只看该作者
STM32的DMA2和ADC3搭配使用

请教大神,我准备做19年的电赛D题,我想用不同的ADC检测波形,计算峰峰值,我用ADC1和DMA1可以采集到数据,但用ADC3和DMA2就不行,根本就不去DMA3的中断函数,我已经检查了好几天了,就是不知道哪里错了,请大神赐教。
这是我的DMA2的配置
void MYDMA2_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
        DMA_InitTypeDef DMA_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);        //使能DMA传输
        
    DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存//
        DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在循环模式
//        DMA_InitStructure.DMA_Mode =DMA_Mode_Normal;//工作在一次模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA_CHx, &DMA_InitStructure);  //ADC1匹配DMA通道1
        
        DMA_ITConfig(DMA2_Channel5,DMA2_IT_TC5,ENABLE);        //使能DMA传输中断        
        
        //配置中断优先级
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;               
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        
        NVIC_Init(&NVIC_InitStructure);        

        DMA_Cmd(DMA2_Channel5,ENABLE);//使能DMA通道
}

使用特权

评论回复
5
舒伯特玫瑰|  楼主 | 2022-11-26 23:10 | 只看该作者

这是我的ADC3的配置
void  Adc3_Init(void)
{         
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC3, ENABLE );          //使能ADC3通道时钟

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA6 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//PC1,通道11
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);        

        ADC_DeInit(ADC3);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在非连续转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC3;        //转换由定时器2的通道2触发(只有在上升沿时可以触发)
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC3, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

        ADC_Cmd(ADC3, ENABLE);        //使能指定的ADC1
        ADC_DMACmd(ADC3, ENABLE);        //ADC的DMA功能使能
        ADC_ResetCalibration(ADC3);        //使能复位校准   
        ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5 );//ADC1通道6,采样时间为239.5周期         
        ADC_ResetCalibration(ADC3);//复位较准寄存器
        while(ADC_GetResetCalibrationStatus(ADC3));        //等待复位校准结束
        ADC_StartCalibration(ADC3);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC3));         //等待校准结束
        ADC_SoftwareStartConvCmd(ADC3, ENABLE);                //使能指定的ADC1的软件转换启动功能

}      

使用特权

评论回复
6
舒伯特玫瑰|  楼主 | 2022-11-26 23:11 | 只看该作者

这是我的DMA2的中断函数
void DMA2_Channel5_IRQHandler(void)
{
        LED0=!LED0;
        delay_ms(100);
        if(DMA_GetITStatus(DMA2_IT_TC5)!=RESET)
        {
                adcx2[t]=currentadc2;
                t++;
                if(t==NPT)
                {
                        t=0;
                        adc_flag2=1;
                        
                        DMA_Cmd(DMA2_Channel5, DISABLE);        //失能DMA
                }
        }
        DMA_ClearITPendingBit(DMA2_IT_TC5);
}

使用特权

评论回复
7
rzjvv| | 2022-11-26 23:22 | 只看该作者
我的天,你中断里面那个100ms延时是认真的吗??

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

227

帖子

2

粉丝