您当前的位置: 首页 >  ide

正点原子

暂无认证

  • 2浏览

    0关注

    382博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【正点原子MP157连载】 第二十四章 DAC实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

正点原子 发布时间:2022-03-12 15:29:22 ,浏览量:2

1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-318813-1-1.html 4)正点原子官方B站:https://space.bilibili.com/394620890 5)正点原子STM32MP157技术交流群:691905614 在这里插入图片描述

第二十四章 DAC实验

前面章节我们学习了ADC实验,本章,我们将介绍STM32MP157的DAC(Digital -to- analog converters,数模转换器)功能。我们将通过三个实验来学习DAC,分别是DAC输出实验、DAC输出三角波实验和DAC输出正弦波实验。 本章分为如下几个小节: 24.1 、DAC简介; 24.2 、DAC输出实验; 24.3 、DAC输出三角波实验; 24.4 、DAC输出正弦波实验;

24.1 DAC简介 数字/模拟转换器(Digital-to-Analog Converter),是指将离散的数字信号转换为连续变量的模拟信号的器件,简称DAC。在模拟电路中,电流电压信号的变化是连续的,而数字电路处理的数据都是离散的数据,DAC将表示一定比例电压值的数字信号转换为模拟信号,这使得主控芯片不再只是输出数字0或者1,从而得到更广泛应用。 (1)分辨率 DAC的分辨率定义为输出满刻度电压与2n的比值,其中n为DAC的位数,所以DAC的位数也可以用来表示分辨率,例如某个DAC的分辨率是12bit、10bit。 DAC的分辨率反应了输出模拟电压的最小变化值,以一个12位的DAC为例,其数据变化范围是0~4096,对于3.3V的满量程,采用8位的DAC时,分辨率为3.3V/256=12.89mV,当采用12位的DAC时,分辨率则为3.3V/4096=0.81mV。显然,位数越多,其输出电压的取值个数就越多(2n 个),也就越能反映出输出电压的细微变化,分辨能力就越高。 (2)建立时间 建立时间是描述DAC转换速度快慢的参数,定义为从输入数字量变化到输出(DAC_OUT)达到终值误差值±1LSB时所需的时间。从参考手册上可以找到STM32MP157的建立时间tSETTLING的典型值是2us。 (3)基准电压 基准电压也叫参考电压,也就是当做参照作用。我们测试外部电压时会以基准电压作为参考,先把基准电压分成多少分(根据分辨率来分),然后再和被测电压进行比较,然后得到比较的结果,这样就能测试出输入电压是多少了。 24.1.1 DAC特性 STM32MP157的DAC模块(数字/模拟转换模块)是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,可以在每个DAC输出通道上进行单独的校准,每个通道都有单独的转换器,DAC输出通道支持低功耗模式。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+(和ADC共用)以获得更精确的转换结果。当DAC输出与焊盘断开并连接至片上外设时,DAC_OUTx引脚可用作通用输入/输出引脚(GPIO)。 STM32MP157的DAC模块主要特点有: ① 1个DAC转换器,每个DAC最多2个输出通道 ; ② 12位模式下数据左对齐或者右对齐 ; ③ 同步更新功能 ; ④ 噪声波形生成 ; ⑤ 三角波形生成 ; ⑥ 双DAC通道同时或者分别转换; ⑦ 每个通道都有DMA功能; ⑧ 通过外部触发信号进行转换; ⑨ 每路 DAC 输出均可与 DAC_OUTx 输出引脚断开连接; ⑩ DAC 输出可与片上外设连接; ⑪ 可在停止模式下通过采样和保持模式实现低功耗运行; ⑫ 来自VREF+引脚的输入参考电压。 DAC通道框图如下图所示: 24.1.2 DAC框图 在这里插入图片描述

图23.1.2. 5 DAC通道框图 ADC框图中的输入/输出引脚信息如下表所示: 在这里插入图片描述

