STM32F4 DAC DMA模式,原理代码分享

说明DAC-DMA只能使用外部触发,即决定了DAC必须外部触发,其它软件触发或无触发是不行的,这也是本人亲测 

代码设计:

1.IO口初始化

2.ADC初始化

3.DMA初始化

注意事项说明:

1.DAC触发源选择:

DAC_InitType.DAC_Trigger=DAC_Trigger_T8_TRGO;    

大多触发模式是和定时器相关的,注意这里没有定时器1 

     TIM_SelectOutputTrigger(TIM8,TIM_TRGOSource_OC1Ref);//选择触发源

这一句是选择触发源,选项如下:

 触发源: 复位、使能,更新,输出比较OC

关于_OC1和_OC1Ref区别,实际测试中未发现二者功能不同;而且_OC1就是参考_OC1Ref来输出的,当然还有更复杂的关系,请看数据手册

2.外设地址说明:

这里使用2种方式:

#define DAC1_DR   (DAC_BASE+0x08)//宏定义

或者使用结构体定义的寄存器方式

DMA_InitStre.DMA_PeripheralBaseAddr=(uint32_t)&(DAC->DHR12R1);//外设 DAC1_DR

3.输出缓冲说明

 这是什么意思呢,缓冲降低输出阻抗,这样就可以提供加大的驱动电流,但是实际设计时为了降低STM32功耗,增加系统稳定性,不会让其直接驱动负载,会在外部加入运放,比如恒流源电路中

另外请看数据手册中,如下

一旦开启缓冲,DAC输出不了0V,而是最低0.2V,类似于有输入失调电压的运放,有的设计中是不行的;另外这会影响DAC输出的线性度,一般外部负载电路是高输入阻抗,理论设计和实际输出不是线性的

 所以实际应用中,一般不使用输出缓冲

代码如下:

/******************************************************************************
  * 功能:
  *
******************************************************************************/
void DAC_IO_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//下拉
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化

}
/******************************************************************************
  * 功能:
  *
******************************************************************************/
void DAC_Mode_Init(void)
{
    DAC_InitTypeDef DAC_InitType;
    DMA_InitTypeDef DMA_InitStre;
    
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);//DMA时钟
    /************************* 通道1 ***************************/
    //使用DMA模式-寄存器到外设
    DAC_InitType.DAC_Trigger=DAC_Trigger_T8_TRGO;    //必须使用触发功能 TEN1=0
    DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
    DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
    DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable;    //DAC1输出缓存关闭 BOFF1=1
  DAC_Init(DAC_Channel_1,&DAC_InitType);     //初始化DAC通道1
    DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC通道1
    
    TIM_SelectOutputTrigger(TIM8,TIM_TRGOSource_OC1Ref);//选择触发源
    
    //DMA初始化
    DMA_DeInit(DMA1_Stream5);//复位
    DMA_InitStre.DMA_PeripheralBaseAddr=(uint32_t)&(DAC->DHR12R1);//外设 DAC1_DR
    DMA_InitStre.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
    DMA_InitStre.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//半字
    DMA_InitStre.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址增加失能
    
    DMA_InitStre.DMA_Memory0BaseAddr=(uint32_t)DAC_Data_Table;    //内存地址
    DMA_InitStre.DMA_MemoryInc=DMA_MemoryInc_Enable;//寄存器(变量)地址增加
    DMA_InitStre.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//半字
    DMA_InitStre.DMA_MemoryBurst=DMA_MemoryBurst_Single;
    
    DMA_InitStre.DMA_Channel=DMA_Channel_7;
    DMA_InitStre.DMA_DIR=DMA_DIR_MemoryToPeripheral;//寄存器到外设输出
    DMA_InitStre.DMA_BufferSize=16;//一个输出循环中数据长度
    DMA_InitStre.DMA_Mode=DMA_Mode_Circular;//循环发送
    
    DMA_InitStre.DMA_Priority=DMA_Priority_High;
    DMA_InitStre.DMA_FIFOMode=DMA_FIFOMode_Disable;
    DMA_InitStre.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
    DMA_Init(DMA1_Stream5,&DMA_InitStre);//初始化
    
    DMA_Cmd(DMA1_Stream5,ENABLE);//DMA使能
    DAC_DMACmd(DAC_Channel_1, ENABLE);//DAC-DMA使能 
 

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现stm32f4dacdma正弦波输出,需要以下步骤: 1. 配置DAC通道和DMA通道,使能时钟 在使用DACDMA前,需要先使能相应的时钟。对于DAC来说,需要使能DAC时钟和GPIO时钟。对于DMA来说,需要使能DMA时钟。同时也需要配置好DAC通道和DMA通道。 2. 构建正弦波表并放入内存 正弦波表是用来存储一段正弦波的数据。可以使用公式y=sin(2πx/N)生成正弦波表,其中N是正弦波表大小,x是当前位置,y是对应的采样值。然后将正弦波表数据放入内存中。 3. 配置DMA传输数据 使用DMA将内存中的正弦波表数据传输到DAC数据寄存器中。可以配置DMA的传输模式、方向、缓存等参数。 4. 设置DAC触发模式 设置DAC触发模式DMA触发,并选择DMA通道。 5. 启动DACDMA传输 启动DACDMA传输即可输出正弦波信号。 总体代码示例: ``` c #define SAMPLE_RATE 100 #define TABLE_SIZE 128 uint16_t sinetable[TABLE_SIZE]; void build_sinetable() { for(int i = 0; i < TABLE_SIZE; i++) { float tmp = sinf(2 * PI * i / TABLE_SIZE) * 2047 + 2047; sinetable[i] = (uint16_t)tmp; } } void DAC_DMA_Init() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; DAC_InitTypeDef DAC_InitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; DAC_Init(DAC_Channel_1, &DAC_InitStructure); DAC_Cmd(DAC_Channel_1, ENABLE); DMA_DeInit(DMA1_Stream5); DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_BufferSize = TABLE_SIZE; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)sinetable; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Init(DMA1_Stream5, &DMA_InitStructure); DAC_DMACmd(DAC_Channel_1, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / SAMPLE_RATE / TABLE_SIZE - 1; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); TIM_Cmd(TIM6, ENABLE); DMA_Cmd(DMA1_Stream5, ENABLE); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值