RT-Thread Studio学习(十四)ADC

news2024/11/25 13:17:37

RT-Thread Studio学习(十四)ADC

  • 一、简介
  • 二、新建RT-Thread项目并使用外部时钟
  • 三、启用ADC
  • 四、测试

一、简介

本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用ADC设备。硬件及开发环境如下:

  • OS WIN10
  • STM32F407VET6
  • STM32CubeMX v6.10.0
  • STM32Cube MCU Package for STM32F4 Series v1.28.0
  • RT-Thread Studio v2.2.7
  • RT-Thread Source Code v5.0.2
  • STM32F4 chip support packages v0.2.3

二、新建RT-Thread项目并使用外部时钟

打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习(一)使用外部时钟系统》。

三、启用ADC

  1. 打开ADC驱动框架
    RT-Thread Setting 中借助图形化配置工具打开软件ADC的驱动框架,如下图所示:
    在这里插入图片描述
  2. 定义ADC相关的宏
    board.h文件中使能宏定义:
#define BSP_USING_ADC1
#define BSP_USING_ADC2
#define BSP_USING_ADC3
  1. 复制ADC初始化函数
    双击RT-Thread Studio工程中的cubemx.ioc文件,使能ADC1、ADC2和ADC3,具体如下图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    3个ADC分别对应引脚PC0、PC1和PC2。

使能ADC后再重新生成STM32CubeMX代码,将.\cubemx\Src\adc.c中的函数HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)复制到board.c的末尾。

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */
    /* ADC1 clock enable */
    __HAL_RCC_ADC1_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PC0     ------> ADC1_IN10
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
  else if(adcHandle->Instance==ADC2)
  {
  /* USER CODE BEGIN ADC2_MspInit 0 */

  /* USER CODE END ADC2_MspInit 0 */
    /* ADC2 clock enable */
    __HAL_RCC_ADC2_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**ADC2 GPIO Configuration
    PC1     ------> ADC2_IN11
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC2_MspInit 1 */

  /* USER CODE END ADC2_MspInit 1 */
  }
  else if(adcHandle->Instance==ADC3)
  {
  /* USER CODE BEGIN ADC3_MspInit 0 */

  /* USER CODE END ADC3_MspInit 0 */
    /* ADC3 clock enable */
    __HAL_RCC_ADC3_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**ADC3 GPIO Configuration
    PC2     ------> ADC3_IN12
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC3_MspInit 1 */

  /* USER CODE END ADC3_MspInit 1 */
  }
}
  1. 定义.\cubemx\Inc\stm32f4xx_hal_conf.h中的相关宏
#define HAL_ADC_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>

// PC0     ------> ADC1_IN10
// PC1     ------> ADC2_IN11
// PC2     ------> ADC3_IN12
// PA4     ------> DAC_OUT1
// PA5     ------> DAC_OUT2

#define ADC_DEV_NAME        "adc1"      /* ADC 设备名称 */
#define REFER_VOLTAGE       330         /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS        (1 << 12)   /* 转换位数为12位 */

#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位 */


// 读取adc的使用命令get_adc adc1 1
// 第一个参数为命令,第二个参数为 adc 设备名称,第 3 个参数为 adc 通道,
// 返回值为 adc 电压值
static int adc_get(int argc, char *argv[])
{
    if(argc!=3)
    {
        rt_kprintf("Usage:    adc_get <device name> <channel>\n");
        rt_kprintf("Example:  adc_get adc1 1\n");
        return RT_ERROR;
    }
    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol, channel;
    rt_err_t ret = RT_EOK;
    char adcdevname[RT_NAME_MAX];

    rt_strncpy(adcdevname, argv[1], RT_NAME_MAX);
    channel = atoi(argv[2]);  // ADC channel

    /* 查找设备 */
    adc_dev = (rt_adc_device_t)rt_device_find(adcdevname);
    if (adc_dev == RT_NULL)
    {
        rt_kprintf("adc sample run failed! can't find %s device!\n", adcdevname);
        return RT_ERROR;
    }

    /* 使能设备 */
    ret = rt_adc_enable(adc_dev, channel);

    /* 读取采样值 */
    value = rt_adc_read(adc_dev, channel);
    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);

    /* 关闭通道 */
    ret = rt_adc_disable(adc_dev, channel);
    rt_kprintf("adc_get %s channel:%d\n", adcdevname, channel);

    return ret;
}

