本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用DAC设备。硬件及开发环境如下:
打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习(一)使用外部时钟系统》。
RT-Thread Setting
中借助图形化配置工具打开软件DAC的驱动框架,如下图所示board.h
文件末尾添加:/*-------------------------- DAC CONFIG BEGIN --------------------------*/
/** if you want to use dac you can use the following instructions.
*
* STEP 1, open dac driver framework support in the RT-Thread Settings file
*
* STEP 2, define macro related to the dac
* such as #define BSP_USING_DAC1
*
* STEP 3, copy your dac init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
* such as void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
*
* STEP 4, modify your stm32xxxx_hal_config.h file to support dac peripherals. define macro related to the peripherals
* such as #define HAL_DAC_MODULE_ENABLED
*
*/
#define BSP_USING_DAC1
/*-------------------------- DAC CONFIG END --------------------------*/
HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
复制到board.c的末尾。void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(dacHandle->Instance==DAC)
{
/* USER CODE BEGIN DAC_MspInit 0 */
/* USER CODE END DAC_MspInit 0 */
/* DAC 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);
/* USER CODE BEGIN DAC_MspInit 1 */
/* USER CODE END DAC_MspInit 1 */
}
}
.\cubemx\Inc\stm32f4xx_hal_conf.h
中的相关宏#define HAL_DAC_MODULE_ENABLED
修改main.c
的代码为:
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-15 RT-Thread first version
*/
#include <rtthread.h>
#include "stm32f4xx.h"
#include <rtdevice.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
// PA4 ------> DAC_OUT1
// PA5 ------> DAC_OUT2
DAC_HandleTypeDef hdac;
#define DAC_DEV_NAME "dac1" /* DAC 设备名称 */
#define DAC_DEV_CHANNEL 1 /* DAC 通道 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
// 设置dac的使用命令 dac_set dac1 1 200
// 第一个参数为命令,第二个参数为 dac 设备名称,第 3 个参数为 dac 通道,
// 第 4 个参数为 dac 输出数值
static int dac_set(int argc, char *argv[])
{
if(argc!=4)
{
rt_kprintf("Usage: dac_set <device name> <channel> <value>\n");
rt_kprintf("Example: dac_set dac1 1 1000\n");
return RT_ERROR;
}
rt_dac_device_t dac_dev;
rt_uint32_t value, vol, channel;
rt_err_t ret = RT_EOK;
char dacdevname[RT_NAME_MAX];
rt_strncpy(dacdevname, argv[1], RT_NAME_MAX);
channel = atoi(argv[2]); // DAC channel
value = atoi(argv[3]);
/* 查找设备 */
dac_dev = (rt_dac_device_t)rt_device_find(dacdevname);
if (dac_dev == RT_NULL)
{
rt_kprintf("dac sample run failed! can't find %s device!\n", dacdevname);
return RT_ERROR;
}
/* 打开通道 */
ret = rt_dac_enable(dac_dev, channel);
/* 设置输出值 */
rt_dac_write(dac_dev, channel, value);
rt_kprintf("the value is :%d \n", value);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/* 延时查看效果,关闭通道后无输出 */
// rt_thread_mdelay(500);
/* 关闭通道 */
// ret = rt_dac_disable(dac_dev, channel);
return ret;
}
static int dac1_vol_sample()
{
rt_dac_device_t dac_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;
/* 查找设备 */
dac_dev = (rt_dac_device_t)rt_device_find(DAC_DEV_NAME);
if (dac_dev == RT_NULL)
{
rt_kprintf("dac sample run failed! can't find %s device!\n", DAC_DEV_NAME);
return RT_ERROR;
}
/* 打开通道 */
ret = rt_dac_enable(dac_dev, DAC_DEV_CHANNEL);
/* 设置输出值 */
value=1000;
rt_dac_write(dac_dev, DAC_DEV_CHANNEL, value);
rt_kprintf("the value is :%d \n", value);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/* 延时查看效果,关闭通道后无输出 */
// rt_thread_mdelay(500);
/* 关闭通道 */
// ret = rt_dac_disable(dac_dev, DAC_DEV_CHANNEL);
return ret;
}
int main(void)
{
int count = 1;
LOG_D("Hello RT-Thread! 2024.1.17");
LOG_D("System CLock information");
LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());
LOG_D("HCLK_Frequency = %d", HAL_RCC_GetHCLKFreq());
LOG_D("PCLK1_Frequency = %d", HAL_RCC_GetPCLK1Freq());
LOG_D("PCLK2_Frequency = %d", HAL_RCC_GetPCLK2Freq());
LOG_D("SysTick->LOAD = %d", SysTick->LOAD);
LOG_D("Current tick = %d", rt_tick_get());
dac1_vol_sample();
while (count++)
{
LOG_D("Hello RT-Thread! %d", rt_tick_get());
rt_thread_mdelay(60000);
}
return RT_EOK;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(dac_set, set dac voltage. Useage: dac_set adc1 1 200);
运行结果如下:
在PA4和PA5脚用万用表测得输出电压为0.8082V
不需要在board.h
中添加#define BSP_USING_DAC2
宏定义,因为dac1
的通道2就是dac2
。