OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4671|回复: 3

STM32f407 ADC与DMA中断问题

[复制链接]

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
139
金钱
139
注册时间
2019-7-16
在线时间
28 小时
发表于 2021-11-4 21:43:29 | 显示全部楼层 |阅读模式
30金钱
使用STM32f407进行16个通道采样,其中ADC1使用11个通道,ADC3使用5个通道,使用软件触发DMA方式,DMA中断进行读取数据,但是实际过程中发现,只能有一个ADC的DMA可以正常进入中断
代码如下:
void  sADC1_Init(void)
{   
        ADC_CommonInitTypeDef         ADC_CommonInitStructure;
        NVIC_InitTypeDef                 NVIC_InitStructure;
        ADC_InitTypeDef               ADC_InitStructure;       
        GPIO_InitTypeDef                  GPIO_InitStructure;
        DMA_InitTypeDef                 DMA_InitStructure;
  /*********GPIO初始化***************/
//其中ADC1采样口为PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7,PB0,PB1,PC0,PC1,PC2,PC13,PC4,PC5

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC, ENABLE);        //使能GPIOA,GPIOB,GPIOC时钟

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);                         //使能ADC1时钟       
       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;                                                    //GPIO_Mode_AN                                //模拟输入
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;                                //不带上下拉
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//PA2,PA3,PA4,PA5,PA6,PA7
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                                        //初始化GPIOA  
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
        GPIO_Init(GPIOB, &GPIO_InitStructure);                                                        //初始化GPIOB  
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_5;
        GPIO_Init(GPIOC, &GPIO_InitStructure);                                                        //初始化GPIOC

  //初始化ADC1


        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);                                  //ADC1复位
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);                        //复位结束         
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
        DMA_DeInit(DMA2_Stream4);                                                                                // 选择 DMA 通道,通道存在于流中//配置为DMA2的通道2
        while(DMA_GetCmdStatus(DMA2_Stream4)!=DISABLE)


        DMA_InitStructure.DMA_Channel = DMA_Channel_0;
        DMA_InitStructure.DMA_PeripheralBaseAddr = ((u32)&(ADC1->DR));        // 外设基址为:ADC 数据寄存器地址       
        DMA_InitStructure.DMA_Memory0BaseAddr = (u32)(u16 *)wAdc1_Result;                  //外设基地址为ADC3的基质+0x4c
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize =11;       
        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_Medium;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;   // 禁止DMA FIFO ,使用直连模式
          // FIFO 大小,FIFO模式禁止时,这个不用配置
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
       
        DMA_Init(DMA2_Stream4, &DMA_InitStructure); //初始化DMA流,流相当于一个大的管道,管道里面有很多通道
        DMA_ClearFlag(DMA2_Stream4,DMA_IT_TC);


        NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;                                           //抢占优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;                                                    //响应优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        DMA_ITConfig(DMA2_Stream4,DMA_IT_TC,ENABLE);
               


        while (DMA_GetCmdStatus(DMA2_Stream4) != DISABLE) {}

        DMA_Cmd(DMA2_Stream4, ENABLE);                                // 使能DMA流

