STM32

您所在的位置:网站首页 基于stm32的dac输出正弦波 STM32

STM32

2024-06-16 21:55:21| 来源: 网络整理| 查看: 265

一、工具

  1、硬件:STM32F429BI单片机(HAL库)

  2、编译环境:Atollic TrueSTUDIO for STM32 9.3.0

  3、辅助工具:STM32CubeMX

二、需求分析

  现有以下需求,需要单片机能够同时输出一个方波和三角波,并且使方波的高电平的中间与三角波的波峰对齐,方波的低电平中间与三角波的波谷对齐,于此同时还必须能够在任意时刻更改两个波形的频率以及三角波的幅值,效果如下图所示:

 

   首先三角波必须得使用单片机的DAC来控制输出,只需要和一个定时器配合工作,即可实现不同频率的三角波输出;方波可以使用DAC输出也可以使用定时器输出,如果使用DAC输出方波,这就需要单片的DAC具备至少两个通道;如果使用定时器输出方波就得考虑同时启动的问题。这里我使用单片机DAC的双通道实现。

  1、通过查阅对应的芯片手册,可以看到关于DAC生成三角波的介绍,具体内容如下图所示:

   这里我总结下来就是:DAC有一个用于计数的寄存器DOR,而这个寄存器不会自己自加或者自减,自加和自减需要借助定时器产生的事件来完成(通常定时器会在一个周期内产生一个事件),而[DOR寄存器的值+DHRx寄存器的值]就是当前DAC输出的电压AD值,幅值就是[DHRx寄存的值+MAMPx寄存器的值]。尽管单片机具备输出三角波的功能,但在使用中发现不够灵活,于是乎我舍弃该方式,使用DAC+DMA的方式输出三角波和方波。

三、单片机系统时钟配置

  1、系统时钟配置(没有显示的默认),这里选择的是外部的高速时钟(HSE)作为时钟源,系统时钟频率配置到96MHz。

 

 

四、触发源定时器配置

  这里选择定时器6作为触发源,该定时器主要是为DAC提供更新事件,具体配置如下图所示。

 

五、DAC配置

  DAC选择通道1和通道2配置相同,触发源选择的是定时器6,具体配置如下图所示:

  补充:这里配置DAC的时候需要设置“Output Buffer”为“DISABLE”,否则三角波的波谷会出现不正常的波形。

 

   DAC的两个通道都开启DMA且配置相同,具体配置如下图所示:

 七、生成工程并进行完善

  1、生成工程设置

 

  2、添加个人代码

DAC_HandleTypeDef hdac; DMA_HandleTypeDef hdma_dac1; DMA_HandleTypeDef hdma_dac2; TIM_HandleTypeDef htim6;

  WAVEFORM_POINT_NUM的值要根据定时器时钟源来灵活设定,首先做到能被4整除,再者使定时器的时钟源能被(定时器频率*WAVEFORM_POINT_NUM)整除,比如当前我的定时器的时钟源为48MHz,如果输出1KHz频率的三角波和方波,则有(1KHz*WAVEFORM_POINT_NUM) = 48MHz/(psc*per)。

#define WAVEFORM_POINT_NUM 800 uint32_t DAC_ch1_value[WAVEFORM_POINT_NUM]; uint32_t DAC_ch2_value[WAVEFORM_POINT_NUM]; /** * @brief 初始化三角波数组值 * @param amplitude 三角波幅值对应的DA值 * @param p 被初始化的数组起始地址 * @param length 被初始化的数组长度(长度值要能被4整除) * @retval none */ void triangle_array_init(uint16_t amplitude, uint32_t *p, uint32_t length) { uint32_t i; float unit_value = 0; unit_value = (amplitude/(length/2.0)); for( i = 0; i < length; i++) { if(i Instance==TIM6) { /* Peripheral clock enable */ __HAL_RCC_TIM6_CLK_ENABLE(); } } /** * @brief TIM_Base MSP De-Initialization * This function freeze the hardware resources used in this example * @param htim_base: TIM_Base handle pointer * @retval None */ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) { if(htim_base->Instance==TIM6) { /* Peripheral clock disable */ __HAL_RCC_TIM6_CLK_DISABLE(); } }

  DMA初始化,具体内容看代码:

/** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Stream5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* DMA1_Stream6_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn); }

  DMA中断函数,具体内容看代码:   

/** * @brief This function handles DMA1 stream5 global interrupt. */ void DMA1_Stream5_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_dac1); } /** * @brief This function handles DMA1 stream6 global interrupt. */ void DMA1_Stream6_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_dac2); }

 

  DAC引脚初始化,及使能时钟,具体内容看代码:

/** * @brief DAC Initialization Function * @param None * @retval None */ static void MX_DAC_Init(void) { DAC_ChannelConfTypeDef sConfig = {0}; /** DAC Initialization */ hdac.Instance = DAC; if (HAL_DAC_Init(&hdac) != HAL_OK) { Error_Handler(); } /** DAC channel OUT1 config */ sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK) { Error_Handler(); } /** DAC channel OUT2 config */ if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_2) != HAL_OK) { Error_Handler(); } }

 

/** * @brief DAC MSP Initialization * This function configures the hardware resources used in this example * @param hdac: DAC handle pointer * @retval None */ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hdac->Instance==DAC) { /* Peripheral clock enable */ __HAL_RCC_DAC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**DAC GPIO Configuration PA4 ------> DAC_OUT1 PA5 ------> DAC_OUT2 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* DAC DMA Init */ /* DAC1 Init */ hdma_dac1.Instance = DMA1_Stream5; hdma_dac1.Init.Channel = DMA_CHANNEL_7; hdma_dac1.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_dac1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_dac1.Init.MemInc = DMA_MINC_ENABLE; hdma_dac1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_dac1.Init.Mode = DMA_CIRCULAR; hdma_dac1.Init.Priority = DMA_PRIORITY_LOW; hdma_dac1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_dac1) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hdac,DMA_Handle1,hdma_dac1); /* DAC2 Init */ hdma_dac2.Instance = DMA1_Stream6; hdma_dac2.Init.Channel = DMA_CHANNEL_7; hdma_dac2.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_dac2.Init.PeriphInc = DMA_PINC_DISABLE; hdma_dac2.Init.MemInc = DMA_MINC_ENABLE; hdma_dac2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_dac2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_dac2.Init.Mode = DMA_CIRCULAR; hdma_dac2.Init.Priority = DMA_PRIORITY_LOW; hdma_dac2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_dac2) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hdac,DMA_Handle2,hdma_dac2); } } /** * @brief DAC MSP De-Initialization * This function freeze the hardware resources used in this example * @param hdac: DAC handle pointer * @retval None */ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) { if(hdac->Instance==DAC) { /* Peripheral clock disable */ __HAL_RCC_DAC_CLK_DISABLE(); /**DAC GPIO Configuration PA4 ------> DAC_OUT1 PA5 ------> DAC_OUT2 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_5); /* DAC DMA DeInit */ HAL_DMA_DeInit(hdac->DMA_Handle1); HAL_DMA_DeInit(hdac->DMA_Handle2); } }

 

4、主函数

/** * @brief The application entry point. * @retval int */ int main(void) { /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_DAC_Init(); MX_TIM6_Init(); /* USER CODE BEGIN 2 */ waveform_set(1000, 200); waveform_start(); HAL_Delay(20000); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ waveform_stop(); waveform_set(200, 800); waveform_start(); HAL_Delay(20000); waveform_stop(); waveform_set(1000, 1200); waveform_start(); HAL_Delay(20000); waveform_stop(); waveform_set(4000, 200); waveform_start(); HAL_Delay(20000); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