打印
[STM32F4]

stm32f407之三ADC交替采样(操作寄存器)

[复制链接]
1878|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
三ADC交替采样
在多ADC模式中,ADC1为主,ADC2或ADC3为从,交替或者同时触发,工作模式取决于ADC_CCR寄存器的MULTI[4:0]。
       多ADC模式中,转换后的数据可以多模式的数据寄存器(ADC_CDR)中读取。状态可以在多模式的状态寄存器(ADC_CSR)读取。

使用特权

评论回复
沙发
caoyunhj2301|  楼主 | 2022-3-31 16:01 | 只看该作者
多ADC模式下的DMA传输方式:

    方式1:每个AD转换完都发出DMA请求,多模式的数据寄存器(ADC_CDR)用低位保存转换结果。

1st request: ADC_CDR[31:0] = ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC2_DR[15:0]

3rd request: ADC_CDR[31:0] = ADC3_DR[15:0]

4th request: ADC_CDR[31:0] = ADC1_DR[15:0]

使用特权

评论回复
板凳
caoyunhj2301|  楼主 | 2022-3-31 16:02 | 只看该作者
方式2:每两个AD转换完都发出DMA请求。

双ADC模式:

高十六位保存ADC2结果,低十六位保存ADC1结果

1st request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

三ADC模式:

1st request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC1_DR[15:0] |ADC3_DR[15:0]

3rd request: ADC_CDR[31:0] = ADC3_DR[15:0] |ADC2_DR[15:0]

4th request: ADC_CDR[31:0] = ADC2_DR[15:0] |ADC1_DR[15:0]

使用特权

评论回复
地板
caoyunhj2301|  楼主 | 2022-3-31 16:03 | 只看该作者
方式2:每两个AD转换完都发出DMA请求。与方式2相似,但是DMA以半字方式传输。

用于6位或者8位分辨率中。

双ADC模式:

高8位保存ADC2结果,低8位保存ADC1结果

1st request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

2nd request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

三ADC模式:

1st request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]

2nd request: ADC_CDR[15:0] = ADC1_DR[7:0] | ADC3_DR[7:0]

3rd request: ADC_CDR[15:0] = ADC3_DR[7:0] | ADC2_DR[7:0]

4th request: ADC_CDR[15:0] = ADC2_DR[7:0] | ADC1_DR[7:0]



使用特权

评论回复
5
caoyunhj2301|  楼主 | 2022-3-31 16:04 | 只看该作者
多ADC转换模式:

1.     注入同步模式

2.     规则同步模式

3.     交替模式

4.     交替触发模式

5.     规则同步+注入同步模式

6.     规则同步+交替触发模式

使用特权

评论回复
6
caoyunhj2301|  楼主 | 2022-3-31 16:05 | 只看该作者
交替模式配置步骤:

1. 配置相关输入通道的IO口。

2. 设置DMA

3. 如果双重ADC或三重采样,设置ADC的公共寄存器

       a.     设置公共寄存器首先要打开任意一个ADC的时钟,否则这部分数字电路是没有开始工作的。

        b.     设置DMA模式

        c.     设置ADC转换完成后,发送DMA请求

        d.     设置多ADC模式

        e.     设置两次采样间隔周期

4. 配置要使用到的ADC(必须ADC1为主,其他为从)。

使用特权

