用户工具

站点工具


dac实验_输出直流电压
银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-07-11 gingko 初次建立

实验三十六:DAC实验——输出直流电压

一、实验目的与意义

  1. 了解STM32的DAC结构。
  2. 了解STM32的DAC特征。
  3. 掌握DAC的使用方法。
  4. 掌握STM32 HAL库中DAC属性的配置方法。
  5. 掌握KEIL MDK 集成开发环境使用方法。

二、实验设备及平台

  1. iCore4 双核心板。
  2. JLINK(或相同功能)仿真器。
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、实验原理

1、DAC简介

  • STM32F767的DAC模块(数字/模拟转换模块)是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压Vref+(通ADC共用)以获得更精确的转换结果。
  • STM32F767的DAC模块主要特点有:
    • ① 2个DAC转换器:每个转换器对应1个输出通道
    • ② 8位或者12位单调输出
    • ③ 12位模式下数据左对齐或者右对齐
    • ④ 同步更新功能
    • ⑤ 噪声波形生成
    • ⑥ 三角波形生成
    • ⑦ 双DAC通道同时或者分别转换
    • ⑧ 每个通道都有DMA功能
  • 单个DAC通道的框图如图所示:

  • 图中VDDA和VSSA为DAC模块模拟部分的供电,而Vref+则是DAC模块的参考电压。DAC_OUTx就是DAC的输出通道了(对应PA4或者PA5引脚)。从图27.1.1可以看出,DAC输出是受DORx寄存器直接控制的,但是我们不能直接往DORx寄存器写入数据,而是通过DHRx间接的传给DORx寄存器,实现对DAC输出的控制。前面我们提到,STM32F767的DAC支持8/12位模式,8位模式的时候是固定的右对齐的,而12位模式又可以设置左对齐/右对齐。单DAC通道x,总共有3种情况:
    • 8位数据右对齐:用户将数据写入DAC_DHR8Rx[7:0]位(实际存入DHRx[11:4]位)。
    • 12位数据左对齐:用户将数据写入DAC_DHR12Lx[15:4]位(实际存入DHRx[11:0]位)。
    • 12位数据右对齐:用户将数据写入DAC_DHR12Rx[11:0]位(实际存入DHRx[11:0]位)。
  • 本实验使用的就是单DAC通道1,采用12位右对齐格式,所以采用第3种情况。
  • 如果没有选中硬件触发(寄存器DAC_CR1的TENx位置’0’),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx。如果选中硬件触发(寄存器DAC_CR1的TENx位置’1’),数据传输在触发发生以后3个APB1时钟周期后完成。一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。我们可以从STM32F767IGT6的数据手册查到的典型值为3us,最大是6us。所以DAC的转
  • 换速度最快是333K左右。
  • 本实验我们将不使用硬件触发(TEN=0),其转换的时间框图如图所示:

  • DAC引脚图

2、DAC输出电压

  • 经过线性转换后,数字输入会转换为0到V_(REF+)之间的输出电压。
  • 各DAC通道引脚的模拟输出电压通过以下公式确定:

DAC_output=V_REF×DOR/4096

3、原理图

  • STM32内部集成两个12位DAC,可以配置成12位或者8位,DAC具有两个独立转换通道。在双DAC模式下,DA转换可被配置成独立模式或者工作模式。iCore4中两路DAC参考电压为2.5V。本实验中我们使用DAC1通道一输出2.0V电压。原理图如下:

四、实验程序

1、主函数

int main(void)
{
  /* MCU配置 */
  /* 重置所有外设, 初始化Flash接口和Systick. */
  HAL_Init();
  /* 系统时钟配置 */
  SystemClock_Config();
  /* 初始化所有已配置的外设 */
  MX_GPIO_Init();
  MX_DAC_Init();
  LED_GREEN_ON;
  HAL_DAC_Start(&hdac, DAC_CHANNEL_1); //开启DAC通道1
  dac1.set_voltage(2.0);
 
  while (1)
  {
  }
}
 

2、DAC初始化

