STM32移植RT-Thread实现DAC功能

news2024/11/18 17:32:07
在进行DAC的学习中,发现RT-Thread中没有该外设的驱动,因此需要自己进行相关配置

1.配置RT-Thread Setting中的DAC组件

在这里插入图片描述

2.在HAL库中完成DAC的配置(HAL库起到时钟的作用)

不懂HAL库配置的最好学一下HAL库的编程思想
在这里插入图片描述

3.在board.h中添加宏定义

我的RT-Thread中,没有DAC的宏定义,因此我就在末尾直接添加了一个:#define BSP_USING_DAC1
在这里插入图片描述

4.打开stm32f7xx_hal_config.h文件,接触DAC的注释

在这里插入图片描述

5.DAC驱动代码移植

<1>在/drivers/include/config文件夹下新建dac_config.h

#ifndef __DAC_CONFIG_H__
#define __DAC_CONFIG_H__

#include <rtthread.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef BSP_USING_DAC1
#ifndef DAC1_CONFIG
#define DAC1_CONFIG                                                    \
    {                                                                  \
       .Instance                      = DAC1,                          \
    }
#endif /* DAC2_CONFIG */
#endif /* BSP_USING_DAC2 */

#ifdef BSP_USING_DAC2
#ifndef DAC2_CONFIG
#define DAC2_CONFIG                                                    \
    {                                                                  \
       .Instance                      = DAC2,                          \
    }
#endif /* DAC2_CONFIG */
#endif /* BSP_USING_DAC2 */

#ifdef __cplusplus
}
#endif

#endif /* __DAC_CONFIG_H__ */

<2>修改/drivers/include/drv_config.h
在STM32F1系列下增加#include “config/dac_config.h”,代码如下

#if defined(SOC_SERIES_STM32F0)
#include "config/dma_config.h"
#include "config/uart_config.h"
#include "config/spi_config.h"
#include "config/tim_config.h"
#include "config/pwm_config.h"
#include "config/adc_config.h"
#elif defined(SOC_SERIES_STM32F1)
#include "config/dac_config.h" //新增
#include "config/dma_config.h"
#include "config/uart_config.h"
#include "config/spi_config.h"
#include "config/adc_config.h"
#include "config/tim_config.h"
#include "config/sdio_config.h"
#include "config/pwm_config.h"
#include "config/usbd_config.h"
#include "config/pulse_encoder_config.h"

<3>在drivers文件夹下新建drv_dac.c

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author            Notes
 * 2020-06-18     thread-liu        the first version
 * 2020-10-09     thread-liu   Porting for stm32h7xx
 */

#include <board.h>
#include<rtthread.h>
#include<rtdevice.h>

#if defined(BSP_USING_DAC1) || defined(BSP_USING_DAC2)
#include "drv_config.h"

//#define DRV_DEBUG
#define LOG_TAG             "drv.dac"
#include <drv_log.h>

static DAC_HandleTypeDef dac_config[] =
{
#ifdef BSP_USING_DAC1
    DAC1_CONFIG,
#endif

#ifdef BSP_USING_DAC2
    DAC2_CONFIG,
#endif
};

struct stm32_dac
{
    DAC_HandleTypeDef DAC_Handler;
    struct rt_dac_device stm32_dac_device;
};

static struct stm32_dac stm32_dac_obj[sizeof(dac_config) / sizeof(dac_config[0])];

static rt_uint32_t stm32_dac_get_channel(rt_uint32_t channel)
{
    rt_uint32_t stm32_channel = 0;

    switch (channel)
    {
    case  1:
        stm32_channel = DAC_CHANNEL_1;
        break;
    case  2:
        stm32_channel = DAC_CHANNEL_2;
        break;
    default:
        RT_ASSERT(0);
        break;
    }

    return stm32_channel;
}

static rt_err_t stm32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
{
    uint32_t dac_channel;
    DAC_HandleTypeDef *stm32_dac_handler;
    RT_ASSERT(device != RT_NULL);
    stm32_dac_handler = device->parent.user_data;

#if 1
    if ((channel <= 2) && (channel > 0))
    {
        /* set stm32 dac channel */
        dac_channel =  stm32_dac_get_channel(channel);
    }
    else
    {
      LOG_E("dac channel must be 1 or 2.");
      return -RT_ERROR;
    }
    HAL_DAC_Start(stm32_dac_handler, dac_channel);
#endif

    return RT_EOK;
}

