OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8318|回复: 7

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

[复制链接]

3

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-10-6
在线时间
0 小时
发表于 2015-12-5 22:10:58 | 显示全部楼层 |阅读模式

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


附加:
搞了一天都只有第一个转换的数据是正确,最后发现是红色部分有问题(原本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
事件,所以要加红色那一段。!!!          在主程序给 data_dac赋值就OK了!~

。。。LIKE MCU!~
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-10-6
在线时间
0 小时
 楼主| 发表于 2015-12-5 23:20:44 | 显示全部楼层
在WHILE(1)里加这些就可以显示了。  
              sprintf((char *)buf,"PA4:%.3lf",((float)data2[0]*(float)3.3/4095));
LCD_ShowString(70,0,400,400,24,buf);

sprintf((char *)buf,"PA5:%.3lf",((float)data2[1]*(float)3.3/4095));
LCD_ShowString(70,32,400,400,24,buf);

sprintf((char *)buf,"PA6:%.3lf",((float)data2[2]*(float)3.3/4095));
LCD_ShowString(70,72,400,400,24,buf);
。。。LIKE MCU!~
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2015-12-5 23:38:39 | 显示全部楼层
谢谢分享....
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-10-6
在线时间
0 小时
 楼主| 发表于 2015-12-6 02:08:39 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
我也是刚学啦,砸了1000多元买那套STM32F4 ,得多花时间学习。。。
。。。LIKE MCU!~
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-12-6 12:01:14 | 显示全部楼层
谢谢分享~~~~~
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-10-6
在线时间
0 小时
 楼主| 发表于 2015-12-6 17:19:12 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
原子哥 ,DAC的DMA 是不是 一定要用 外部触发?就像我上面写得那样?
。。。LIKE MCU!~
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2015-12-6 22:59:18 | 显示全部楼层
回复【6楼】LLL杰:
---------------------------------
不然用什么触发?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-10-6
在线时间
0 小时
 楼主| 发表于 2015-12-7 14:24:50 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
我以为可以软件触发,然后自己不断的传送数据
。。。LIKE MCU!~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-25 18:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表