//        // 使能DMA流
        DMA_Cmd(DMA2_Stream4, ENABLE);

        ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_7Cycles;//两个采样阶段之间的延迟5个时钟
        ADC_CommonInit(&ADC_CommonInitStructure);                                                                //初始化

        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;                                //12位模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                                //扫描模式开启
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                        //关闭连续转换
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;        //确认为软件触发
       
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                                //右对齐       
        ADC_InitStructure.ADC_NbrOfConversion = 11;                                                                  //转换16个通道
        ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化               
       
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 6,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 7,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 8,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 9,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 10,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 11,        ADC_SampleTime_112Cycles);

        ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); //连续使能DMA
        ADC_DMACmd(ADC1, ENABLE);  //使能ADC_DMA
        ADC_Cmd(ADC1, ENABLE);        // 使能ADC
        ADC_SoftwareStartConv(ADC1);

}
oid DMA2_Stream4_IRQHandler()
{

        static u8 num=0;
        if(++num>=100)
        {
                num=0;
        }
        LED1=~LED1;
        if(DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF4) ) //判断DMA传输完成中断  
    {               
                switch (bCS)
                {
                        case 0:
                                wV6_Adc=wAdc1_Result[5];
                                wI3_Adc=wAdc1_Result[6];
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wV6_Adc-_wV6_Adc)>=300)
                                        {
                                                wV6_Adc=_wV6_Adc;
                                        }
                                        if(abs(wI3_Adc-_wI3_Adc)>=300)
                                        {
                                                wI3_Adc=_wI3_Adc;
                                        }

                                }
                               
                                _wV6_Adc=wV6_Adc;       
                                _wI3_Adc=wI3_Adc;
                               
                        break;
                        case 1:
                                wV7_Adc=wAdc1_Result[5];
                                wREV2_Adc=wAdc1_Result[6];
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wV7_Adc-_wV7_Adc)>=300)
                                        {
                                                wV7_Adc=_wV7_Adc;
                                        }
                                        if(abs(wREV2_Adc-_wREV2_Adc)>=300)
                                        {
                                                wREV2_Adc=_wREV2_Adc;
                                        }

                                }
                                _wV7_Adc=wV7_Adc;
                                _wREV2_Adc=wREV2_Adc;
                               
                        break;
                        case 2:
                                wI1_Adc=wAdc1_Result[5];
                                wREV1_Adc=wAdc1_Result[6];       
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wI1_Adc-_wI1_Adc)>=300)
                                        {
                                                wI1_Adc=_wI1_Adc;
                                        }
                                        if(abs(wREV1_Adc-_wREV1_Adc)>=300)
                                        {
                                                wREV1_Adc=_wREV1_Adc;
                                        }
                                }
                                _wI1_Adc=wI1_Adc;
                                _wREV1_Adc=wREV1_Adc;
                        break;
                        case 3:
                                wI2_Adc=wAdc1_Result[5];
                                wREV3_Adc=wAdc1_Result[6];
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wI2_Adc-_wI2_Adc)>=300)
                                        {
                                                wI2_Adc=_wI2_Adc;
                                        }

                                        if(abs(wREV3_Adc-_wREV3_Adc)>=300)
                                        {
                                                wREV3_Adc=_wREV3_Adc;
                                        }

                                }
                                _wI2_Adc=wI2_Adc;
                                _wREV3_Adc=wREV3_Adc;
                        break;
                        default:
                        break;
                }
               
                DMA_ClearFlag(DMA2_Stream4, DMA_IT_TCIF4);
//                        sUart3SendByte(bADC1_CS);       
//               
         }
}





void  sADC3_Init(void)
{   
        ADC_CommonInitTypeDef         ADC_CommonInitStructure;
        ADC_InitTypeDef               ADC_InitStructure;       
        GPIO_InitTypeDef                  GPIO_InitStructure;
        DMA_InitTypeDef                 DMA_InitStructure;
        NVIC_InitTypeDef        NVIC_InitStructure;       
  /*********GPIO初始化***************/
        //PF 6.7.10.3
        //
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);                                //使能GPIOF时钟
  //初始化ADC3
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);                                 //使能ADC3时钟       

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;                                                //模拟输入
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;                                        //不带上下拉
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_4|GPIO_Pin_5;
        GPIO_Init(GPIOF, &GPIO_InitStructure);                                                                //初始化  

       

       

        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);                                          //ADC3复位
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);                                //复位结束         
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
       
        DMA_DeInit(DMA2_Stream0);                                                                                // 选择 DMA 通道,通道存在于流中//配置为DMA2的通道2
        while(DMA_GetCmdStatus(DMA2_Stream0)!=DISABLE)
       
       
        DMA_InitStructure.DMA_Channel = DMA_Channel_2;                                                 // 外设基址为:ADC 数据寄存器地址               
        DMA_InitStructure.DMA_PeripheralBaseAddr = ((u32)ADC3+0x4c);        //外设基地址为ADC3的基质+0x4c
                       
        DMA_InitStructure.DMA_Memory0BaseAddr = (u32)(u16 *)wAdc3_Result;  // 存储器地址,实际上就是一个内部SRAM的变量       
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;         // 数据传输方向为外设到存储器               
        DMA_InitStructure.DMA_BufferSize =5;                                                // 缓冲区大小为,指一次传输的数据量
        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_Medium;                                        // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                           // 禁止DMA FIFO ,使用直连模式
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;// FIFO 大小,FIFO模式禁止时,这个不用配置
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;   
       
        DMA_Init(DMA2_Stream0, &DMA_InitStructure); //初始化DMA流,流相当于一个大的管道,管道里面有很多通道       
        DMA_ClearFlag(DMA2_Stream0,DMA_IT_TC);


        NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00;                                           //抢占优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;                                                    //响应优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        DMA_ITConfig(DMA2_Stream0,DMA_IT_TC,ENABLE);
               

        while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE){}
        DMA_Cmd(DMA2_Stream0, ENABLE);                                // 使能DMA流


        ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;                        //独立模式
        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;                        //预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_7Cycles;//两个采样阶段之间的延迟5个时钟

        ADC_CommonInit(&ADC_CommonInitStructure);//初始化

        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;                                                //12位模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                                                //扫描模式开启
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                                        //连续转换
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止外部触发
//        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;                 //使用T4触发
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                                //右对齐       
        ADC_InitStructure.ADC_NbrOfConversion =5;                                                                  //转换5个通道
        ADC_Init(ADC3, &ADC_InitStructure);//ADC初始化       


        ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 1,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 2,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 3,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 4,        ADC_SampleTime_112Cycles);
        ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 5,        ADC_SampleTime_112Cycles);
       
       
        ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); //连续使能DMA
        ADC_DMACmd(ADC3, ENABLE);  //使能ADC_DMA
        ADC_Cmd(ADC3, ENABLE);         // 使能ADC
        ADC_SoftwareStartConv(ADC3);
}       

