OpenEdv-开源电子网

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

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

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-5-6 09:51:26 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-4-30 09:32 编辑

第三十七章 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

本章介绍使用STM32F103的DAC输出指定的电压值。通过本章的学习。读者将学习到DAC的使用。
本章分为如下几个小节:
37.1 硬件设计
37.2 程序设计
37.3 下载验证

37.1 硬件设计
37.1.1 例程功能
1. LCD上不断刷新显示PA4引脚输出电压的数字量、模拟量和PA1引脚输入电压的模拟量
2. 按下WKUP按键可以加大PA4引脚输出的电压,按下KEY0按键可以减小PA4引脚输出的电压
3. LED0闪烁,提示程序正在运行

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

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

37.2 程序设计
37.2.1 HAL库的DAC驱动
本章实验主要使用DAC的Channel1(PA4引脚)输出指定的电压值(0V~3.3V),其具体的步骤如下:
①:初始化DAC
②:配置DAC通道
③:开启DAC转换
④:设置DAC输出值
在HAL库中对应的驱动函数如下:
①:初始化DAC
该函数用于初始化DAC的相关参数,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240430092927.png
表37.2.1.1 函数HAL_DAC_Init()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240430092936.png
表37.2.1.2 函数HAL_DAC_Init()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.    DAC_HandleTypeDef dac_handle = {0};
  5.    
  6.     /* 初始化DAC */
  7.    dac_handle.Instance = DAC;
  8.    HAL_DAC_Init(&dac_handle);
  9. }
复制代码
②:配置DAC通道
该函数用于配置DAC通道,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_DAC_ConfigChannel(   DAC_HandleTypeDef *hdac,
  2.                                              DAC_ChannelConfTypeDef*sConfig,
  3.                                              uint32_t Channel);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240430092945.png
表37.2.1.3 函数HAL_DAC_ConfigChannel()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240430092952.png
表37.2.1.4 函数HAL_DAC_ConfigChannel()返回值描述
该函数使用DAC_ChannelConfTypeDef类型结构体指针传入了DAC通道的配置参数,该结构体的定义如下所示:
  1. typedef struct
  2. {
  3.     uint32_t DAC_Trigger;       /* 外部触发源 */
  4.     uint32_t DAC_OutputBuffer;  /* 输出缓冲 */
  5. }DAC_ChannelConfTypeDef;
复制代码
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.    DAC_ChannelConfTypeDef config = {0};
  5.    
  6.     /* 配置DAC通道 */
  7.    config.DAC_Trigger =DAC_TRIGGER_SOFTWARE;
  8.    config.DAC_OutputBuffer=DAC_OUTPUTBUFFER_DISABLE;
  9.    HAL_DAC_ConfigChannel(&dac_handle, &config);
  10. }
复制代码
③:开启DAC转换
该函数用于开启DAC转换,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240430093001.png
表37.2.1.5 函数HAL_DAC_Start()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240430093009.png
表37.2.1.6 函数HAL_DAC_Start()返回值描述
该函数的使用示例,如下所示:
  1. #include"stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     /* 开启DAC转换 */
  5.     HAL_DAC_Start(&dac_handle, DAC_CHANNEL_1);
  6. }
复制代码
④:设置DAC输出值
该函数用于设置DAC输出值,其函数原型如下所示:
  1. HAL_StatusTypeDef HAL_DAC_SetValue(    DAC_HandleTypeDef *hdac,
  2.                                          uint32_t Channel,
  3.                                          uint32_t Alignment,
  4.                                          uint32_t Data);
复制代码
该函数的形参描述,如下表所示:
QQ截图20240430093018.png
表37.2.1.7 函数HAL_DAC_SetValue()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240430093026.png
表37.2.1.8 函数HAL_DAC_SetValue()返回值描述
该函数的使用示例,如下所示:
  1. #include "stm32f1xx_hal.h"
  2. void example_fun(void)
  3. {
  4.     /* 设置DAC输出值 */
  5.     HAL_DAC_SetValue(&dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 1000);
  6. }