表23.1.2. 2 DAC输入/输出引脚 除了上表列出的输入/输出引脚,DAC通道框图还有一些内部输入/输出信号,具体如下表所示: 在这里插入图片描述

表23.1.2. 3 DAC内部输入/输出信号 关于DAC框图的内容,我们做如下讲解:

  1. DAC的输入/输出引脚以及内部信号 图中VDDA和VSSA为DAC模块模拟部分的供电。VREF+ 是正模拟参考电压输入,选择范围是1.62V~3.6V,开发板上我们一般给VREF+接入的电压时3.3V。在ADC实验章节我们说过,STM32MP157有ADC和DAC共用的内部基准电压VREFBUF,可通过VREFBUF_CSR寄存器进行配置,可选1.5 V、1.8 V、2.048 V和2.5 V。 要注意的是,DAC只能在VDDA高于或等于1.8V时使用,使用内部参考电压VREF+时要求VDDA高于或等于VERF+++0.3V。 DAC_OUT1/2就是DAC的两个输出通道了(对应PA4和PA5引脚): 在这里插入图片描述

图23.1.2. 6DAC的两个输出通道引脚 注意:表中的dac_pclk即DAC的时钟源,转换和寄存器访问都是靠这个时钟,该时钟来自APB1,最大可以配置为104.5Mhz。 从通道框图可以看出,DAC输出是受DAC_DORx寄存器直接控制的,但是我们不能直接往DAC_DORx寄存器写入数据,而是通过DAC_DHRx间接的传给DAC_DORx寄存器,实现对DAC输出的控制。 2. DAC通道使能/转换速度和输出电压 (1)DAC通道使能 将 DAC_CR 寄存器中的相应 ENx位置1,即可使能对应DAC 通道。经过一段启动时间 tWAKEUP后,DAC 通道被真正使能。从数据手册查询,tWAKEUP 的典型值为2us或者5 us: 在这里插入图片描述

图23.1.2. 7 tWAKEUP 时间 一旦使能DAC通道,相应的GPIO引脚(PA4和PA5)就会自动与DAC的模拟输出(DAC_OUTx)相连,为了避免寄生的干扰和额外的功耗,引脚PA4和PA5应当设置成模拟输入。 (2)DAC的转换速度 DAC的转换速度最快是1MSPS: 在这里插入图片描述

图23.1.2. 8 DAC的转换速率 (3)DAC的输出电压 DAC就是数字量转换为模拟量,数字输入经过DAC被线性地转换为模拟电压输出。当DAC的参考电压为VREF+的时候,DAC的输出电压是线性的从0~VREF+,12位模式下DAC输出电压与VREF +以及DORx的计算公式如下: DACx输出电压= VREF *(DORx/4096) 3. DAC的8/12位数据格式 前面我们提到,STM32MP157的DAC支持8/12位模式,8位模式的时候是固定的右对齐的,而12位模式又可以设置左对齐/右对齐。DAC单通道模式下的数据寄存器对齐方式,总共有3种情况,如下图所示:在这里插入图片描述

图23.1.2. 9 DAC单通道模式下的数据寄存器对齐方式 ①8位数据右对齐:用户将数据写入DAC_DHR8Rx[7:0]位(实际存入DAC_DHRx寄存器的DHRx[11:4]位,后面的描述中我们只写DHRx[11:4]位)。 ②12位数据左对齐:用户将数据写入DAC_DHR12Lx[15:4]位(实际存入DHRx[11:0]位)。 ③12位数据右对齐:用户将数据写入DAC_DHR12Rx[11:0]位(实际存入DHRx[11:0]位)。 我们本章实验中使用的都是单通道模式下的DAC通道1,采用12位右对齐格式,所以采用第③种情况。另外DAC还具有双通道转换功能。对于 DAC 双通道(可用时),也有三种可能的方式,如下图所示: 在这里插入图片描述

