【STM32H7教程】第59章 STM32H7的DAC基础知识和HAL库API

完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第59章       STM32H7的DAC基础知识和HAL库API

本章节为大家讲解DAC,实际项目用到DAC的地方比较多,而且H7的DAC性能也比较给力。

59.1 初学者重要提示

59.2 DAC基础知识

59.3 DAC的HAL库用法

59.4 源文件stm32h7xx_hal_dac.c

59.5 总结

 

 

59.1 初学者重要提示

  1.   注意STM32H7只有一个DAC,但有两个独立的通道,跟F4的略不同,F4是两个DAC。
  2.   如果仅使用STM32H7的一个通道,即PA4或者PA5引脚,另一个引脚没有做任何配置,这个引脚上会有波形效应。
  3.   STM32H7的DAC支持出厂校准和用户校准模式。特别注意一点,校准是建立在用户使能了输出缓冲的情况下才有效。
  4.   STM32H7的DAC支持正常模式和采样保持模式,其中采样保持模式用于低功耗状态使用。
  5.   DAC的输出除了可以连接PA4或者PA5引脚,也可以连接到片上外设,比如运放,比较器。

59.2 DAC基础知识

对于STM32H7的DAC了解到以下几点即可:

  •   STM32H7的DAC只有一个,但有两个独立的通道,跟F4的略不同,F4是两个DAC
  •   12位分辨率,双通道,支持独立或者同时使用。
  •   两个DAC通道均支持DMA。
  •   每路DAC输出均可与DAC_OUTx输出引脚断开连接,而且DAC 输出可与片上外设连接。
  •   支持偏移校准,参考电压可以使用内部的VREFBUF,也可以使用VREF+引脚外接的电压基准。
  •   支持噪声波和三角波生成。这两种方案不够灵活,所以基本都采用定时器触发+DMA方式生成任意波形。

59.2.1 DAC硬件框图

认识一个外设,最好的方式就是看它的框图,方便我们快速地了解DAC的基本功能,然后再看手册了解细节。框图如下所示:

 

通过这个框图,我们可以得到如下信息:

  •   VDDA

用于ADC、DAC、运放、比较器和电压基准供电,这部分供电是独立的。

  •   VREF+

用于ADC和DAC的基准电压,当使能了STM32H7内部的电压基准,将使用内部基准供VREF+,VREF-。如果没有使能的话,通过外置电压基准提供。

  •   VSSA

所有电源和模拟稳压器的地端。

  •   dac_ch1_dma

DAC通道1的DMA请求。

  •   dac_ch2_dma

DAC通道2的DMA请求。

  •   dac_ch1_trg[0:15]

DAC通道1的输入触发。

  •   dac_ch2_trg[0:15]

DAC通道2的输入触发。

  •   dac_unr_it

DAC输出的下溢中断信号。

  •   dac_pclk

DAC时钟输入

  •   dac_out1

DAC通道1输出。

  •   dac_out2

DAC通道2输出。

  •   lsi_ck

使用LSI时钟源,可以让DAC在停止模式下运行。

59.2.2 DAC数据格式和输出电压

DAC的数据寄存器设计比较灵活,每个通道都有一组单独的寄存器(下面是通道1的寄存器):

  •   8位右对齐数据保持寄存器DACx_DHR8R1。
  •   12位右对齐数据保持寄存器DACx_DHR12R1。
  •   12位左对齐数据保持寄存器DACx_DHR12L1。

 

除了这种单独寄存器,为了降低带宽,也支持两个通道公用一个寄存器。

  •   8 位右对齐数据保持寄存器DACx_DHR8RD。
  •   12 位左对齐数据保持寄存器DACx_DHR12LD。
  •   12 位右对齐数据保持寄存器DACx_DHR12RD。

通道1和通道2共用的效果如下:

 

由于DAC是12bit的DAC,那么范围就是0-4095,对应的输出电压如下:

DAC Output = Vref *(DOR / 4095),其中Vref是参考电压,DOR是数据输出寄存器。

比如需要DAC输出0.7V,那么假设VREF+ = 3.3V,  DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V。

59.2.3 DAC支持的触发源

DAC支持软件触发和硬件触发,具体支持的触发源如下:

#define DAC_TRIGGER_NONE        ((uint32_t)0x00000000)       
#define DAC_TRIGGER_SOFTWARE    ((uint32_t)(DAC_CR_TEN1))     
#define DAC_TRIGGER_T1_TRGO     ((uint32_t)(DAC_CR_TSEL1_0 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_T2_TRGO     ((uint32_t)(DAC_CR_TSEL1_1 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_T4_TRGO     ((uint32_t)(DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)
#define DAC_TRIGGER_T5_TRGO     ((uint32_t)(DAC_CR_TSEL1_2 |DAC_CR_TEN1))  
#define DAC_TRIGGER_T6_TRGO     ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_T7_TRGO     ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_T8_TRGO     ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_T15_TRGO    ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TEN1))
#define DAC_TRIGGER_HR1_TRGO1   ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TSEL1_0 | DAC_CR_TEN1))
#define DAC_TRIGGER_HR1_TRGO2   ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TSEL1_1 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_LP1_OUT     ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_LP2_OUT     ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TSEL1_2 | DAC_CR_TEN1)) 
#define DAC_TRIGGER_EXT_IT9     ((uint32_t)(DAC_CR_TSEL1_3 | DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0 | DAC_CR_TEN1))

 

59.2.4 DAC正常模式和采样保持模式

关于正常模式和采样保持模式,注意以下几点:

  •   正常模式是平时最常用的方式,比较好理解。而采样保持模式用于低功耗方式。
  •   在采样保持模式下,DAC内核转换数据,然后保持电容上的电压。不转换时,DAC内核和样本之间的缓冲器完全关闭,DAC输出为三态,因此降低了整体功耗,但每次新转换前都需要一段稳定期。
  •   采样保持模式可修改内部或者外部参考电压。
  •   采样保持部分可以用LSI时钟,也可以运行在几种低功耗模式下,如RUN模式, SLEEP& STOP模式。

59.2.5 DAC的出厂校准和用户校准

一般情况下,使用出厂校准即可,芯片上电后自动完成出厂校准。而用户校准略麻烦,暂不做研究。这里特别注意一点,校准是建立在用户使能了输出缓冲的情况下才有效。

59.3 DAC的HAL库用法

DAC的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断和DMA。下面我们逐一展开为大家做个说明。

59.3.1 DAC寄存器结构体DAC_TypeDef

DAC相关的寄存器是通过HAL库中的结构体DAC_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:

typedef struct
{
  __IO uint32_t CR;       
  __IO uint32_t SWTRIGR;  
  __IO uint32_t DHR12R1;
  __IO uint32_t DHR12L1;  
  __IO uint32_t DHR8R1;   
  __IO uint32_t DHR12R2;  
  __IO uint32_t DHR12L2;  
  __IO uint32_t DHR8R2;   
  __IO uint32_t DHR12RD;  
  __IO uint32_t DHR12LD;  
  __IO uint32_t DHR8RD;  
  __IO uint32_t DOR1;     
  __IO uint32_t DOR2;    
  __IO uint32_t SR;       
  __IO uint32_t CCR;      
  __IO uint32_t MCR;      
  __IO uint32_t SHSR1;   
  __IO uint32_t SHSR2;   
  __IO uint32_t SHHR;     
  __IO uint32_t SHRR;     
} DAC_TypeDef;

 

__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:

#define     __O     volatile             /*!< Defines 'write only' permissions */
#define     __IO    volatile             /*!< Defines 'read / write' permissions */

 

下面我们再看DAC的定义,在stm32h743xx.h文件。