复制代码
37.2.2DAC驱动
本章实验的DAC驱动主要负责向应用层提供DAC的初始化和配置其输出指定电压的函数。本章实验中,DAC的驱动代码包括dac.c和dac.h两个文件。
DAC驱动中,DAC的初始化函数,如下所示:
  1. /**
  2. *@brief   初始化DAC
  3. *@param   无
  4. *@retval  无
  5. */
  6. void dac_init(void)
  7. {
  8.     /* 配置DAC */
  9.    g_dac_handle.Instance = DAC_DACX;
  10.    HAL_DAC_Init(&g_dac_handle);
  11.    HAL_DAC_Start(&g_dac_handle, DAC_DACX_CHY);
  12. }
  13. /**
  14. *@brief   HAL库DAC初始化MSP函数
  15. *@param   hdac: DAC句柄
  16. *@retval  无
  17. */
  18. voidHAL_DAC_MspInit(DAC_HandleTypeDef*hdac)
  19. {
  20.    GPIO_InitTypeDef gpio_init_struct = {0};
  21.    DAC_ChannelConfTypeDef dac_channel_conf_struct = {0};
  22.    
  23.     if (hdac->Instance == DAC_DACX)
  24.     {
  25.          DAC_DACX_CLK_ENABLE();
  26.          DAC_DACX_CHY_GPIO_CLK_ENABLE();
  27.          
  28.          /* 配置DAC输出引脚 */
  29.          gpio_init_struct.Pin = DAC_DACX_CHY_GPIO_PIN;
  30.          gpio_init_struct.Mode = GPIO_MODE_ANALOG;
  31.          gpio_init_struct.Pull = GPIO_NOPULL;
  32.          gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
  33.          HAL_GPIO_Init(DAC_DACX_CHY_GPIO_PORT, &gpio_init_struct);
  34.          
  35.          /* 配置DAC通道 */
  36.          dac_channel_conf_struct.DAC_Trigger = DAC_TRIGGER_NONE;
  37.          dac_channel_conf_struct.DAC_OutputBuffer =DAC_OUTPUTBUFFER_DISABLE;
  38.          HAL_DAC_ConfigChannel( &g_dac_handle,
  39.                                  &dac_channel_conf_struct,
  40.                                  DAC_DACX_CHY);
  41.     }
  42. }
复制代码
从上面的代码中可以看出,DAC的初始化函数会初始化DAC、配置DAC通道并开启DAC转换。
DAC驱动中,配置DAC通道输出指定电压的函数,如下所示:
  1. /**
  2. *@brief   设置DAC输出电压
  3. *@param   voltage: DAC输出电压(扩大1000倍)
  4. *@retval  无
  5. */
  6. voiddac_set_voltage(uint16_t voltage)
  7. {
  8.     uint16_t value;
  9.    
  10.    value = (voltage * 4095) / 3300;
  11.    value &= 0xFFF;
  12.    HAL_DAC_SetValue(&g_dac_handle, DAC_DACX_CHY, DAC_ALIGN_12B_R, value);
  13. }
复制代码
该函数将输入的电压模拟量转换为DAC输出的数字量后,将该值写入指定DAC通道的数据保持寄存器。