图23.1.2. 10 DAC双通道模式下的数据寄存器对齐方式 ①8位数据右对齐:用户将DAC通道1的数据写入DAC_DHR8RD[7:0]位(DHR1 [11:4]位),将DAC通道2的数据写入DAC_DHR8RD[15:8]位(DHR2 [11:4]位)。 ②12位数据左对齐:用户将DAC通道1的数据写入DAC_DHR12LD[15:4]位(实际存入DHR1[11:0]位),将DAC通道2的数据写入DAC_DHR12LD [31:20]位(实际存入DHR2[11:0]位)。 ③12位数据右对齐:用户将DAC通道1的数据写入DAC_DHR12RD [11:0]位(实际存入DHR1[11:0]位),将DAC通道2的数据写入DAC_DHR12RD [27:16]位(实际存入DHR2[11:0]位)。 4. DAC的触发选择 写入到DAC_DHRyyy(就是上述提到的DAC_DHR8Rx、DAC_DHR12Lx和DAC_DHR12Rx等)的值,经过相应的移位操作后会被转存到DHRx寄存器中,随后,DHRx寄存器的内容可以通过触发后被自动地传送到DAC_DORx寄存器中,当 DAC_DORx加载了DAC_DHRx内容时,模拟输出电压将在一段时间 tSETTLING 后可用,也就是从DAC_OUTx引脚上输出,输出的值就是我们要获取的转换值。tSETTLING 的具体时间取决于电源电压和模拟输出负载,我们可以从《STM32MP157A&D数据手册》找到此值的典型值是2us。 DAC可以通过软件或者硬件触发转换,通过配置TENx控制位来决定。 (1)不使用触发 TENx为0时不使用触发,DAC通道x的触发被禁用,写入到DAC_DHRx寄存器的数据在一个APB1时钟后自动传至寄存器DAC_DORx中。不使用触发转换的时间框图如下图所示,dac_pclk的时钟其实也就是APB1总线时钟: 在这里插入图片描述

图23.1.2. 11 TEN=0时DAC模块转换时间框图 (2)使用触发 TENx为1时,表示使能触发,这里分为软件触发和硬件触发。DAC_CR寄存器的TSELx[3:0]为0000时表示选择软件触发,DAC_CR寄存器的TSELx[3:0]不为0000时(具体设置什么可以根据此位的设置来),表示选择硬件触发。 软件触发 如果选择软件触发,一旦DAC_SWTRGR 寄存器的SWTRIGx(x=1,2)位置 1,转换随即开始。DAC_DHRx的内容加载到DAC_DORx寄存器中后,SWTRIG 即由硬件清0。如果选择软件触发,DAC_DHRx寄存器的内容只需一个dac_pclk(也就是一个APB1)时钟周期即可转移到DAC_DORx寄存器中。ENx 位置1(使能DAC通道)时就无法更改TSELx[3:0]位。 硬件触发 如果选中硬件触发,每次DAC接口检测到触发信号时(定时器TRGO输出,或者外部中断线9的上升沿),最新存放在DAC_DHRx的值会被传入DAC_DORx中,发生触发后再经过3个dac_pclk周期(3个APB1时钟周期)后,DAC_DORx寄存器将会得到更新。一旦DAC_DORx寄存器的值更新后,再经过时间tSETTLING之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。 如果使用触发(TEN=1),可通过TSELx[3:0]控制位来决定选择16个触发事件中的某一个来触发DAC转换。这16个触发事件的部分事件如下表所示: 在这里插入图片描述

其它 保留 表23.1.2. 4 DAC触发选择 采样和保持模块(低功耗)及其关联寄存器可在停止模式下使用 LSI时钟源(dac_hold_ck)运行。 5. DAC的DMA请求 每个DAC通道都有DMA功能,两个DMA通道分别用于处理两个DAC通道的DMA 请求。如果DMAENx 位置1时,如果发生硬件触发(而不是软件触发),就会产生一个DMA 请求,然后DAC_DHRx的数据被转移到DAC_DORx中。 DAC_DMA请求没有缓冲队列,如果第二个外部触发到达时,尚未收到第一个外部触发的应答,将不会发出新的请求,DMA通道下溢标志 DMAUDRx将置1,产生中断(DMA下溢),DAC 通道仍将继续转换旧有数据。软件通过写1到DMAUDRx中来清除标志位,将所用 DMA 数据流的 DMAEN 位清零,并重新初始化 DMA 和 DAC 通道,以便正确地重新开始 DMA 传输。 在这里插入图片描述