#define PERIPH_BASE         ((uint32_t)0x40000000) 
#define D2_APB1PERIPH_BASE  PERIPH_BASE
#define DAC1_BASE           (D2_APB1PERIPH_BASE + 0x7400)
#define DAC1                ((DAC_TypeDef *) DAC1_BASE) <----- 展开这个宏,(DAC_TypeDef *) 0x40007400

 

我们访问DAC1的CR寄存器可以采用这种形式:DAC1->CR = 0。

59.3.2 DAC的采样保持DAC_SampleAndHoldConfTypeDef

此结构体用于DAC的采样保持参数,具体定义如下:

typedef struct
{
  uint32_t DAC_SampleTime ;          
  uint32_t DAC_HoldTime ;            
  uint32_t DAC_RefreshTime ;        }
DAC_SampleAndHoldConfTypeDef;

 

下面将这几个参数逐一为大家做个说明:

  •   uint32_t DAC_SampleTime

此参数用于设置DAC的采样时间,范围0 - 1023。

  •   uint32_t DAC_HoldTime

此参数用于设置DAC的保持时间,范围0 – 1023。

  •   uint32_t DAC_RefreshTime

此参数用于设置DAC的刷新时间,范围0 – 255。

59.3.3 DAC的通道参数结构体DAC_ChannelConfTypeDef

此结构体用于DAC的通道参数配置,具体定义如下:

typedef struct
{
  uint32_t DAC_SampleAndHold;          
  uint32_t DAC_Trigger;                  
  uint32_t DAC_OutputBuffer;            
  uint32_t DAC_ConnectOnChipPeripheral ;
  uint32_t DAC_UserTrimming;            
  uint32_t DAC_TrimmingValue;          
  DAC_SampleAndHoldConfTypeDef  DAC_SampleAndHoldConfig;      
}DAC_ChannelConfTypeDef;

 

下面将这几个参数逐一为大家做个说明:

  •   uint32_t DAC_SampleAndHold

此参数用于使能采样保持模式,具体支持的参数如下:

#define DAC_SAMPLEANDHOLD_DISABLE     ((uint32_t)0x00000000)
#define DAC_SAMPLEANDHOLD_ENABLE      ((uint32_t)DAC_MCR_MODE1_2)

 

  •   uint32_t DAC_Trigger

此参数用于DAC触发源的选择,具体支持的参数如下:

#define DAC_TRIGGER_NONE                                        
#define DAC_TRIGGER_SOFTWARE               
#define DAC_TRIGGER_T1_TRGO              
#define DAC_TRIGGER_T2_TRGO             
#define DAC_TRIGGER_T5_TRGO                
#define DAC_TRIGGER_T6_TRGO               
#define DAC_TRIGGER_T7_TRGO            
#define DAC_TRIGGER_T8_TRGO              
#define DAC_TRIGGER_T15_TRGO              
#define DAC_TRIGGER_HR1_TRGO1            
#define DAC_TRIGGER_HR1_TRGO2         
#define DAC_TRIGGER_LP1_OUT              
#define DAC_TRIGGER_LP2_OUT               
#define DAC_TRIGGER_EXT_IT9 

 

  •   uint32_t DAC_OutputBuffer

此参数用于使能或者关闭DAC的输出缓冲,使能输出缓冲后,可以增加DAC的驱动能力,具体支持的参数如下:

#define DAC_OUTPUTBUFFER_ENABLE            ((uint32_t)0x00000000)
#define DAC_OUTPUTBUFFER_DISABLE           ((uint32_t)DAC_MCR_MODE1_1)

 

  •   uint32_t DAC_ConnectOnChipPeripheral

此参数用于DAC是否连接片上外设(运放,比较器等),具体支持的参数如下:

#define DAC_CHIPCONNECT_DISABLE      ((uint32_t)0x00000000)
#define DAC_CHIPCONNECT_ENABLE       ((uint32_t)DAC_MCR_MODE1_0)

 

  •   uint32_t DAC_UserTrimming

此参数用于设置DAC的校准方式,采用出厂模式还是用户模式,具体支持的参数如下:

#define DAC_TRIMMING_FACTORY        ((uint32_t)0x00000000)          
#define DAC_TRIMMING_USER           ((uint32_t)0x00000001)   

 

  •   uint32_t DAC_TrimmingValue

此参数用于设置用户校准模式的偏移值,参数范围1-31。       

  •   DAC_SampleAndHoldConfTypeDef  DAC_SampleAndHoldConfig

此参数用于采样保持具体参数设置,详解本章3.2小节的说明。

59.3.4 DAC结构体句柄DAC_HandleTypeDef

HAL库在DAC_TypeDef的基础上封装了一个结构体DAC_HandleTypeDef,定义如下:

typedef struct
{
  DAC_TypeDef                 *Instance;     
  __IO HAL_DAC_StateTypeDef   State;        
  HAL_LockTypeDef             Lock;         
  DMA_HandleTypeDef           *DMA_Handle1;  
  DMA_HandleTypeDef           *DMA_Handle2; 
  __IO uint32_t               ErrorCode;     
}DAC_HandleTypeDef;

 

下面将这几个参数逐一做个说明。

  •   DAC_TypeDef   *Instance

这个参数是寄存器的例化,方便操作寄存器,详见本章3.1小节。

  •   DMA_HandleTypeDef    *DMA_Handle1
  •   DMA_HandleTypeDef    *DMA_Handle2

DMA句柄结构体指针变量,用于关联DAC句柄,方便调用。    

  •   HAL_LockTypeDef          Lock           
  •   __IO  HAL_DAC_STATETypeDef  State           
  •   __IO  uint32_t           ErrorCode      

这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。

59.3.5 DAC初始化流程总结

使用方法由HAL库提供:

  第1步:基本的初始化。

  •   函数HAL_DAC_Init初始化。
  •   配置DAC_OUT1: PA4, DAC_OUT2: PA5引脚为模拟模式。
  •   函数HAL_DAC_ConfigChannel配置通道参数。
  •   函数HAL_DAC_Start() or HAL_DAC_Start_DMA()使能DAC。

 

  第2步:DAC校准。

  • 出厂校准比较简单,芯片上电后自动完成,而用户校准需要依次调用函数HAL_DACEx_GetTrimOffset,HAL_DACEx_SelfCalibrate和HAL_DACEx_SetUserTrimming。

 

  第3步:查询模式。

  •   函数HAL_DAC_Start() 启动。
  •   函数HAL_DAC_GetValue()可以读取输出值。
  •   函数HAL_DAC_Stop可以停止DAC。

 

  第4步:DMA方式。

  •  函数HAL_DAC_Start_DMA()启动DMA方式转换。
  •  DAC的数据传输一半的时候, HAL_DAC_ConvHalfCpltCallbackCh1() 或者 HAL_DACEx_ConvHalfCpltCallbackCh2() 会被调用。
  •  DAC的数据传输完成的时候,HAL_DAC_ConvCpltCallbackCh1() 或者 HAL_DACEx_ConvHalfCpltCallbackCh2() 会被调用。
  •  传输错误时,函数HAL_DAC_ErrorCallbackCh1会被调用。
  •  DMA下溢错误,会调用函数HAL_DAC_DMAUnderrunCallbackCh1()或者HAL_DACEx_DMAUnderrunCallbackCh2()。
  •  停止DAC的DMA方式,可以调用函数HAL_DAC_Stop_DMA

59.4 源文件stm32h7xx_hal_dac.c

这里把我们把如下几个常用到的函数做个说明:

  •   HAL_DAC_Init
  •   HAL_DAC_ConfigChannel
  •   HAL_DAC_Start_DMA

59.4.1 函数HAL_DAC_Init

函数原型:

HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef* hdac)
{ 
  /* 检测DAC句柄 */
  if(hdac == NULL)
  {
     return HAL_ERROR;
  }
  assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
  
  if(hdac->State == HAL_DAC_STATE_RESET)
  {  
    hdac->Lock = HAL_UNLOCKED;
     /* 初始化GPIO,NVIC等 */
    HAL_DAC_MspInit(hdac);
  }
  
  /* 设置DAC状态忙 */
  hdac->State = HAL_DAC_STATE_BUSY;
  
  /* 设置DAC无错误 */
  hdac->ErrorCode = HAL_DAC_ERROR_NONE;
  
  /* 设置DAC就绪 */
  hdac->State = HAL_DAC_STATE_READY;
  
  /* 返回HAL_OK */
  return HAL_OK;
}

 

函数描述:

此函数用于初始化DAC。

函数参数:

  •   第1个参数是DAC_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.4小节。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

注意事项:

  1. 函数HAL_DAC_MspInit用于初始化DAC的底层时钟、NVIC等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
  2. 如果形参hdac的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量DAC_HandleTypeDef DacHandle。

对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_DAC_STATE_RESET  = 0x00U。

解决办法有三

方法1:用户自己初始DAC底层。

方法2:定义DAC_HandleTypeDef DacHandle为全局变量。

方法3:下面的方法

if(HAL_DAC_DeInit(&DacHandle) != HAL_OK)
{
    Error_Handler();
}  
if(HAL_DAC_Init(&DacHandle) != HAL_OK)
{
    Error_Handler();
}

 

使用举例:

DAC_HandleTypeDef   DAC_Handle;
DacHandle.Instance = DAC1;
if (HAL_DAC_Init(&DacHandle) != HAL_OK)
{
    Error_Handler(__FILE__, __LINE__);
}

 

59.4.2 函数HAL_DAC_ConfigChannel

函数原型:

HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel)
{
  uint32_t tmpreg1 = 0, tmpreg2 = 0;
  uint32_t tickstart = 0;
  
  /* 部分省略,未贴出 */
 
  /* 上锁 */
  __HAL_LOCK(hdac);
  
  /* 设置DAC忙 */
  hdac->State = HAL_DAC_STATE_BUSY;
  
  if(sConfig->DAC_SampleAndHold == DAC_SAMPLEANDHOLD_ENABLE)
  {
    /* 通道1设置 */
    if (Channel == DAC_CHANNEL_1)
    {
     

    }
    else /* 通道2设置 */
    {
    }
  }
    
  if(sConfig->DAC_UserTrimming == DAC_TRIMMING_USER)
  /* 用户校准配置 */
  {


  }
  /* 出厂模式无需配置,复位后自动设置 */
  
  /* 获取DAC MCR数值 */
  tmpreg1 = hdac->Instance->MCR;
  /* 清除DAC_MCR_MODE2_0, DAC_MCR_MODE2_1 和  DAC_MCR_MODE2_2 位 */
  tmpreg1 &= ~(((uint32_t)(DAC_MCR_MODE1)) << Channel); 
  /* 配置DAC通道 */
  tmpreg2 = (sConfig->DAC_SampleAndHold | sConfig->DAC_OutputBuffer | sConfig->DAC_ConnectOnChipPeripheral);
  tmpreg1 |= tmpreg2 << Channel;
  /* 设置MCR数值 */
  hdac->Instance->MCR = tmpreg1;
  
  /* DAC工作在正常模式 */
  CLEAR_BIT (hdac->Instance->CR, DAC_CR_CEN1 << Channel);
  
  /* 获取DAC CR值 */
  tmpreg1 = hdac->Instance->CR;
  tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1)) << Channel); 
  tmpreg2 = (sConfig->DAC_Trigger);
  tmpreg1 |= tmpreg2 << Channel;

  /* 写DAC CR值 */
  hdac->Instance->CR = tmpreg1;
      
  /* 禁止波形生成 */
  hdac->Instance->CR &= ~(DAC_CR_WAVE1 << Channel);
  
  /* 设置DAC就绪 */
  hdac->State = HAL_DAC_STATE_READY;
  
  /* 解锁 */
  __HAL_UNLOCK(hdac);
  
  /* 返回HAL_OK */
  return HAL_OK;
}

 