/* DAC初始化函数*/
void MX_DAC_Init(void)
{
  DAC_ChannelConfTypeDef sConfig;
  /** DAC初始化 */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
    /**DAC 通道1配置 */
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}
 
  • HAL库中提供了一个DAC初始化函数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; 
    /* 初始化底层硬件 */
    HAL_DAC_MspInit(hdac);
  }
  /* 初始化DAC状态*/
  hdac->State = HAL_DAC_STATE_BUSY;
  /* 将DAC错误代码设置为none */
  hdac->ErrorCode = HAL_DAC_ERROR_NONE;
  /* 初始化DAC状态*/
  hdac->State = HAL_DAC_STATE_READY;
  /*返回函数状态 */
  return HAL_OK;
}
 

3、使能DAC转换通道

  • 初始化DAC之后,理所当然要使能DAC转换通道,HAL库函数定义如下:
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel)//第一个参数是DAC句柄,第二个用来设置DAC 通道
{
  uint32_t tmp1 = 0, tmp2 = 0;
  /* 检查参数 */
  assert_param(IS_DAC_CHANNEL(Channel));
  /* 锁定进程 */
  __HAL_LOCK(hdac);
  /* 更改DAC状态 */
  hdac->State = HAL_DAC_STATE_BUSY;
  /* 使能外设 */
  __HAL_DAC_ENABLE(hdac, Channel);
  if(Channel == DAC_CHANNEL_1)
  {
    tmp1 = hdac->Instance->CR & DAC_CR_TEN1;
    tmp2 = hdac->Instance->CR & DAC_CR_TSEL1;
    /* 检查是否启用了软件触发器*/
    if((tmp1 ==  DAC_CR_TEN1) && (tmp2 ==  DAC_CR_TSEL1))
    {
      /* 启用选定的DAC软件转换 */
      hdac->Instance->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1;
    }
  }
  else
  {
    tmp1 = hdac->Instance->CR & DAC_CR_TEN2;
    tmp2 = hdac->Instance->CR & DAC_CR_TSEL2;    
    /* 检查是否启用了软件触发器*/
    if((tmp1 == DAC_CR_TEN2) && (tmp2 == DAC_CR_TSEL2))
    {
      /* 启用选定的DAC软件转换*/
      hdac->Instance->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG2;
    }
  }
  /* 更改DAC状态 */
  hdac->State = HAL_DAC_STATE_READY;
  /* 进程解锁 */
  __HAL_UNLOCK(hdac);
  /* 返回函数状态 */
  return HAL_OK;
}

4、设置DAC的输出值

  • 通过前面的步骤设置,DAC就可以开始工作了,我们使用12位右对齐数据格式,就可以在DAC输出引脚( PA4)得到电压值了,相关的函数为:
void set_voltage(double voltage)
{   
    unsigned short int temp;
    temp = voltage * 4095 / 2.5;
    HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp);
}
/* 设置DAC通道的指定数据保持寄存器值 */
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
{  
  __IO uint32_t tmp = 0;
  /* 检查参数 */
  assert_param(IS_DAC_CHANNEL(Channel));
  assert_param(IS_DAC_ALIGN(Alignment));
  assert_param(IS_DAC_DATA(Data));
 
  tmp = (uint32_t)hdac->Instance; 
  if(Channel == DAC_CHANNEL_1)
  {
    tmp += DAC_DHR12R1_ALIGNMENT(Alignment);
  }
  else
  {
    tmp += DAC_DHR12R2_ALIGNMENT(Alignment);
  }
  /*设置DAC通道1选择的数据保持寄存器 */
  *(__IO uint32_t *) tmp = Data;
  /* 返回函数状态 */
  return HAL_OK;
}
 

五、实验步骤

  1. 把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连);
  2. 把iCore4通过Micro USB线与计算机相连,为iCore4供电;
  3. 打开Keil MDK 开发环境,并打开本实验工程;
  4. 烧写程序到iCore4上;
  5. 也可以进入Debug模式,单步运行或设置断点验证程序逻辑。

六、实验现象

  • 用电压表测量PA4引脚有2.0V直流电压输出。
dac实验_输出直流电压.txt · 最后更改: 2022/03/22 10:25 由 sean