【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的基本功能,然后再看手册了解细节。框图如下所示:

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

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

  • 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共用的效果如下:

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

由于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 = , tmpreg2 = ;
uint32_t tickstart = ; /* 部分省略,未贴出 */ /* 上锁 */
__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 = ; /* 部分省略,未贴出 */ /* 检测参数 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, , DAC_ALIGN_12B_R) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}

59.5 总结

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

上一篇:实现文字自动横移--- jquery尺寸相关函数


下一篇:ASP.NET WebAPi之断点续传下载(下)