用户工具

站点工具


dac实验_输出直流电压

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
dac实验_输出直流电压 [2019/11/29 10:08]
zhangzheng 创建
dac实验_输出直流电压 [2022/03/22 10:25] (当前版本)
sean
行 1: 行 1:
-[[http://www.cnblogs.com/xiaomagee/p/6029002.html]]+|  **银杏科技有限公司旗下技术文档发布平台** ​ |||| 
 +|技术支持电话|**0379-69926675-801**||| 
 +|技术支持邮件|Gingko@vip.163.com||| 
 +^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ 
 +|  V1.0  |  2020-07-11 |  gingko ​ |  初次建立 ​ |  
 + 
 +===== 实验三十六:DAC实验——输出直流电压 ===== 
 +==== 一、实验目的与意义 ==== 
 +  - 了解STM32的DAC结构。 
 +  - 了解STM32的DAC特征。 
 +  - 掌握DAC的使用方法。 
 +  - 掌握STM32 HAL库中DAC属性的配置方法。 
 +  - 掌握KEIL MDK 集成开发环境使用方法。 
 +==== 二、实验设备及平台 ==== 
 +  - iCore4 双核心板。 
 +  - JLINK(或相同功能)仿真器。 
 +  - Micro USB线缆。 
 +  - Keil MDK 开发平台。 
 +  - STM32CubeMX开发平台。 
 +  - 装有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通道的框图如图所示: 
 +{{ :​icore4:​icore4_arm_hal_36_1.png?​direct |}}  
 +  * 图中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),其转换的时间框图如图所示: 
 +{{ :​icore4:​icore4_arm_hal_36_2.png?​direct |}}  
 +  * DAC引脚图 
 +{{ :​icore4:​icore4_arm_hal_36_3.png?​direct |}}  
 +=== 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电压。原理图如下: 
 +{{ :​icore4:​icore4_arm_hal_36_4.png?​direct |}}  
 +==== 四、实验程序 ==== 
 + 
 +1、主函数 
 +<code c>  
 +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) 
 +  { 
 +  } 
 +
 +  
 +</code> 
 +2、DAC初始化 
 +<code c>  
 +/* 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__);​ 
 +  } 
 +
 +  
 +</​code>​ 
 +  * HAL库中提供了一个DAC初始化函数HAL_DAC_Init,该函数定义如下: 
 +<code c>  
 +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; 
 +
 +  
 +</​code>​ 
 +3、使能DAC转换通道 
 +  * 初始化DAC之后,理所当然要使能DAC转换通道,HAL库函数定义如下: 
 +<code c>  
 +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; 
 +
 + 
 +</​code>​ 
 +4、设置DAC的输出值 
 +  * 通过前面的步骤设置,DAC就可以开始工作了,我们使用12位右对齐数据格式,就可以在DAC输出引脚( PA4)得到电压值了,相关的函数为: 
 +<code c>  
 +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; 
 +
 +  
 +</​code>​ 
 +==== 五、实验步骤 ==== 
 + 
 +  - 把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连); 
 +  - 把iCore4通过Micro USB线与计算机相连,为iCore4供电; 
 +  - 打开Keil MDK 开发环境,并打开本实验工程; 
 +  - 烧写程序到iCore4上; 
 +  - 也可以进入Debug模式,单步运行或设置断点验证程序逻辑。 
 +==== 六、实验现象 ==== 
 + 
 +  * 用电压表测量PA4引脚有2.0V直流电压输出。 
dac实验_输出直流电压.1574993297.txt.gz · 最后更改: 2019/11/29 10:08 由 zhangzheng