// 设置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(adc_get, get adc voltage);
MSH_CMD_EXPORT(dac_set, set dac voltage. Useage: dac_set adc2 11 200);

将引脚PA4和PC1短接,运行结果如下:
在这里插入图片描述

在PA4脚用万用表测得输出电压为0.8080V

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

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

相关文章

16.5 参考文献——深度学习定位

16.5 一种高效鲁棒的多楼层室内环境指纹定位方法 同济大学 Zhao Y, Gong W, Li L, et al. An Efficient and Robust Fingerprint Based Localization Method for Multi Floor Indoor Environment[J]. IEEEa Internet of Things Journal, 2023. 2.相关工作 B.基于深度学习的…

情人节专属--html5 canvas制作情人节告白爱心动画特效

💖效果展示 💖html展示 <!doctype html> <html> <head> <meta charset=

2024杭州国际智慧城市,人工智能,安防展览会(杭州智博会)

在智能化浪潮的冲击下&#xff0c;我们的生活与环境正在经历一场深刻的变革。这是一场前所未有的技术革命&#xff0c;它以前所未有的速度和广度&#xff0c;改变着我们的生活方式、工作方式、思维方式和社会结构。在这场变革中&#xff0c;有的人选择激流勇进&#xff0c;拥抱…

Redis中的Java客户端

一、Jedis Jedis是一个Java实现的Redis客户端连接工具。 Jedis使用非常简单&#xff0c;直接引入依赖。基于默认参数的Jedis连接池&#xff0c;初始化连接池类&#xff08;使用默认连接池参数&#xff09;JedisPool&#xff0c;获取一个Jedis连接Jedis jedisjp.getResource()…

Git将某个文件合并到指定分支

企业开发中&#xff0c;经常会单独拉分支去做自己的需求开发&#xff0c;但是某些时候一些公共的配置我们需要从主线pull&#xff0c;这时候整个分支merge显然不合适 1.切换至待合并文件的分支 git checkout <branch>2.将目标分支的单个文件合并到当前分支 git checkou…

线上党建展厅有哪些功能,如何搭建一个成功的线上党建展厅

引言&#xff1a; 随着互联网的飞速发展&#xff0c;线上党建展厅成为党建宣传的新平工具&#xff0c;它提供了一个方便的党建学习、交流和展示的空间。那么线上党建展厅有哪些功能&#xff0c;如何搭建一个成功的线上党建展厅呢&#xff1f; 一、线上党建展厅有哪些功能 1.组…

SSH 隧道是什么,有什么用

本地主机&#xff08;A&#xff09;&#xff1a;需要访问目标服务器的主机。 跳板服务器&#xff08;B&#xff09;&#xff1a;位于本地主机和目标服务器之间的第三方服务器。跳板服务器上已经配置好SSH服务&#xff0c;并允许SSH隧道传输。 目标服务器&#xff08;C&#xff…

vscode调试debug,launch.json文件‘args’无法发传递给脚本

问题&#xff1a;调试时&#xff0c;脚本执行&#xff0c;发现在launch.json文件中明明定义了“args”参数&#xff0c;却没有传递给执行命令。 解决&#xff1a; launch.json中的"name"参数不要随便起&#xff0c;要与执行的文件名一致&#xff01; 参考链接&…

RT-Thread Studio学习(十三)DAC

RT-Thread Studio学习&#xff08;十三&#xff09;DAC 一、简介二、新建RT-Thread项目并使用外部时钟三、启用DAC四、测试五、总结 一、简介 本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用DAC设备。硬件及开发环境如下&#xff1a; OS WIN10STM32F40…

聆听人生故事:欧美用户与“爱可声”助听器的相伴时刻

在日常生活中&#xff0c;听力下降是一种常见的问题&#xff0c;尤其在年长者中更为普遍。随着人口老龄化的加剧&#xff0c;助听器市场也在不断扩大。据世界卫生组织发布的《世界听力报告》显示&#xff0c;目前全球五分之一的人听力受损&#xff0c;听力损失影响全球超过15亿…