#endif




void DMA2_Stream0_IRQHandler()        //ADC3中断函数

{
               
        if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))  //判断DMA传输完成中断  
    {  

                switch (bCS)
                {
                        case 0:
                               
                                wDCI1_Adc=wAdc3_Result[2];
                                wRET2_Adc=wAdc3_Result[3];

                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wDCI1_Adc-_wDCI1_Adc)>=300)
                                        {
                                                wDCI1_Adc=_wDCI1_Adc;
                                        }
                                        if(abs(wRET2_Adc-_wRET2_Adc)>=300)
                                        {
                                                wRET2_Adc=_wRET2_Adc;
                                        }
                                }
                                _wDCI1_Adc=wDCI1_Adc;
                                _wRET2_Adc=wRET2_Adc;       
                        break;
                        case 1:
                                wREI2_Adc=wAdc3_Result[2];
                                wT6_Adc=wAdc3_Result[3];
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wREI2_Adc-_wREI2_Adc)>=300)
                                        {
                                                wREI2_Adc=_wREI2_Adc;
                                        }
                                        if(abs(wT6_Adc-_wT6_Adc)>=300)
                                        {
                                                wT6_Adc=_wT6_Adc;
                                        }
                                }
                                _wREI2_Adc=wREI2_Adc;
                                _wT6_Adc=wT6_Adc;
                       
                        break;
                        case 2:                       
                                wREI1_Adc=wAdc3_Result[2];
                                wDCI2_Adc=wAdc3_Result[3];
                                if(bAdcChangeFlag==1)
                                {
                                        if(abs(wREI1_Adc-_wREI1_Adc)>=300)
                                        {
                                                wREI1_Adc=_wREI1_Adc;
                                        }

                                        if(abs(wDCI2_Adc-_wDCI2_Adc)>=300)
                                        {
                                                wDCI2_Adc=_wDCI2_Adc;
                                        }
                                }
                               
                                _wREI1_Adc=wREI1_Adc;
                                _wDCI2_Adc=wDCI2_Adc;
                        break;
                        case 3:
                                wDAC_Adc=wAdc3_Result[2];
                                wT1_Adc=wAdc3_Result[3];
                        if(bAdcChangeFlag==1)
                        {
                                if(abs(wDAC_Adc-_wDAC_Adc)>=300)
                                {
                                        wDAC_Adc=_wDAC_Adc;
                                }
                                if(abs(wT1_Adc-_wT1_Adc)>=300)
                                {
                                        wT1_Adc=_wT1_Adc;
                                }

                        }
                        _wDAC_Adc=wDAC_Adc;
                        _wT1_Adc=wT1_Adc;
                               
                        break;
                        default:
                        break;
                }
                 DMA_ClearFlag(DMA2_Stream0, DMA_IT_TCIF0);
               
         }
}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
139
金钱
139
注册时间
2019-7-16
在线时间
28 小时
 楼主| 发表于 2021-11-4 21:47:57 | 显示全部楼层
回复

使用道具 举报

2

主题

592

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1458
金钱
1458
注册时间
2019-7-28
在线时间
137 小时
发表于 2021-11-5 11:57:28 | 显示全部楼层
。。。。。这么长 建议还是精简下吧 这么长谁看啊
回复

使用道具 举报

11

主题

2131

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4729
金钱
4729
注册时间
2015-1-10
在线时间
591 小时
发表于 2021-11-9 10:16:32 | 显示全部楼层
ADC1+DMA结束后再ADC3+DMA,再ADC1+DMA,如此循环
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 15:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表