评论回复
7
caoyunhj2301|  楼主 | 2022-3-31 16:06 | 只看该作者
程序:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片

    /************************************  
        标题:ADC  
        软件平台:IAR for ARM6.21  
        硬件平台:stm32f4-discovery  
        主频:168M  
         
        author:小船  
        data:2012-02-16  
    *************************************/  
      
    #include <stm32f4xx.h>   
    #include "MyDebugger.h"  
      
    __IO uint16_t ADCConvertedVault[10000];  
    char TXbuffer[] = "PC1输入电压为:x.xxxV\n\r";  
      
    void ADC_IO_Config(void);  
    void ADC_DMA_Config(void);  
      
    void ADC_Common_Config(void);  
      
    void ADC3_IN11_Config(void);  
    void ADC2_IN11_Config(void);  
    void ADC1_IN11_Config(void);  
      
    void main ()  
    {     
      SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  
      
      ADC_IO_Config();  
      ADC_DMA_Config();  
        
      ADC_Common_Config();  
        
      ADC3_IN11_Config();  
      ADC2_IN11_Config();   
      ADC1_IN11_Config();  
        
      ADC3->CR2 |= (1<<0);   //开启ADC3转换  
      ADC2->CR2 |= (1<<0);   //开启ADC2转换  
      ADC1->CR2 |= (1<<0);   //开启ADC1转换  
         
      ADC1->CR2 |= (1<<30); //触发转换开始   
        
      MyDebugger_Init();  
      
      while(1)  
      {  
      };  
    }  
      
    void ADC_Common_Config(void)  
    {  
      RCC->APB2ENR |= ( (1<<8) | (1<<9) | (1<<10) ); //使能ADC时钟  
      ADC->CCR &= 0x00000000;  
        
      /*  
      DMA模式1  
      最后一次ADC转换后发出dma请求  
      交错模式  
      2次采样之间的延迟5个周期  
      */  
      ADC->CCR |= ( 0x00004000 | (1<<13) | 0x00000017 | 0x00000000);  
         
    }  
      
    /***ADC1设置***/  
    void ADC1_IN11_Config(void)  
    {     
      ADC1->SQR1 = 0x00000000;//转换一个通道  
      ADC1->SQR3 = 0x0000000B;//第一个通道为ADC1_in11  
      ADC1->CR1 &= 0x00000000;   
      ADC1->CR2 &= 0x00000000;   
      ADC1->CR2 |= (1<<1);  //连续转换  
      ADC1->CR2 |= (1<<9); //最后一次ADC转换后发出dma请求  
      
      ADC1->CR2 |= (1<<8);//ADC dma发送模式使能  
    }  
      
    /***ADC2设置***/  
    void ADC2_IN11_Config(void)  
    {     
      ADC2->SQR1 = 0x00000000;//转换一个通道  
      ADC2->SQR3 = 0x0000000B;//第一个通道为ADC1_in11  
      ADC2->CR1 &= 0x00000000;   
      ADC2->CR2 &= 0x00000000;   
      ADC2->CR2 |= (1<<1);  //连续转换  
      ADC2->CR2 |= (1<<9); //最后一次ADC转换后发出dma请求  
    }  
      
    /***ADC3设置***/  
    void ADC3_IN11_Config(void)  
    {     
      ADC3->SQR1 = 0x00000000;//转换一个通道  
      ADC3->SQR3 = 0x0000000B;//第一个通道为ADC3_in11  
      ADC3->CR1 &= 0x00000000;   
      ADC3->CR2 &= 0x00000000;   
      ADC3->CR2 |= (1<<1);  //连续转换  
      ADC3->CR2 |= (1<<9); //最后一次ADC转换后发出dma请求  
    }  
      
    /***GPIO设置***/  
    void ADC_IO_Config(void)  
    {  
      RCC->AHB1ENR |= (1<<2); //打开GPIOC时钟  
      GPIOC->MODER &= 0xfffffff3;//PC1模拟模式  
      GPIOC->MODER |= 0x0000000C;  
      GPIOC->PUPDR &= 0xfffffff3;//无上拉无下拉   
    }  
      
    /***DMA设置***/  
    void ADC_DMA_Config(void)  
    {     
      RCC->AHB1ENR |= (1<<22); //使能DMA2时钟  
      ADC3->CR2 &= ~(1<<8);//ADC3 dma发送模式除能  
      DMA2_Stream0->CR &= 0xFFFFFFFE; //除能DMA2_Stream0  
      while(DMA2_Stream0->CR & 0x00000001);//确保DMA可以被设置   
      DMA2->LIFCR |= 0x0000003D;//传送前清空DMA2_Stream0所有中断标志   
      DMA2_Stream0->PAR = (uint32_t)&ADC->CDR;//设置外设地址  
      DMA2_Stream0->M0AR = (uint32_t)ADCConvertedVault; //设置内存地址  
      DMA2_Stream0->CR |= 0x0002800;//16位数据  
      DMA2_Stream0->NDTR = 10000; //设置dma传输数据的数量  
      /*  
        设置dma2通道0,即ADC1  
        优先级Medium  
        传输方向外设到内存  
        内存递增模式  
        循环模式  
        传输完成中断  
      */  
      DMA2_Stream0->CR |= ( 0x00000000 | 0x00010000 | 0x0 | (1<<10) | (1<<8) | (1<<4) );   
        
      NVIC->IP[56] = 0xB0;  
      NVIC->ISER[1] |= (1<<(56-32));  
        
      DMA2_Stream0->CR |= 1; //DMA2数据流0使能  
    }  
      
    void DMA2_Stream0_IRQHandler (void)  
    {  
      uint32_t i;  
      uint32_t Average;  
      if(DMA2->LISR & 0x00000010)  
      {  
          DMA2->LIFCR |= 0x00000010;  
          for(i = 0; i < 10000; i++)  // 对一万个数据取平均值  
            Average += ADCConvertedVault[i];  
          Average *= 3;  
          Average /= 40960;  
          TXbuffer[14] = ( Average / 1000 ) % 10 + 0x30;//转换成ASCII码  
          TXbuffer[16] = ( Average / 100 ) % 10 + 0x30;  
          TXbuffer[17] = ( Average / 10 ) % 10 + 0x30;  
          TXbuffer[18] = Average % 10 + 0x30;  
          MyDebugger_Message(TXbuffer, sizeof(TXbuffer)/sizeof(char));   
      }  
    }  

