OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 644|回复: 0

《M144Z-M3最小系统板使用指南——STM32F103版》第三十九章 DAC输出正弦波实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-5-8 17:06:59 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-5-7 10:02 编辑

第三十九章 DAC输出正弦波实验
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板

2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boar ... _mini_sysboard.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32技术交流QQ群:725095144

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章将使用TIM7的更新事件用于TRGO触发DAC Channel1输出DMA1 Stream5 Channel7从使用软件算法生成的正弦波数据,以输出正弦波。通过本章的学习,读者将学习到DAC、TIM、DMA的使用。
本章分为如下几个小节:
39.1 硬件设计
39.2 程序设计
39.3 下载验证

39.1 硬件设计
39.1.1 例程功能
1. 按下WKUP按键,PA4引脚输出正弦波1(幅值3.3V,频率1KHz,采样点100)
2. 按下KEY0按键,PA4引脚输出正弦波2(幅值3.3V,频率10KHz,采样点10)
3. LED0闪烁,提示程序正在运行

39.1.2 硬件资源
1. LED
       LED0 - PB5
2. 正点原子2.8/3.5/4.3/7/10寸TFTLCD模块
3. 按键
       WKUP - PA0
       KEY0 - PE4
4. DAC
       Channel1 - PA4
5. DMA1
       Stream5 Channel7
6. TIM7

39.1.3 原理图
本章实验使用的DAC为STM32F103的片上资源,因此没有对应的连接原理图。

39.2 程序设计
39.2.1 HAL库的TIM驱动
本章实验中将使用TIM7的更新事件产生TRGO事件,该TRGO事件将用于触发DAC,其具体的步骤如下:
①:初始化TIM
②:配置TIM主模式
在HAL库中对应的驱动函数如下:
①:初始化TIM
请见第16.2.1小节中初始化TIM的相关章节。
②:配置TIM主模式
该函数用于配置TIM的主模式,其函数原型如下所示:
  1. HAL_StatusTypeDefHAL_TIMEx_MasterConfigSynchronization(
  2.                                          TIM_HandleTypeDef*htim,
  3.                                          TIM_MasterConfigTypeDef*sMasterConfig);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240507100047.png
表39.2.1.1 函数HAL_TIMEx_MasterConfigSynchronization()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240507100055.png
表39.2.1.2 函数HAL_TIMEx_MasterConfigSynchronization()返回值描述
该函数使用TIM_MasterConfigTypeDef类型结构体指针传入了TIM主模式的配置参数,该结构体的定义如下所示:
  1. typedef struct
  2. {
  3.     uint32_tMasterOutputTrigger;   /* 触发输出选择 */
  4.     uint32_t MasterSlaveMode;       /* 主从模式 */
  5. }TIM_MasterConfigTypeDef;
复制代码
该函数的使用示例,如下所示:
  1. #include"stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     TIM_MasterConfigTypeDef config = {0};
  5.    
  6.     /* 配置TIM主模式 */
  7.     config.MasterOutputTrigger= TIM_TRGO_RESET;
  8.     config.MasterSlaveMode =TIM_MASTERSLAVEMODE_ENABLE;
  9.    HAL_TIMEx_MasterConfigSynchronization(&tim_handle, &config);
  10. }
复制代码

39.2.2 HAL库的DAC驱动
本章实验与第四十章一样,使用DAC通道1(PA4引脚)输出电压,不同之处在于,本章使用使用DMA自动将DAC通道1待输出的数据写入DAC的数据保持寄存器,以输出正弦波。其中对DAC的操作请见第四十章中HAL库的DAC驱动的相关内容,本小节仅介绍DAC使用DMA的相关步骤,其具体的步骤如下:
①:开启DAC DMA转换
在HAL库中对应的驱动函数如下:
①:开启DAC DMA转换
该函数用于开启DAC DMA转换,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_DAC_Start_DMA(   DAC_HandleTypeDef *hdac,
  2.                                          uint32_t Channel,
  3.                                          uint32_t *pData,
  4.                                          uint32_t Length,
  5.                                          uint32_t Alignment);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240507100112.png
表39.2.2.1 函数()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240507100122.png
表39.2.2.2 函数()返回值描述
该函数的使用示例,如下所示:
  1. #include"stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     uint16_t buf;
  5.    
  6.     /* 开启DAC DMA传输 */
  7.     HAL_DAC_Start_DMA(&dac_handle,
  8.     DAC_CHANNEL_1,
  9.     buf,
  10.     sizeof(buf) / sizeof(buf),
  11.     DAC_ALIGN_12B_R);
  12. }
复制代码