表23.1.2. 5 DAC中断 24.2 DAC输出实验 本实验我们来学习DAC输出实验。 本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\ 17-1 DAC_OUT1。 24.2.1 DAC寄存器 下面,我们介绍要实现DAC的通道1输出,需要用到的一些DAC寄存器。

  1. DAC控制寄存器(DAC_CR) DAC控制寄存器描述如下图所示: 在这里插入图片描述

图23.2.1. 1 DAC_CR寄存器 DAC_CR的低16位用于控制通道1,而高16位用于控制通道2,我们这里仅列出本实验需要设置的一些位: EN1位:用于DAC通道1的使能,我们需要用到DAC通道1的输出,该位必须设置为1。 TEN1位:用于DAC通道1的触发使能,我们设置该位为0,不使用硬件触发。写入DAC_DHR1的值会在1个APB1周期后传送到DAC_DOR1,然后输出到PA4口上。 TSEL[3:0]位:用于选择DAC通道1的触发方式,本实验设置为0,使用软件触发。 WAVE[1:0]位:用于控制DAC通道1的噪声/波形输出功能,默认设置为00,不使能噪声/波形输出。 DMAEN1位:用于控制DAC通道1的DMA使能,本实验不使用DMA,设置该位为0即可。 CEN1位:用于控制DAC通道1的输出缓冲校准使能,本章不使用校准功能(默认有一个出厂校准值,我们使用默认的校准值即可),设置该位为0即可。 2. DAC模式控制寄存器(DAC_ MCR) DAC模式控制寄存器描述如下图所示: 在这里插入图片描述

图23.2.1. 2 DAC_ MCR寄存器 该寄存器我们只关心MODE1[2:0],这三个位用于设置DAC通道1的工作模式。本章使用普通模式,且使用输出缓冲,设置MODE1[2:0]=0即可。MODE2[2:0] 设置通道2的工作模式,本实验没用到。 3. DAC通道1 12位右对齐数据保持寄存器(DAC_ DHR12R1) DAC通道1 12位右对齐数据保持寄存器描述如图下图所示: 在这里插入图片描述

图23.2.1. 3 DAC_ DHR12R1寄存器 该寄存器用来设置DAC输出,通过写入12位数据到该寄存器,就可以在DAC输出通道1(PA4)得到我们所要的结果。 24.2.2 DAC的HAL库驱动 DAC在HAL库中的驱动代码在stm32mp1xx_hal_dac.c和stm32mp1xx_hal_dac_ex.c文件(及其头文件)中,可以翻看这两个文件来了解。

  1. HAL_DAC_Init函数 DAC的初始化函数,其声明如下: HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac); 函数描述: 用于初始化DAC。 函数形参: 形参1是DAC_HandleTypeDef结构体类型指针变量,其定义如下:
typedef struct
{
  DAC_TypeDef                    *Instance;       /* DAC寄存器基地址 */
  __IO HAL_DAC_StateTypeDef    State;           /* DAC 工作状态 */
  HAL_LockTypeDef                Lock;            /* DAC锁定对象 */
  DMA_HandleTypeDef             *DMA_Handle1;   /* 通道1的DMA处理句柄指针 */
  DMA_HandleTypeDef             *DMA_Handle2;   /* 通道2的DMA处理句柄指针 */
  __IO uint32_t               

从该结构体看到该函数并没有设置任何DAC相关寄存器,即没有对DAC进行任何配置,它只是HAL库提供用来在软件上初始化DAC,为后面HAL库操作DAC做好准备。 函数返回值: HAL_StatusTypeDef枚举类型的值。 注意事项: DAC的MSP初始化函数HAL_DAC_MspInit,该函数声明如下: void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac); 2. HAL_DAC_ConfigChannel函数 DAC 的通道参数初始化函数,其声明如下: HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel); 函数描述: 该函数用来配置DAC通道的触发类型以及输出缓冲。 函数形参: 形参1是DAC_HandleTypeDef结构体类型指针变量。 形参2是DAC_ChannelConfTypeDef结构体类型指针变量,其定义如下:

typedef struct
{
  uint32_t DAC_SampleAndHold;      		/* 设置是否使能低功耗模式,即采样和保持模式 */
  uint32_t DAC_Trigger;             		/* DAC触发源的选择 */
  uint32_t DAC_OutputBuffer;      	 	/* 启用或者禁用DAC通道输出缓冲区 */
  uint32_t DAC_ConnectOnChipPeripheral; /* 指定DAC输出是否连接到片上外设 */
  uint32_t DAC_UserTrimming;   /* 设置DAC的校准方式,采用出厂模式还是用户模式 */
  uint32_t DAC_TrimmingValue;  /* 设置用户校准模式的偏移值 */
  DAC_SampleAndHoldConfTypeDef  DAC_SampleAndHoldConfig; /* 设置采样保持具体参数 */
} DAC_ChannelConfTypeDef;

形参3用于选择要配置的通道,可选择DAC_CHANNEL_1或者DAC_CHANNEL_2。 函数返回值: HAL_StatusTypeDef枚举类型的值。 3. HAL_DAC_Start函数 使能启动DAC转换通道函数,其声明如下: HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel); 函数描述: 使能启动DAC转换通道。 函数形参: 形参1是DAC_HandleTypeDef结构体类型指针变量。 形参2用于选择要启动的通道,可选择DAC_CHANNEL_1或者DAC_CHANNEL_2。 函数返回值: HAL_StatusTypeDef枚举类型的值。 4. HAL_DAC_SetValue函数 DAC的通道输出值函数,其声明如下: HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data); 函数描述: 配置DAC的通道输出值。 函数形参: 形参1是DAC_HandleTypeDef结构体类型指针变量。 形参2用于选择要输出的通道,可选择DAC_CHANNEL_1或者DAC_CHANNEL_2。 形参3用于指定数据对齐方式。 形参4设置要加载到选定数据保存寄存器中的数据。 函数返回值: HAL_StatusTypeDef枚举类型的值。 5. HAL_DAC_GetValue函数 DAC读取通道输出值函数,其声明如下: uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef *hdac, uint32_t Channel); 函数描述: 获取所选DAC通道的最后一个数据输出值。 函数形参: 形参1是DAC_HandleTypeDef结构体类型指针变量。 形参2用于选择要读取的通道,可选择DAC_CHANNEL_1或者DAC_CHANNEL_2。 函数返回值: 获取到的输出值。 24.2.3 硬件设计

  1. 例程功能 使用KEY0/KEY1两个按键,控制STM32MP157内部DAC的通道1输出电压大小,然后通过ADC1的通道19采集DAC输出的电压,并通过串口将ADC采集到的电压值以及DAC的设定输出电压值等信息打印出来。实验中,LED0闪烁,提示程序在运行。 实验时,请用跳线帽将PA4和PA5接在一起: 在这里插入图片描述

图23.2.3. 1 硬件连接 本节实验ADC的配置和相关代码部分和ADC实验章节的 单通道ADC采集实验 部分一样。 2. 硬件资源 1)LED灯:LED0 2)按键KEY0和KEY1 3)串口4 4)ADC1的通道19引脚(PA5) 5)DAC的通道1 LED0 UART4_TX UART4_RX ADC1_INP19 DAC_CHANNEL_1 KEY0 KEY1 PI0 PG11 PB2 PA5 PA4 PG3 PH7 表23.2.3. 1硬件资源 3. 原理图 ADC和DAC属于STM32MP157的内部资源,实际上我们只需要软件设置就可以正常工作。 在这里插入图片描述