函数描述:

此函数主要用于配置DAC的通道参数。

函数参数:

  •   第1个参数是DAC_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数是DAC_ChannelConfTypeDef类型结构体指针变量,用于DAC的通道参数配置,结构体变量成员的详细介绍看本章3.3小
  •   第3个参数用于选择要配置那个通道,DAC_CHANNEL_1表示配置通道1,DAC_CHANNEL_2表示配置通道2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

static DAC_ChannelConfTypeDef sConfig;
static DAC_HandleTypeDef      DacHandle;

sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;        /* 关闭采样保持模式,这个模式主要用于低功耗 */
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;                    /* 采用定时器6触发 */
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;           /* 使能输出缓冲 */
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;/* 不将DAC连接到片上外设 */
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;              /* 使用出厂校准 */

if (HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
    Error_Handler(__FILE__, __LINE__);
}

 

59.4.3 函数HAL_DAC_Start_DMA

函数原型:

HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment)
{
  uint32_t tmpreg = 0;
   
  /* 部分省略,未贴出 */

  /* 检测参数 Check the parameters */
  assert_param(IS_DAC_CHANNEL(Channel));
  assert_param(IS_DAC_ALIGN(Alignment));
  
  /* 上锁 Process locked */
  __HAL_LOCK(hdac);
  
  /* 设置DAC忙 Change DAC state */
  hdac->State = HAL_DAC_STATE_BUSY;
  
  /* 配置通道1 */
  if(Channel == DAC_CHANNEL_1)
  {
    /* DMA传输完成回调 */
    hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
    
    /* DMA半传输完成回调 */
    hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
       
    /* DMA传输错误回调 */
    hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
    
    /* 使能DAC DMA */
    SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
    
    /* 数据对齐方式设置 */
    switch(Alignment)
    {
      case DAC_ALIGN_12B_R:
        tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
        break;
      case DAC_ALIGN_12B_L:
        tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
        break;
      case DAC_ALIGN_8B_R:
        tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
        break;
      default:
        break;
    }
  }
  else
  {
   
    }
  }
  
  /* 使能DMA Stream  */
  if(Channel == DAC_CHANNEL_1)
  {
    /* 使能DAC DMA下溢中断 */
    __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
    
    /* 启动传输 */
    HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
  } 
  else
  {
    __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
    HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
  }

  /* 解锁 */
  __HAL_UNLOCK(hdac);
  /* 使能DAC通道 */
  __HAL_DAC_ENABLE(hdac, Channel);
  
  /* 返回HAL_OK */
  return HAL_OK;
}

 

函数描述:

此函数用于启动DAC的DMA方式

函数参数:

  •   第1个参数是DAC_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数用于选择要配置那个通道,DAC_CHANNEL_1表示配置通道1,DAC_CHANNEL_2表示配置通道2。
  •   第3个参数是波形数据地址。
  •   第4个参数是传输的数据长度。
  •   第5个参数是数据对齐方式设置。
    •   DAC_ALIGN_8B_R 表示8bit右对齐。
    •   DAC_ALIGN_12B_L 表示12bit左对齐。
    •   DAC_ALIGN_12B_R 表示12bit右对齐。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

static DAC_HandleTypeDef      DacHandle;

/* 启动DAC DMA */    
if (HAL_DAC_Start_DMA(&DacHandle, DAC_CHANNEL_2, (uint32_t *)g_usWaveBuff, 64, DAC_ALIGN_12B_R) != HAL_OK)
{
    Error_Handler(__FILE__, __LINE__);
}

 

59.5 总结

本章节就为大家讲解这么多,DAC功能用到的地方还是比较多的,建议熟练使用。

 

posted @ 2020-02-21 14:28  硬汉嵌入式  阅读(3328)  评论(0编辑  收藏  举报