pxe高效批量网络装机 以及安装教程

系统装机的三种引导模式 1.pe 2光驱 3.网卡 打开本机桌面 可以看见背景图片 查看配置文件内容 文件时引导选项的功能 pxe原理&#xff1a; 先根据dhcp找到IP地址、和引导程序的地址&#xff0c;还提供客户机tftp地址&#xff0c;因为tftp是小文件&#xff0c;容量小&#…

龙芯3A6000_统信UOS上使用UDOM工具箱

原文链接&#xff1a;龙芯3A6000|统信UOS上使用UDOM工具箱 大家好&#xff01;今天&#xff0c;我非常兴奋地和大家分享一篇关于在龙芯3A6000搭载统信UOS系统上使用UDOM工具箱的实用指南。这不仅是一次技术探索&#xff0c;也是一次提升运维效率的旅程。 首先&#xff0c;让我们…

【NPL】自然语言处理(Natural Language Processing,NLP)的发展简述

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读文章&#xff01; 此篇是【话题达人】序列文章&#xff0c;这一次的话题是《自然语言处理的发展》 文章将以博主的角度进行讲述&#xff0c;理解和水平有限&#xff0c;不足之处&#xff0c;望指正。 目录 背景发展线路研发关…

d2l包安装教程

目录 一、下载d2l包 1、错误的安装方法 2、正确的安装方法 二、可能会遇到的问题 1、网络超时导致下载中断 2、windows powershell激活虚拟环境时报错 一、下载d2l包 直接按照教程安装 — 动手学深度学习 2.0.0 documentation运行命令pip install d2l0.17.6安装会比较慢&…

Jira 宣布Data Center版涨价5%-15%,6年内第8次提价

近日&#xff0c;Atlassian官方面向合作伙伴发布2024年涨价通知&#xff1a; 自2024年2月15日起&#xff0c;旗下核心产品Jira Software、Confluence、Jira Service Management的DC版本&#xff08;Data Center版本&#xff09;价格提高5%-15%&#xff08;涨幅与坐席数阶梯相关…

关于C#中的async/await的理解

1. 使用async标记的方法被认为是一个异步方法&#xff0c;如果不使用await关键字&#xff0c;调用跟普通方法没有区别 static async Task Main(string[] args){Console.WriteLine("主线程id&#xff1a;" Thread.CurrentThread.ManagedThreadId);TestAwait();Consol…

数字身份所有权:Web3时代用户数据的掌控权

随着Web3时代的来临&#xff0c;数字身份的概念正焕发出崭新的光芒。在这个数字化的时代&#xff0c;用户的个人数据变得愈加珍贵&#xff0c;而Web3则为用户带来了数字身份所有权的概念&#xff0c;重新定义了用户与个人数据之间的关系。本文将深入探讨Web3时代用户数据的掌控…

1127: 矩阵乘积

题目描述 计算两个矩阵A和B的乘积。 输入 第一行三个正整数m、p和n&#xff0c;0<m,n,p<10&#xff0c;表示矩阵A是m行p列&#xff0c;矩阵B是p行n列&#xff1b; 接下来的m行是矩阵A的内容&#xff0c;每行p个整数&#xff0c;用空格隔开&#xff1b; 最后的p行是矩…

C++大学教程(第九版)5.15修改GradeBook

目录 题目 代码 运行命令&#xff08;在控制台输入&#xff09; 运行截图 题目 &#xff08;修改GradeBook&#xff09;修改图5.9~图5.11所示的 GradeBook 程序&#xff0c;使它计算一组成绩的平均成绩。 成绩A为4分&#xff0c;成绩B为3分&#xff0c;依次类推。 A:4 B:3…

UML-通信图和交互概览图(通信图和顺序图的区别与联系)

UML-通信图和交互概览图&#xff08;通信图和顺序图的区别与联系&#xff09; 一、通信图简介1.消息2.链接 二、通信图和[顺序图](https://blog.csdn.net/weixin_65032328/article/details/135587782)的联系与区别三、交互概览图四、顺序图转化为通信图练习 一、通信图简介 通…