static rt_err_t stm32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
{
    uint32_t dac_channel;
    DAC_HandleTypeDef *stm32_dac_handler;
    RT_ASSERT(device != RT_NULL);
    stm32_dac_handler = device->parent.user_data;

#if 1
    if ((channel <= 2) && (channel > 0))
    {
        /* set stm32 dac channel */
        dac_channel =  stm32_dac_get_channel(channel);
    }
    else
    {
      LOG_E("dac channel must be 1 or 2.");
      return -RT_ERROR;
    }
    HAL_DAC_Stop(stm32_dac_handler, dac_channel);
#endif

    return RT_EOK;
}

static rt_err_t stm32_set_dac_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
    uint32_t dac_channel;
    DAC_ChannelConfTypeDef DAC_ChanConf;
    DAC_HandleTypeDef *stm32_dac_handler;

    RT_ASSERT(device != RT_NULL);
    RT_ASSERT(value != RT_NULL);

    stm32_dac_handler = device->parent.user_data;

    rt_memset(&DAC_ChanConf, 0, sizeof(DAC_ChanConf));

#if 1
    if ((channel <= 2) && (channel > 0))
    {
        /* set stm32 dac channel */
        dac_channel =  stm32_dac_get_channel(channel);
    }
    else
    {
      LOG_E("dac channel must be 1 or 2.");
      return -RT_ERROR;
    }
#endif

#if 1
    DAC_ChanConf.DAC_Trigger      = DAC_TRIGGER_NONE;
    DAC_ChanConf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
#endif
    /* config dac out channel*/
    if (HAL_DAC_ConfigChannel(stm32_dac_handler, &DAC_ChanConf, dac_channel) != HAL_OK)
    {
        LOG_D("Config dac out channel Error!\n");
        return -RT_ERROR;
    }
    /* set dac channel out value*/
    if (HAL_DAC_SetValue(stm32_dac_handler, dac_channel, DAC_ALIGN_12B_R, *value) != HAL_OK)
    {
        LOG_D("Setting dac channel out value Error!\n");
        return -RT_ERROR;
    }
    /* start dac */
    if (HAL_DAC_Start(stm32_dac_handler, dac_channel) != HAL_OK)
    {
        LOG_D("Start dac Error!\n");
        return -RT_ERROR;
    }

    return RT_EOK;
}

static const struct rt_dac_ops stm_dac_ops =
{
    .disabled = stm32_dac_disabled,
    .enabled  = stm32_dac_enabled,
    .convert  = stm32_set_dac_value,
};

static int stm32_dac_init(void)
{
    int result = RT_EOK;
    /* save dac name */
    char name_buf[5] = {'d', 'a', 'c', '0', 0};
    int i = 0;

    for (i = 0; i < sizeof(dac_config) / sizeof(dac_config[0]); i++)
    {
        /* dac init */
        name_buf[3] = '0';
        stm32_dac_obj[i].DAC_Handler = dac_config[i];
#if defined(DAC1)
        if (stm32_dac_obj[i].DAC_Handler.Instance == DAC1)
        {
            name_buf[3] = '1';
        }
#endif
#if defined(DAC2)
        if (stm32_dac_obj[i].dac_Handler.Instance == DAC2)
        {
            name_buf[3] = '2';
        }
#endif
        if (HAL_DAC_Init(&stm32_dac_obj[i].DAC_Handler) != HAL_OK)
        {
            LOG_E("%s init failed", name_buf);
            result = -RT_ERROR;
        }
        else
        {
            /* register dac device */
            if (rt_hw_dac_register(&stm32_dac_obj[i].stm32_dac_device, name_buf, &stm_dac_ops, &stm32_dac_obj[i].DAC_Handler) == RT_EOK)
            {
                LOG_D("%s init success", name_buf);
            }
            else
            {
                LOG_E("%s register failed", name_buf);
                result = -RT_ERROR;
            }
        }
    }

    return result;
}
INIT_DEVICE_EXPORT(stm32_dac_init);

#endif /* BSP_USING_DAC */

运行代码

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define DAC_DEV_NAME        "dac1"  /* DAC 设备名称 */
#define DAC_DEV_CHANNEL     1       /* DAC 通道 */
rt_dac_device_t dac_dev;
#define REFER_VOLTAGE       330         /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS        (1 << 12)   /* 转换位数为12位 */

