在多ADC模式中,ADC1为主,ADC2或ADC3为从,交替或者同时触发,工作模式取决于ADC_CCR寄存器的MULTI[4:0]。
多ADC模式中,转换后的数据可以多模式的数据寄存器(ADC_CDR)中读取。状态可以在多模式的状态寄存器(ADC_CSR)读取。
多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]
方式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]
方式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]
多ADC转换模式:
1. 注入同步模式
2. 规则同步模式
3. 交替模式
4. 交替触发模式
5. 规则同步+注入同步模式
6. 规则同步+交替触发模式
交替模式配置步骤:
1. 配置相关输入通道的IO口。
2. 设置DMA
3. 如果双重ADC或三重采样,设置ADC的公共寄存器
a. 设置公共寄存器首先要打开任意一个ADC的时钟,否则这部分数字电路是没有开始工作的。
b. 设置DMA模式
c. 设置ADC转换完成后,发送DMA请求
d. 设置多ADC模式
e. 设置两次采样间隔周期
4. 配置要使用到的ADC(必须ADC1为主,其他为从)。
程序:
[plain] view plain copy
- /************************************
- 标题: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;
- 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));
- }
- }
运行结果:
|