39.2.3DAC驱动
本章实验的DAC驱动主要负责向应用层提供DAC的初始化和使能DAC输出指定幅值、频率的正弦波。本章实验中,DAC的驱动代码包括dac.c和dac.h两个文件。
DAC驱动中,DAC的初始化函数,如下所示:
  1. /**
  2. *@brief   初始化DAC DMA波形输出
  3. *@param   无
  4. *@retval  无
  5. */
  6. voiddac_dma_wave_init(void)
  7. {
  8.     /* 配置DAC */
  9.    g_dac_dma_handle.Instance = DAC_DMA_DACX;
  10.    HAL_DAC_Init(&g_dac_dma_handle);
  11. }
  12. /**
  13. *@brief   HAL库DAC初始化MSP函数
  14. *@param   hdac: DAC句柄
  15. *@retval  无
  16. */
  17. voidHAL_DAC_MspInit(DAC_HandleTypeDef*hdac)
  18. {
  19.    GPIO_InitTypeDef gpio_init_struct = {0};
  20.    DAC_ChannelConfTypeDef dac_channel_conf_struct = {0};
  21.    TIM_MasterConfigTypeDef tim_master_config_struct = {0};
  22.    
  23.     if (hdac->Instance == DAC_DMA_DACX)
  24.     {
  25.          DAC_DMA_DACX_CLK_ENABLE();
  26.          DAC_DMA_DACX_CHY_GPIO_CLK_ENABLE();
  27.          DAC_DMA_DACX_DMA_CLK_ENABLE();
  28.          DAC_DMA_DACX_TIMX_CLK_ENABLE();
  29.          
  30.          /* 配置DAC输出引脚 */
  31.          gpio_init_struct.Pin = DAC_DMA_DACX_CHY_GPIO_PIN;
  32.          gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  33.          gpio_init_struct.Pull = GPIO_NOPULL;
  34.          gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
  35.          HAL_GPIO_Init(DAC_DMA_DACX_CHY_GPIO_PORT, &gpio_init_struct);
  36.          
  37.          /* 配置DAC通道 */
  38.          dac_channel_conf_struct.DAC_Trigger =DAC_TRIGGER_T7_TRGO;
  39.          dac_channel_conf_struct.DAC_OutputBuffer =DAC_OUTPUTBUFFER_DISABLE;
  40.          HAL_DAC_ConfigChannel(hdac, &dac_channel_conf_struct, DAC_DMA_DACX_CHY);
  41.          
  42.          /* 配置DMA */
  43.          g_dac_dma_dma_handle.Instance = DAC_DMA_DACX_DMACX;
  44.          g_dac_dma_dma_handle.Init.Direction =DMA_MEMORY_TO_PERIPH;
  45.          g_dac_dma_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;
  46.          g_dac_dma_dma_handle.Init.MemInc = DMA_MINC_ENABLE;
  47.          g_dac_dma_dma_handle.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
  48.          g_dac_dma_dma_handle.Init.MemDataAlignment =DMA_MDATAALIGN_HALFWORD;
  49.          g_dac_dma_dma_handle.Init.Mode = DMA_CIRCULAR;
  50.          g_dac_dma_dma_handle.Init.Priority = DMA_PRIORITY_VERY_HIGH;
  51.          HAL_DMA_Init(&g_dac_dma_dma_handle);
  52.          
  53.          __HAL_LINKDMA(hdac, DMA_Handle1, g_dac_dma_dma_handle);
  54.          
  55.          HAL_NVIC_SetPriority(DAC_DMA_DACX_DMACX_IRQn, 0, 0);
  56.          HAL_NVIC_EnableIRQ(DAC_DMA_DACX_DMACX_IRQn);
  57.          
  58.          /* 配置TIM */
  59.          g_dac_dma_tim_handle.Instance = DAC_DMA_DACX_TIMX;
  60.          HAL_TIM_Base_Init(&g_dac_dma_tim_handle);
  61.          
  62.          tim_master_config_struct.MasterOutputTrigger=TIM_TRGO_UPDATE;
  63.          HAL_TIMEx_MasterConfigSynchronization( &g_dac_dma_tim_handle,
  64.                                                  &tim_master_config_struct);
  65.     }
  66. }