void dac_set_vol(rt_uint32_t vol)//1000->1V
{
    rt_uint32_t value;
    double temp=vol;
    temp=temp/1000;
    temp=temp*4095/3.3;
    value=temp;
    rt_dac_write(dac_dev, DAC_DEV_CHANNEL, vol);
}

int main(void)
{
    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);

    //设置输出值
    dac_set_vol(300);

    //关闭通道  这里的disable也关闭了,貌似用不了,是不是可以用HAL库的呢?
    //ret = rt_dac_disable(dac_dev, DAC_DEV_CHANNEL);

    return ret;
}

最后

RT-Thread中存在着部分外设没有驱动程序需要我们自己去移植,或者使用HAL库的编程思想去实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2178471.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于分箱的一些介绍

在这篇文章中&#xff0c;我将介绍一种数据预处理的技术——分箱&#xff0c;然会将会从概念、步骤、分类、应用场景、注意事项与实际操作等方面去介绍它。 一、概念 分箱&#xff08;Binning&#xff09;是一种数据预处理技术&#xff0c;在数据分析和机器学习中经常使用。它…

Java8 用流收集数据之归约汇总

目录 规约汇总最大值 (max)・最小值 (min)统计总数 (count)统计求和 (summingInt・summingLong・summingDouble・sum&#xff09;平均值 (averagingInt・averagingLong・averagingInt・average&#xff09;统计梗概 (summarizingInt・summarizingLong・summarizingDouble・summ…

AI周报(9.22-9.28)

AI应用-Siipet宠物沟通师 Siipet是一款由SiiPet公司推出的创新宠物行为分析相机&#xff0c;旨在通过尖端技术加深宠物与主人之间的情感联系。这款相机利用先进的AI算法&#xff0c;能够自动识别和分析家中宠物的行为&#xff0c;并提供定制化的护理建议。 SiiPet相机的核心功…

益而益集团荣获2024年江苏省智能制造车间称号

近日&#xff0c;江苏省工信厅公示2024年江苏省智能制造车间名单&#xff0c;苏州益而益电器制造有限公司以其卓越的智能化转型成果&#xff0c;荣获2024年度江苏省级智能制造车间称号。 此次获评&#xff0c;是江苏省政府对益而益集团智能化高质量转型发展的认可及肯定&#…

活动在线报名小程序源码系统 自主提交表单+创建表单 带完整的安装代码包以及搭建部署教程

系统概述 随着各类活动的日益丰富和多样化&#xff0c;传统的报名方式逐渐显现出其局限性。纸质报名表格繁琐易错、人工统计费时费力&#xff0c;难以满足现代活动管理的需求。因此&#xff0c;开发一款集自主提交表单和创建表单功能于一体的活动在线报名小程序源码系统成为必…

mit6824-01-MapReduce详解

文章目录 MapReduce简述编程模型执行流程执行流程排序保证Combiner函数Master数据结构 容错性Worker故障Master故障 性能提升定制分区函数局部性执行缓慢的worker(slow workers) 常见问题总结回顾参考链接 MapReduce简述 MapReduce是一个在多台机器上并行计算大规模数据的软件架…

C++进阶知识2 多态

多态 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.1.2 虚函数2.1.3 虚函数的重写/覆盖2.1.5 虚函数重写的⼀些其他问题2.1.6 override和final关键字2.1.7 重载/重写/隐藏的对⽐ 3. 多态的原理3.2 多态的原理3.2.1 多态是如何实现的3.2.2 动态绑定与静态绑定3.2.3 虚函…

828华为云征文|部署在线文档应用程序 CodeX Docs

828华为云征文&#xff5c;部署在线文档应用程序 CodeX Docs 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 CodeX Docs3.1 CodeX Docs 介绍3.2 CodeX Docs 部署3.3 CodeX…

SpringBoot整合JPA 基础使用

一、什么是JPA ‌‌1.JPA的定义和基本概念‌‌ ‌JPA&#xff08;Java Persistence API&#xff09;‌是Java中用于进行持久化操作的一种规范&#xff0c;它定义了一系列用于操作关系型数据库的API接口。通过这些接口&#xff0c;开发人员可以方便地进行数据库的增删改查等操…

ArcgisEngine开发中,Ifeatureclass.Addfield 报错0x80040655处理方法

1、ArcgisEngine开发中&#xff0c;Ifeatureclass.Addfield 报错0x80040655。如下图所示。 2、经分析&#xff0c;这是由于字段类型错误&#xff0c;经检查&#xff0c;是由于字段名为中文名&#xff0c;超出shp格式的最大字段长度量&#xff0c;看资料说是5个中文字符&#xf…

fastadmin 搜索提交重置按钮文本修改

默认 修改require-backend.min.js文件 效果 当然最好还是去需修改lang文件 效果 如果修改没生效记得清楚一下缓存&#xff0c;再刷新 完结 赠人玫瑰&#xff0c;手有余香&#xff01;如果文章内容对你有所帮助&#xff0c;请不要吝啬你的点赞评论和关注&#xff0c;你…

校园跑腿系统二手市场校园搭子校园社团活动系统2000的和4800的有什么区别

校园跑腿系统、二手市场、校园搭子、校园社团活动系统在不同价格档位&#xff08;如2000元和4800元&#xff09;之间可能存在多方面的区别&#xff0c;这些区别主要体现在功能丰富性、技术支持、用户体验、定制化程度以及后续服务等方面。然而&#xff0c;由于具体的价格差异和…

TDengine 流计算与窗口机制的深度解析:揭示计数窗口的关键作用

在 TDengine 3.2.3.0 版本中&#xff0c;我们针对流式计算新增了计数窗口&#xff0c;进一步优化了流式数据处理的能力。本文将为大家解读流式计算与几大窗口的关系&#xff0c;并针对新增的计数窗口进行详细的介绍&#xff0c;帮助大家进一步了解 TDengine 流式计算&#xff0…

趣味SQL | 从围棋收官到秦楚大战的数据库SQL实现(下)

目录 0 上集回顾 1 双先量化&#xff0c;得失权衡 2 各守城池&#xff0c;妥协攻守 3 SQL演算&#xff0c;三策评详 4 寸土必争&#xff0c;利益倍增 5 SQL再演&#xff0c;策略精进 6 棋道相通&#xff0c;治国有术 如果觉得本文对你有帮助&#xff0c;那么不妨也可…

这是我见过最强的AI大模型教程书籍!免费白嫖,可以上车!!

这是LLM入门级书籍&#xff0c;共145页&#xff0c;主要介绍了大型语言模型&#xff08;LLM&#xff09;的基本原理和底层技术。 阅读本书&#xff0c;您将能够掌握 LLM 的基本概念&#xff0c;了解自然语言处理&#xff08;NLP&#xff09;的发展历程&#xff0c;理解 Transf…

家中浮毛太多怎么办?希喂、米家、安德迈更推荐哪款?

在现代养宠家庭生活中&#xff0c;宠物空气净化器已经成为不可或缺的家电之一。 而在众多空气净化器类型中&#xff0c;宠物空气净化器以其独特的设计和卓越的净化效果&#xff0c;逐渐赢得了越来越多养宠家庭的青睐。 它不仅能有效地吸附空中飞舞的浮毛&#xff0c;还能高效…

召回10 Deep Retrieval召回

Deep Retrieval召回&#xff1a;给定用户特征采用beam search算法召回路径&#xff0c;根据路径召回物品&#xff0c;对物品排序&#xff0c;最终用分数高的物品作为召回结果。 双塔模型是将向量表征作为用户和物品之间的中介。 Deep Retrieval是将路径作为用户和物品之间的中介…

基于Java+VUE+echarts大数据智能道路交通信息统计分析管理系统的设计与实现

大数据智能交通管理系统是一种基于Web的系统架构&#xff0c;通过浏览器/服务器&#xff08;B/S&#xff09;模式实现对城市交通数据的高效管理和智能化处理。该系统旨在通过集成各类交通数据&#xff0c;包括但不限于车辆信息、行驶记录、违章情况等&#xff0c;来提升城市管理…

场地预约系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;场地类型管理&#xff0c;场地信息管理&#xff0c;我的预约管理&#xff0c;场地使用管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;场地信息&#xff0c;我的预约&a…

简易CPU设计入门:取指令(三),ip_buf与rd_en的非阻塞赋值

在开篇&#xff0c;还是请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&…