图23.2.3. 2 原理图部分 24.2.4 软件设计

  1. 新建和配置工程 (1)配置LED0、KEY0、KEY1和UART4 新建工程DAC_OUT1,本节实验我们会用到UART4发送数据,还会使用到按键KEY1、KEY0以及LED0,所以我们这里按照前面的实验章节配置LED0、KEY0、KEY1。UART4的配置我们这里就不再赘述了,请参考前面串口通信实验章节的来配置。 在这里插入图片描述

图23.2.4. 1 按键和LED的引脚部分配置 在这里插入图片描述

图23.2.4. 2 UART4引脚部分配置 LED0和按键以及UART4的代码我们本节实验就不讲解了,大家可以参考本实验工程里的代码,也可以参考前面相关实验章节部分。 (2)配置ADC ADC1的配置可参考前面 单通道ADC采集实验 部分。选择ADC1的通道19: 在这里插入图片描述

图23.2.4. 3选择ADC1的通道19 ADC的配置参数我们前面ADC实验章节已经做了详细讲解,这里就不再说明,配置如下: 在这里插入图片描述

图23.2.4. 4配置ADC1的参数 (3)配置DAC DAC配置如下,DAC的每路输出均可与DAC_OUTx输出引脚断开连接,然后可与片上外设连接。这里我们可以配置DAC输出连接到外部引脚DAC_OUTx。 DAC参数配置部分: Output Buffer配置使能; Trigger配置触发源,可以配置软件触发和硬件触发以及不触发,我们配置不触发; DAC High Frequency配置DAC是否以指定频率接口模式工作,可以开启或者关闭高频接口模式,或者设置高频接口模式为自动模式。 User Trimming设置DAC的校准方式,采用出厂模式还是用户模式。校准的目的是为了减少误差,这里我们就默认使用出厂模式; Sample And Hold用于设置是否使能低功耗模式,即采样和保持模式,这里我们就不选择了。 在这里插入图片描述

图23.2.4. 5配置DAC的输出通道1 (4)UART相关的参数配置 UART4的参数配置以及中断配置请参考前面串口通信实验。 (5)时钟配置 这里配置MCU的时钟为209MHz,使用外部时钟HSE,这部分配置可以参考前面实验章节: 在这里插入图片描述

图23.2.4. 6时钟树配置 ADC1的时钟使用PER,其中PER时钟源默认使用HSI,即为64MHz。上面ADC参数配置中,我们配置分频系数为2,所以实际ADC的时钟是32MHz。DAC因为接在APB1上,DAC的时钟是104.5MHz。 (6)配置生成独立的.c和.h文件 在这里插入图片描述

图23.2.4. 7配置生成独立的文件 2. 生成工程 保存配置,生成工程后,将前面按键输入实验章节使用的BSP文件夹拷贝到工程的Src文件夹下,本节我们要使用LED0、KEY0和KEY1的驱动,所以将LED1和WKUP相关的代码注释掉即可。 在这里插入图片描述

图23.2.4. 8生成工程 3. 初始化代码分析 ADC的初始化代码我们在前面章节的实验已经介绍过,这里就不再介绍了。DAC的初始化代码在dac.c文件及其头文件中,代码附上了详细的注释,如下:

/**
* @brief   DAC外设初始化函数
* @note    DAC的输入时钟来自APB1, 时钟频率=104.5Mhz=9.5ns
           	DAC在输出buffer关闭的时候, 输出建立时间: 
           	tSETTLING = 2us (STM32MP1数据手册有写)
           	因此DAC输出的最高速度约为:500Khz, 以10个点为一个周期, 
           	最大能输出50Khz左右的波形。
* @param   无
* @retval  无
*/
#include "dac.h"
DAC_HandleTypeDef hdac1; 							/* DAC句柄 */
void MX_DAC1_Init(void)
{
  DAC_ChannelConfTypeDef sConfig = {0};
  hdac1.Instance = DAC1;								/* DAC1,只有一个DAC */
  if (HAL_DAC_Init(&hdac1) != HAL_OK) 				/* DAC初始化 */
  {
    Error_Handler();
  }
  /* 关闭高频接口模式 */
  sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_DISABLE;
  /* 不使能低功耗模式 */
  sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;			/* 不使用触发源 */
  /* 输出Buffer使能 */
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  /* DAC输出不连接到外围设备 */
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
  /* 校准模式为出厂模式 */
  sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
  /* DAC通道初始化 */
  if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
}
/**
* @brief   DAC的引脚初始化函数
* @param   dacHandle DAC句柄
* @retval  无
*/
void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(dacHandle->Instance==DAC1)
  {
    __HAL_RCC_DAC12_CLK_ENABLE();				/* 开启DAC时钟 */
    __HAL_RCC_GPIOA_CLK_ENABLE();				/* 开启GPIOA时钟 */
    /**DAC1 GPIO Configuration
    PA4     ------> DAC1_OUT1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4;			/* 引脚4 */
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;	/* 模拟模式 */
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);	/* 初始化GPIO引脚 */
  }
}
/**
* @brief   DAC外设取消初始化函数
* @note    如果有必要,可以调用此函数来取消初始化DAC
* @param   dacHandle DAC句柄
* @retval  无
*/
void HAL_DAC_MspDeInit(DAC_HandleTypeDef* dacHandle)
{
  if(dacHandle->Instance==DAC1)
  {
    __HAL_RCC_DAC12_CLK_DISABLE();				/* 关闭DAC时钟 */
    /**DAC1 GPIO Configuration
    PA4     ------> DAC1_OUT1
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);			/* 取消初始化DAC */
  }
}
  1. 添加用户代码 (1)修改adc.c文件 按照前面 单通道ADC采集实验 章节,在adc.c中添加如下代码:
/* USER CODE BEGIN 1 */
/**
 * @brief       获取ADC1通道ch的转换结果,先取times次,然后取平均
 * @param       ch      : 通道 ,为0~19
 * @param       times   : 获取次数
 * @retval      通道ch的times次转换结果的平均值
 */
uint32_t adc_get_result_average(uint32_t ch, uint8_t times)
{
    uint32_t temp_val = 0;
    uint8_t t;
    /* ADC校准 */
    HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); 
    HAL_ADC_Start(&hadc1);                             /* 启动ADC */
    HAL_ADC_PollForConversion(&hadc1, 10);          /* 轮询转换 */;
    for (t = 0; t (samples/2),此三角波的周期T=samples*dt,那么此三角波的频率就是1/T。 本实验我们就采用以上第二种方法,实验中,我们通过修改dt的值和samples的值来实现输出两种波形: 1)设置dt为5us,samples为2000,则输出的三角波频率为100Hz; 2)设置dt为500us,samples为20,则输出的三角波也是100Hz。 24.3.2 DAC寄存器

  1. DAC_CR寄存器 本实验用到的DAC_DHRx和DAC_DORx寄存器在上一章节已经介绍了,这里我们介绍DAC_CR寄存器和三角波设置有关的位,如下: 在这里插入图片描述