使用特权

评论回复
8
caoyunhj2301|  楼主 | 2022-3-31 16:07 | 只看该作者
运行结果:

使用特权

评论回复
9
Jacquetry| | 2022-10-5 21:20 | 只看该作者
看着操作寄存器就很麻烦

使用特权

评论回复
10
Uriah| | 2022-10-8 10:30 | 只看该作者

对于没有else的场景,使用ifPresent即可

使用特权

评论回复
11
Bblythe| | 2022-10-8 13:29 | 只看该作者

需要在做项目的过程中经历磨难

使用特权

评论回复
12
Pulitzer| | 2022-10-8 16:28 | 只看该作者

I2C1工作时钟源选择;I2C1模块工作时钟的开启使能。

使用特权

评论回复
13
sheflynn| | 2023-2-2 12:10 | 只看该作者

stm32中如何通过定时器来设置ADC的采样率?

使用特权

评论回复
14
mnynt121| | 2023-2-4 12:54 | 只看该作者
如何用STM32内置ADC采集音频信号

使用特权

评论回复
15
albertaabbot| | 2023-2-4 18:46 | 只看该作者
如何实现多通道AD采样               

使用特权

评论回复
16
sdlls| | 2023-2-7 21:03 | 只看该作者
如何设置stm32片内adc实现接近1M的采样率

使用特权

评论回复
17
benjaminka| | 2023-2-7 21:22 | 只看该作者
ADC DMA多通道采集到的数据相互有干扰,该怎么破?

使用特权

评论回复
18
cemaj| | 2023-2-8 13:59 | 只看该作者
STM32 中定时器中断回调函数中加入adc采样轮换查询后,中断函数不执行?请问怎么解决?

使用特权

评论回复
19
janewood| | 2023-2-8 14:49 | 只看该作者
stm32f407的adc采样率是多少

使用特权

评论回复
20
loutin| | 2023-2-11 19:26 | 只看该作者
多通道ADC采集,两路数据相同怎么解决  

使用特权

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

本版积分规则

34

主题

285

帖子

1

粉丝