本帖最后由 奋斗哥 于 2013-7-26 13:55 编辑
DAC
Stm32f4内嵌的DAC是12位数字输入,电压输出的数模转换器。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+以获得更精确的转换结果。 主要特点: 2个DAC转换器:每个转换器对应1个输出通道 8位或者12位单调输出 12位模式下数据左对齐或者右对齐 同步更新功能 噪声波形生成 三角波形生成 双DAC通道同时或者分别转换 每个通道都有DMA功能 外部触发转换 输入参考电压VREF+
设置步骤: 1. 设置相关GPIO(PA4、5)。 2. 若时钟源为TIMx更新事件,则设置TIMx。 3. 使能DAC时钟 4. 设置触发源,开启相关触发通道,如果用DMA,是否允许数据错误中断。 5. 如果用DMA。配置相关DMA数据流。 程序: - /************************************
- 标题:DAC
- 软件平台:IAR for ARM6.21
- 硬件平台:stm32f4-discovery
- 主频:168M
-
- author:小船
- data:2012-02-12
- *************************************/
- #include <stm32f4xx.h>
- #include "MyDebugger.h"
- #include "sintable.h"
- void main ()
- {
- SCB->AIRCR = 0x05FA0000 | 0x400; //中断优先级分组 抢占:响应=3:1
-
- /***GPIO设置***/
- RCC->AHB1ENR |= (1<<0); //打开GPIOA时钟
- GPIOA->MODER |= 0x00000F00;//PA4、5模拟模式
- GPIOA->PUPDR &= 0xfffff0ff;//无上拉无下拉
-
- /***定时器设置***/
- RCC->APB1ENR |= (1<<4);//打开TIM6时钟
- TIM6->PSC = 0;
- TIM6->ARR = 83; //使得更新事件频率为1m
- TIM6->CR2 |= 0x00000020;//更新事件输出
- TIM6->CR1 |= 1; //开始计时
-
- /***DAC设置***/
- RCC->APB1ENR |= (1<<29); //使能DAC时钟
- DAC->CR &= 0xffff0000;
- /*
- 使能DMA堵塞中断
- 使能通道1触发
- */
- DAC->CR |= ( (1<<13) | (1<<2) );
- NVIC->IP[54] = 0xA0;
- NVIC->ISER[1] |= (1<<(54-32));
-
- /***DMA设置***/
- RCC->AHB1ENR |= (1<<21); //使能DMA1时钟
- DAC->CR &= ~(1<<12);//DAC dma发送模式除能
- DMA1_Stream5->CR &= 0xFFFFFFFE; //除能DMA1_Stream5
- while(DMA1_Stream5->CR & 0x00000001);//确保DMA可以被设置
- DMA1->HIFCR |= 0x000004f0;//传送前清空DMA1_Stream5所有中断标志
- DMA1_Stream5->PAR = (uint32_t)&DAC->DHR12R1;//设置外设地址
- DMA1_Stream5->M0AR = (uint32_t)SinTable; //设置内存地址
- DMA1_Stream5->CR |= 0x0002800;//16位数据
- DMA1_Stream5->NDTR = 1024; //设置dma传输数据的数量
- /*
- 设置dma通道7,即DAC1
- 优先级Medium
- 传输方向内存到外设
- 内存递增模式
- 循环模式
- */
- DMA1_Stream5->CR |= ( 0x0e000000 | 0x00010000 | (1<<6)
- | (1<<10) | (1<<8) );
-
- DMA1_Stream5->CR |= 1; //DMA数据流5使能
-
- DAC->CR |= (1<<0); //DAC通道1使能
- DAC->CR |= (1<<12);//DAC dma发送模式使能
-
- MyDebugger_Init();
- while(1)
- {
- };
- }
- void TIM6_DAC_IRQHandler(void)
- {
- if( DAC->SR & (1<<13) )
- {
- MyDebugger_LEDs(red, on);
- DAC->SR &= ~(1<<13);
- }
- }
复制代码ADC 12位ADC是一种逐次逼近型模拟数字转换器。它有多达19个通道,可测量16个外部和2个内部信号源和Vbat通道。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。 有16个多路通道。 通道选择: 可以把转换组织成两组:规则组和注入组。在任意多个通道上以任意顺序进行的一系列转换构成成组转换。例如,可以如下顺序完成转换:通道3、通道8、通道2、通道2、通道0、通道2、通道2、通道15。 规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。 注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中。如果ADC_SQRx或ADC_JSQR寄存器在转换期间被更改,当前的转换被清除,一个新的启动脉冲将发送到ADC以转换新选择的组。 单次转换模式: 单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位(只适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。 一旦选择通道的转换完成: 如果一个规则通道被转换: ─ 转换数据被储存在16位ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。 然后ADC停止 连续转换模式: 在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。 每个转换后: 如果一个规则通道被转换: ─ 转换数据被储存在16位的ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。 注入通道不能被用于连续转换模式,唯一的例外是当规则通道配置为连续转换后,注入通道配置为自动转换。 扫描模式: 此模式用来扫描一组模拟通道。 扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。 如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM中。而注入通道转换的数据总是存储在ADC_JDRx寄存器中。
在以下情况中,ADC_SR寄存器的EOC位将被设置:
在每个规则组序列结束后,如果EOCS位被清0
在每个规则通道转换结束,如果EOCS位设置为1
注入通道转换结束数据总是存放在ADC_JDRx寄存器中 注入通道管理: 触发注入 清除ADC_CR1寄存器的JAUTO位,并且设置SCAN位,即可使用触发注入功能。 1. 利用外部触发或通过设置ADC_CR2寄存器的ADON位,启动一组规则通道的转换。 2. 如果在规则通道转换期间产生一外部注入触发或者JSWSTART位被设置,当前转换被复位,注入通道序列被以单次扫描方式进行转换。 3. 然后,恢复上次被中断的规则组通道转换。如果在注入转换期间产生一规则事件,注入转换不会被中断,但是规则序列将在注入序列结束后被执行。 注:当使用触发的注入转换时,必须保证触发事件的间隔长于注入序列。例如:序列长度为30个ADC时钟周期(即2个具有3个时钟间隔采样时间的转换),触发之间最小的间隔必须是31个ADC时钟周期。 自动注入 如果设置了JAUTO位,在规则组通道之后,注入组通道被自动转换。这可以用来转换在ADC_SQRx和ADC_JSQR寄存器中设置的多至20个转换序列。 在此模式里,必须禁止注入通道的外部触发。 如果除JAUTO位外还设置了CONT位,规则通道至注入通道的转换序列被连续执行。
间断模式: 规则组 此模式通过设置ADC_CR1寄存器上的DISCEN位激活。它可以用来执行一个短序列的n次转换(n<=8),此转换是ADC_SQRx寄存器所选择的转换序列的一部分。数值n由ADC_CR1寄存器的DISCNUM[2:0]位给出。 一个外部触发信号可以启动ADC_SQRx寄存器中描述的下一轮n次转换,直到此序列所有的转换完成为止。总的序列长度由ADC_SQR1寄存器的L[3:0]定义。 例如: n=3,被转换的通道 = 0、1、2、3、6、7、9、10 第一次触发:转换的序列为 0、1、2 第二次触发:转换的序列为 3、6、7 第三次触发:转换的序列为 9、10,并产生EOC事件 第四次触发:转换的序列 0、1、2 注: 当以间断模式转换一个规则组时,转换序列结束后不自动从头开始。 当所有子组被转换完成,下一次触发启动第一个子组的转换。在上面的例子中,第四次触发重新转换第一子组的通道0、1和2
注入组 此模式通过设置ADC_CR1寄存器的JDISCEN位激活。在一个外部触发事件后,该模式按通道顺序逐个转换ADC_JSQR寄存器中选择的序列。 一个外部触发信号可以启动ADC_JSQR寄存器选择的下一个通道序列的转换,直到序列中所有的转换完成为止。总的序列长度由ADC_JSQR寄存器的JL[1:0]位定义。 例如: n=1,被转换的通道 = 1、2、3 第一次触发:通道1被转换 第二次触发:通道2被转换 第三次触发:通道3被转换,并且产生EOC和JEOC事件 第四次触发:通道1被转换
设置步骤: 1. 配置相关输入通道的IO口。 2. 设置DMA 3. 如果双重ADC或三重采样,设置ADC的公共寄存器 4. 配置要使用到的ADC
程序:- /************************************
- 标题:一个ADC连续采样
- 软件平台:IAR for ARM6.21
- 硬件平台:stm32f4-discovery
- 主频:168M
-
- author:小船
- data:2012-02-14
- *************************************/
- #include <stm32f4xx.h>
- #include "MyDebugger.h"
- __IO uint16_t ADC3ConvertedVault[10000];
- char TXbuffer[] = "PC1输入电压为:x.xxxV\n\r";
- void ADC3_IN11_Config(void);
- void main ()
- {
- SCB->AIRCR = 0x05FA0000 | 0x400; //中断优先级分组 抢占:响应=3:1
-
- ADC3_IN11_Config();
-
- MyDebugger_Init();
- while(1)
- {
- };
- }
- void ADC3_IN11_Config(void)
- {
- /***GPIO设置***/
- RCC->AHB1ENR |= (1<<2); //打开GPIOC时钟
- GPIOC->MODER &= 0xfffffff3;//PC1模拟模式
- GPIOC->MODER |= 0x0000000C;
- GPIOC->PUPDR &= 0xfffffff3;//无上拉无下拉
-
- /***DMA设置***/
- 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;//传送前清空DMA1_Stream5所有中断标志
- DMA2_Stream0->PAR = (uint32_t)&ADC3->DR;//设置外设地址
- DMA2_Stream0->M0AR = (uint32_t)ADC3ConvertedVault; //设置内存地址
- DMA2_Stream0->CR |= 0x0002800;//16位数据
- DMA2_Stream0->NDTR = 10000; //设置dma传输数据的数量
- /*
- 设置dma2通道2,即ADC3
- 优先级Medium
- 传输方向外设到内存
- 内存递增模式
- 循环模式
- 传输完成中断
- */
- DMA2_Stream0->CR |= ( 0x04000000 | 0x00010000 | 0x0
- | (1<<10) | (1<<8) | (1<<4) );
-
- NVIC->IP[56] = 0xB0;
- NVIC->ISER[1] |= (1<<(56-32));
-
- DMA2_Stream0->CR |= 1; //DMA2数据流0使能
-
- /***ADC3设置***/
- RCC->APB2ENR |= (1<<10); //使能ADC3时钟
- ADC3->SQR1 = 0x00000000;//转换一个通道
- ADC3->SQR3 = 0x0000000B;//第一个通道为ADC3_in11
- ADC3->CR1 &= 0x00000000;
- ADC3->CR2 &= 0x00000000;
- ADC3->CR2 |= (1<<1); //连续转换
- ADC3->CR2 |= (1<<9); //最后一次ADC转换后发出dma请求
- ADC3->CR2 |= (1<<0); //开启AD转换
-
- ADC3->CR2 |= (1<<8);//ADC dma发送模式使能
-
- ADC3->CR2 |= (1<<30); //规则通道转换开始
- }
- 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 += ADC3ConvertedVault[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));
- }
- }
复制代码 运行结果:
三ADC交替采样 在多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为主,其他为从)。 程序: 运行结果:
|