复制代码
可以看到本章实验DAC驱动中的DAC初始化函数与第三十九章“DAC输出实验”中对DAC的初始化基本一致,不过本章配置DAC Channel1的触发源为TIM7的TRGO事件,同时还配置了DMA。
DAC驱动中使能DAC输出指定幅值、频率的正弦波的函数,如下所示:
  1. /**
  2. *@brief   使能DAC DMA波形输出
  3. *@param   ndtr: DMA数据流传输一次数据项的数目
  4. *@param   arr: DAC触发定时器的自动重装载值
  5. *@param   psc: DAC触发定时器的预分频器数值
  6. *@retval  无
  7. */
  8. voiddac_dma_wave_enable(uint16_t ndtr, uint16_t arr, uint16_t psc)
  9. {
  10.     /* 配置TIM */
  11.    g_dac_dma_tim_handle.Init.Prescaler = psc;
  12.    g_dac_dma_tim_handle.Init.Period = arr;
  13.    HAL_TIM_Base_Init(&g_dac_dma_tim_handle);
  14.    HAL_TIM_Base_Start(&g_dac_dma_tim_handle);
  15.    
  16.     /* 重新开启DAC DMA传输 */
  17.    HAL_DAC_Stop_DMA(&g_dac_dma_handle, DAC_DMA_DACX_CHY);
  18.    HAL_DAC_Start_DMA(  &g_dac_dma_handle,
  19.                          DAC_DMA_DACX_CHY,
  20.                          (uint32_t *)g_dac_sin_buf,
  21.                          ndtr,
  22.                          DAC_ALIGN_12B_R);
  23. }
复制代码
该函数配置了TIM7的溢出频率,因此TIM7的溢出频率就决定了DAC输出正弦波的频率,同时也开启了DAC DMA传输。

39.2.4 实验应用代码
本章实验的应用代码,如下所示:
  1. /* 正弦波数据缓冲区 */
  2. uint16_t g_dac_sin_buf[4096];
  3. /**
  4. *@brief   生成正弦数据
  5. *@param   maxval : 正弦的振幅
  6. *@param   samples: 正弦一个周期的采样点个数
  7. *@retval  无
  8. */
  9. static voiddac_creat_sin_buf(uint16_t maxval, uint16_t samples)
  10. {
  11.     uint16_t i;
  12.     double w;
  13.     uint16_t outdata;
  14.    
  15.     w = (2 * 3.1415926) / samples;                      /* ω=2π/T */
  16.    
  17.     for (i=0; i<samples; i++)
  18.     {
  19.          outdata = maxval * sin(w * i + 0) + maxval;    /* y=Asin(ωx+φ)+b */
  20.          if (outdata > 4095)                            /* 限制上限 */
  21.          {
  22.              outdata = 4095;
  23.          }
  24.          g_dac_sin_buf = outdata;
  25.     }
  26. }
  27. int main(void)
  28. {
  29.     uint8_t t = 0;
  30.     uint8_t key;
  31.    
  32.    HAL_Init();                             /* 初始化HAL库 */
  33.    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 配置时钟,72MHz */
  34.    delay_init(72);                         /* 初始化延时 */
  35.    usart_init(115200);                     /* 初始化串口 */
  36.    led_init();                             /* 初始化LED */
  37.    key_init();                             /* 初始化按键 */
  38.    lcd_init();                             /* 初始化LCD */
  39.    dac_dma_wave_init();                        /* 初始化DAC DMA波形输出 */
  40.    dac_creat_sin_buf(2048 - 1, 100);           /* 生成正弦数据 */
  41.    dac_dma_wave_enable(100, 10 - 1, 72 - 1);  /* 使能DAC DMA波形输出 */
  42.    
  43.    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  44.    lcd_show_string(30, 70, 200, 16, 16, "DAC DMASine Wave TEST", RED);
  45.    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  46.    
  47.    lcd_show_string(30, 110, 200, 16, 16, "WK_UP:Wave1KEY0:Wave2", RED);
  48.    
  49.     while (1)
  50.     {
  51.          key = key_scan(0);
  52.          if (key == WKUP_PRES)
  53.          {
  54.              /* 生成正弦数据 */
  55.              dac_creat_sin_buf(2048 - 1, 100);
  56.              /* 使能DAC DMA波形输出 */
  57.              dac_dma_wave_enable(100, 10 - 1, 72 - 1);
  58.          }
  59.          else if (key == KEY0_PRES)
  60.          {
  61.              /* 生成正弦数据 */
  62.              dac_creat_sin_buf(2048 - 1, 10);
  63.              /* 使能DAC DMA波形输出 */
  64.              dac_dma_wave_enable(10, 10 - 1, 72 - 1);
  65.          }
  66.          
  67.          if (++t == 20)
  68.          {
  69.              t = 0;
  70.              LED0_TOGGLE();
  71.          }
  72.          
  73.          delay_ms(10);
  74.     }
  75. }
复制代码
可以看到,在实验应用代码中,定义了函数dac_creat_sin_buf(),该函数用于生成正弦波数据,并保存至数组g_dac_sin_buf中。在完成DAC初始化后,便生成了一组正弦波数据,并调用函数dac_dma_wave_enable()使能DAC Channel1输出指定的正弦波,随后便通过扫描到的不同按键值,输出不同频率的正弦波。

39.3 下载验证
在完成编译和烧录操作后,便可分别按下KEY0按键和WKUP按键控制DAC Channel1输出不同类型的正弦波,DAC Channel1输出的正弦波可通过示波器观察PA4引脚(DAC Channel1输出引脚)看到。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 00:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表