DMA方式3通道AD转换 :
代码如下:
#include <adcc.h>
#include <stm32f4xx_adc.h>
#include <stm32f4xx.h>
void Init_adc(void){
ADC_InitTypeDef ADC_InitStruct;
ADC_CommonInitTypeDef ADC_CommonInitTStruct;
GPIO_InitTypeDef GPIO_InitTStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitTStruct.GPIO_Mode=GPIO_Mode_AN;
GPIO_InitTStruct.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_6;
GPIO_InitTStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&GPIO_InitTStruct); //配置  
A5  
A4  
A6 为 模拟输入
ADC_CommonInitTStruct.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled; //DMA模式禁止
ADC_CommonInitTStruct.ADC_Mode=ADC_Mode_Independent; // ADC独立 模式
ADC_CommonInitTStruct.ADC_Prescaler=ADC_Prescaler_Div4; // //分频系数
ADC_CommonInitTStruct.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个采样阶段的延时周期数
ADC_CommonInit(&ADC_CommonInitTStruct); // 配置 ADC 时钟 模式
ADC_InitStruct.ADC_ContinuousConvMode=ENABLE; //连续转换
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right; //右对齐
ADC_InitStruct.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
ADC_InitStruct.ADC_NbrOfConversion=3; // 2个转换在规则序列中
ADC_InitStruct.ADC_Resolution=ADC_Resolution_12b; // 12位 转换模式
ADC_InitStruct.ADC_ScanConvMode=ENABLE; //扫描模式
ADC_Init(ADC1,&ADC_InitStruct); //配置
// ADC_Cmd(ADC1,ENABLE); // 使能 ADC转换
}
u32 data2[4];
void INit_dma(void){
DMA_InitTypeDef DMA_InitStructure;
Init_adc();
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //开启外设时钟
DMA_InitStructure.DMA_Channel = DMA_Channel_0; //设置DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_BASE+0x4C;; //外设的地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)data2; //数据内存的地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //读取数据的模式是从外设到内存
DMA_InitStructure.DMA_BufferSize = 3; //有 3个转换通道, ADC 采集3次
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_PeripheralDataSize_Word; //数据宽度为 32 位 只有这样才不会错位//如果数据宽度为 16 位将u32data2改成u16
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //循环转换
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable ;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4 ; //内存地址增长的方式
DMA_InitStructure.DMA_PeripheralBurst = 0 ; //外设内存增长的方式
DMA_Init(DMA2_Stream0, &DMA_InitStructure); //配置
DMA_Cmd(DMA2_Stream0, ENABLE); //使能 DMA
// 转换优先级
ADC_RegularChannelConfig(ADC1,4, 1, ADC_SampleTime_144Cycles );
ADC_RegularChannelConfig(ADC1,5, 2, ADC_SampleTime_144Cycles );
ADC_RegularChannelConfig(ADC1,6, 3, ADC_SampleTime_144Cycles );
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); // 源数据变化时开启DMA传输
ADC_DMACmd(ADC1, ENABLE); //使能 ADC1 的 DMA功能
ADC_ContinuousModeCmd(ADC1, ENABLE); // adc连续转换模式
ADC_Cmd(ADC1,ENABLE); // 使能 ADC1
ADC_SoftwareStartConv(ADC1); //开始转换规则通道
}
附加:
搞了一天都只有第一个转换的数据是正确,最后发现是红 {MOD}部分有问题(原本2个数据位一样就会出错),修改就没事了。。。不过发现网上好多人都那样写也没事。我也是无语了。
DMA 方式 DAC(PA4)转换 :
代码如下:
#include <dac.h>
#include <stm32f4xx_dac.h>
u32 data_dac;
void Dac_DMA(void){
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Stream5); //复位
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //开启外设时钟
DMA_InitStructure.DMA_Channel = DMA_Channel_7 ; //设置DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)&(DAC->DHR12R1); //DHR12R1的地址
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&data_dac ; //数据内存的地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //读取数据的模式是从外设到内存
DMA_InitStructure.DMA_BufferSize = 1; //有 1个转换通道, 采集1次
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //内存地址不变
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //数据宽度为 32 位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //数据宽度为 32 位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //循环转换
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable ;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ; //内存地址不加
DMA_InitStructure.DMA_PeripheralBurst = 0 ; //外设内存不加
DMA_Init(DMA1_Stream5, &DMA_InitStructure); //配置
DMA_Cmd(DMA1_Stream5, ENABLE); //使能 DMA
}
void Dac_Init(void){
GPIO_InitTypeDef GPIO_InitTStruct;
DAC_InitTypeDef DAC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitTStruct.GPIO_Mode=GPIO_Mode_AN; // 模拟输入 会映射成到DA
GPIO_InitTStruct.GPIO_Pin=GPIO_Pin_4;
GPIO_InitTStruct.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Init(GPIOA,&GPIO_InitTStruct);
DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;// 不用波形发生器
DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None;
DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable; //使用设置缓冲
DAC_InitStruct.DAC_Trigger=DAC_Trigger_T2_TRGO; // 定时器2 TRGO模式
DAC_Init(DAC_Channel_1,&DAC_InitStruct);
Dac_DMA(); // DMA 配置
DAC_Cmd(DAC_Channel_1,ENABLE); // 使能 DA1 方式
DAC_DMACmd(DAC_Channel_1,ENABLE); // 使能 DA1 DMA方式
}
void INIT_timer2(void)
{
TIM_TimeBaseInitTypeDef TIM_Typetim2;
NVIC_InitTypeDef NVIC_InitTIM2;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_Typetim2.TIM_CounterMode=TIM_CounterMode_Up;
TIM_Typetim2.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_Typetim2.TIM_Prescaler=8400;
TIM_Typetim2.TIM_Period=50;
TIM_TimeBaseInit(TIM2,&TIM_Typetim2);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
NVIC_InitTIM2.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitTIM2.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitTIM2.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitTIM2.NVIC_IRQChannelSubPriority=0x02;
NVIC_Init(&NVIC_InitTIM2);
TIM_Cmd(TIM2,ENABLE);
TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update); //选择更新事件作为触发输出 (TRGO)。
}
附加 : DAC的DMA 方式 好像不能那个用 DAC-CR2里TSEL1[2:0]的软件触发 (我弄了好久都搞不好,原子哥见到请帮忙指点下是不是上图已说明不能用软件触发) ,最后改成 定时器2TRGO
事件,所以要加红 {MOD}那一段。!!! 在主程序给 data_dac赋值就OK了!~
一周热门 更多>