图24.3.2. 1 DAC_CR寄存器 如果使用触发方式,对应位设置如下: TENx位用于使能DAC的通道,将该位置1则使能对应的通道; WAVEx[1:0]用于使能或者禁止生成波,如果要生成三角波,此位设置为1x; DAC_CR寄存器的MAMP1[3:0]和MAMP2[3:0]分别对应的是的是通道1和通道2的掩码/振幅选择器配置项,这些位由软件写入,用于在生成噪声波模式下选择掩码,或者在生成三角波模式下选择振幅,MAMP1[3:0]配置如下: 0000:不屏蔽 LFSR 的位 0/三角波振幅等于 1 0001:不屏蔽 LFSR 的位 [1:0]/三角波振幅等于 3 0010:不屏蔽 LFSR 的位 [2:0]/三角波振幅等于 7 0011:不屏蔽 LFSR 的位 [3:0]/三角波振幅等于 15 0100:不屏蔽 LFSR 的位 [4:0]/三角波振幅等于 31 0101:不屏蔽 LFSR 的位 [5:0]/三角波振幅等于 63 0110:不屏蔽 LFSR 的位 [6:0]/三角波振幅等于 127 0111:不屏蔽 LFSR 的位 [7:0]/三角波振幅等于 255 1000:不屏蔽 LFSR 的位 [8:0]/三角波振幅等于 511 1001:不屏蔽 LFSR 的位 [9:0]/三角波振幅等于 1023 1010:不屏蔽 LFSR 的位 [10:0]/三角波振幅等于 2047 ≥ 1011:不屏蔽 LFSR 的位 [11:0]/三角波振幅等于 4095 WAVE1[1:0]和WAVE2[1:0]用于使能DAC通道1和通道2的噪声/三角波生成,这些位由软件置 1 或清零: 00:禁止生成波 01:使能生成噪声波 1x:使能生成三角波 2. 其它寄存器 关于本节实验用到的DAC的HAL库驱动,我们前面的实验章节已经介绍过,这里就不再重复介绍了。 24.3.3 DAC的HAL库驱动 本实验中用到的HAL库驱动前面的实验代码都有介绍到,这里就不再赘述。 24.3.4 硬件设计

  1. 例程功能 使用DAC输出三角波,通过KEY0/KEY1两个按键,控制DAC1的通道1输出两种三角波,需要通过示波器接PA4进行观察波形。LED0闪烁,提示程序运行。 我们只需要把示波器的探头接到DAC1通道1(PA4)引脚,就可以在示波器上显示DAC输出的波形。PA4的引脚排针已经引出,硬件连接如下图所示: 在这里插入图片描述

图24.3.4. 1硬件连接示意图 2. 硬件资源 1)LED灯:LED0 2)按键KEY0和KEY1 3)DAC的通道1 LED0 DAC_CHANNEL_1 KEY0 KEY1 PI0 PA4 PG3 PH7 表24.3.4. 1硬件资源 3. 原理图 DAC属于STM32MP157的内部资源,实际上我们只需要软件设置就可以正常工作。 在这里插入图片描述

图24.3.4. 2原理图部分 24.3.5 软件设计

  1. 创建和配置工程 本实验使用到DAC,可以直接在上一章节的实验的基础上操作。为了方便,我们新建了一个工程DAC_Triangle_Wave,DAC工程的配置和上一章节的一样,这里我们没有用到ADC,关于ADC部分我们就不配置了。

图24.3.5. 1DAC配置 关于本节实验用到的LED0、KEY1和KEY0的配置清参考前面相关的实验章节部分。时钟配置使用HSE作为锁相环PLL3的输入时钟源,我们配置APB1为104.5MHz,关于时钟配置也请参考前面实验有关章节部分。 2. 生成工程 生成工程,并将上一章节用到的BSP文件夹拷贝到本工程的Src目录下,因为我们会用到上一章节实验的LED0和KEY0以及KEY1的驱动程序,然后本节实验会用到微秒延时函数(dt采用us来计时),所以将SysTick高精度延时实验的delay.c和delay.h文件拷贝到本工程的BSP文件夹下。

图24.3.5. 2生成工程 3. 添加用户代码 (1)添加三角波生成函数 如下,我们在dac.c文件中添加如下代码:

1   /* USER CODE BEGIN 1 */
2   /**
3    * @brief   设置DAC_OUT1输出三角波
4    * @note    输出频率 ≈1/(dt*samples),注意单位换算。不过在dt较小
5    *          的时候,比如小于5us时, 由于delay_us本身就不准了(调用函数,
6    *          计算等都需要时间,延时很小的时候,这些时间会影响到延时), 频率会偏小.
7    * 
8    * @param   maxval : 最大值(0            
关注
打赏
1665308814
查看更多评论
0.0471s