zoukankan      html  css  js  c++  java
  • 【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功能用到的地方还是比较多的,建议熟练使用。

  • 相关阅读:
    欧拉公式求四面体的体积
    欧拉公式求四面体的体积
    I
    I
    闭包传递(floyed)
    闭包传递(floyed)
    Python hypot() 函数
    Python cos() 函数
    Python atan2() 函数
    Python atan() 函数
  • 原文地址:https://www.cnblogs.com/armfly/p/12341267.html
Copyright © 2011-2022 走看看