37.2.3 实验应用代码
本章实验的应用代码,如下所示:
  1. extern DAC_HandleTypeDef g_dac_handle;
  2. int main(void)
  3. {
  4.     uint8_t t = 0;
  5.     uint8_t key;
  6.     uint16_t dac_value;
  7.     uint16_t dac_voltage = 100;
  8.     uint16_t adc_value;
  9.     uint16_t adc_voltage;
  10.    
  11.    HAL_Init();                         /* 初始化HAL库 */
  12.    sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
  13.    delay_init(72);                     /* 初始化延时 */
  14.    usart_init(115200);                 /* 初始化串口 */
  15.    led_init();                         /* 初始化LED */
  16.    key_init();                         /* 初始化按键 */
  17.    lcd_init();                         /* 初始化LCD */
  18.    adc_init();                         /* 初始化ADC */
  19.    dac_init();                         /* 初始化DAC */
  20.    
  21.    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  22.    lcd_show_string(30, 70, 200, 16, 16, "DACTEST", RED);
  23.    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  24.    
  25.    lcd_show_string(30, 110, 200, 16, 16, "WK_UP:+KEY0:-", RED);
  26.    
  27.    lcd_show_string(30, 130, 200, 16, 16, "DAC_CH1VAL:", BLUE);
  28.    lcd_show_string(30, 150, 200, 16, 16, "DAC_CH1_VOL:0.000V", BLUE);
  29.    lcd_show_string(30, 170, 200, 16, 16, "ADC2_CH1_VOL:0.000V", BLUE);
  30.    
  31.     /* 设置DAC输出电压 */
  32.    dac_set_voltage(dac_voltage);
  33.    
  34.     while (1)
  35.     {
  36.          key = key_scan(0);
  37.          if (key == WKUP_PRES)
  38.          {
  39.              /* 加大DAC输出 */
  40.              if (dac_voltage < 3300)
  41.              {
  42.                  dac_voltage += 100;
  43.                  dac_set_voltage(dac_voltage);
  44.              }
  45.          }
  46.          else if (key == KEY0_PRES)
  47.          {
  48.              /* 减小DAC输出 */
  49.              if (dac_voltage > 100)
  50.              {
  51.                  dac_voltage -= 100;
  52.                  dac_set_voltage(dac_voltage);
  53.              }
  54.          }
  55.          
  56.          if (++t == 20)
  57.          {
  58.              t = 0;
  59.             
  60.              /* 显示DAC输出数字量 */
  61.              dac_value = HAL_DAC_GetValue(&g_dac_handle, DAC_DACX_CHY);
  62.              lcd_show_xnum(126, 130, dac_value, 4, 16, 0, BLUE);
  63.             
  64.              /* 显示DAC输出模拟量 */
  65.              lcd_show_xnum(126, 150, dac_voltage / 1000, 1, 16, 0, BLUE);
  66.              lcd_show_xnum(142, 150, dac_voltage % 1000, 3, 16, 0x80, BLUE);
  67.             
  68.              /* 显示ADC采集模拟量 */
  69.              adc_value = adc_get_result_average(ADC_ADCX_CHY, 10);
  70.              adc_voltage = (adc_value * 3300) / 4095;
  71.              lcd_show_xnum(134, 170, adc_voltage / 1000, 1, 16, 0, BLUE);
  72.              lcd_show_xnum(150, 170, adc_voltage % 1000, 3, 16, 0x80, BLUE);
  73.             
  74.              LED0_TOGGLE();
  75.          }
  76.          
  77.          delay_ms(10);
  78.     }
  79. }
复制代码
可以看到,应用代码中不仅初始化了DAC的Channel1(PA4引脚)同时还使能了ADC2的Channel1(PA1引脚)用于采集DAC Channel1的输出电压。在完成初始化后,便不断地扫描按键并将DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量在LCD上进行显示,此时若扫描到KEY0按键,则减少DAC输出电压的数字量,若扫描到WKUP按键,则增加DAC输出电压的数字量。

37.3 下载验证
在完成编译和烧录操作后,可以看到LCD上实时刷新显示着DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量,此时可以将PA4引脚(DAC Channel1输出引脚)和PA4引脚(ADC Channel1采集引脚)通过杜邦线相连,在按下KEY0或WKUP按键来调整DAC通道1的输出电压,可以看到LCD上显示的DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量也随之变化,并且ADC采集到电压的模拟量也十分接近DAC输出电压的模拟量。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

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

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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