打印

STM32F4,DMA方式3通道AD转换 + DMA 方式 DA转换

[复制链接]
191|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
王将|  楼主 | 2018-7-30 07:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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);                                  //配置 &nbspA5 &nbspA4 &nbspA6 为  模拟输入

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);               //开始转换规则通道
}

       

附加:
搞了一天都只有第一个转换的数据是正确,最后发现是红色部分有问题(原本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)。

使用特权

评论回复

相关帖子

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

本版积分规则

419

主题

419

帖子

0

粉丝