RT-Thread:ADC 框架应用,通过 STM32CubeMX 配置 STM32 ADC驱动

关键词:ADC,RT-Thread ADC,STM32 ADC应用

说明:本笔记是记录如何开启 RT-Thread 框架的ADC功能,使用系统自带的ADC函数,并通过 STM32CubeMX 配置 STM32  ADC驱动 。

1. 打开board.h 文件,找到ADC 使用配置的流程,按流程操作。

* if you want to use adc you can use the following instructions. 
 * 如果您想使用adc,可以使用以下说明。
 *
 * STEP 1, open adc driver framework support in the RT-Thread Settings file  ,
 * 步骤1,在RT线程设置文件中打开adc驱动程序框架支持
 *
 * STEP 2, define macro related to the adc  
 * 第2步,定义与adc相关的宏
 *                 such as     #define BSP_USING_ADC1  例如:  #define BSP_USING_ADC1
 *
 * STEP 3, copy your adc init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
 * STEP 3, 将adc init函数从stm32cubemx生成的stm32xxxx_hal_msp.c复制到board.c文件的末尾
 *                 such as     void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
 *
 * STEP 4, modify your stm32xxxx_hal_config.h file to support adc peripherals. define macro related to the peripherals
 * STEP 4,修改stm32xxxx_hal_config.h文件以支持adc外围设备。定义与外围设备相关的宏
 *                 such as     #define HAL_ADC_MODULE_ENABLED
 *
 */

2.配置驱动

第1步:打开配置

* STEP 1, open adc driver framework support in the RT-Thread Settings file ,

* 步骤1,在RT线程设置文件中打开adc驱动程序框架支持

勾选如下 ADC 配置

第2步:如图打开 ADC 相关的宏,根据硬件实际使用的是 ADC1或者其他打开对应的ADC。

* STEP 2, define macro related to the adc

* 第2步,定义与adc相关的宏

* such as #define BSP_USING_ADC1 例如: #define BSP_USING_ADC1

第3步:设置ADC通道,配置ADC。(具体的生成过程参考专门的ADC驱动生成文件)

* STEP 3, copy your adc init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file

* STEP 3, 将adc init函数从stm32cubemx生成的stm32xxxx_hal_msp.c复制到board.c文件的末尾

* such as void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

按流程配置后点击下图生成代码

找到生成的代码 adc.c

把如下代码 复制到board.c文件的末尾

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

ADC_HandleTypeDef hadc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

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_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ADC1 GPIO Configuration    
    PA7     ------> ADC1_IN7
    PB0     ------> ADC1_IN8 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC1_CLK_DISABLE();
  
    /**ADC1 GPIO Configuration    
    PA7     ------> ADC1_IN7
    PB0     ------> ADC1_IN8 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_7);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0);

  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

第4步:打开ADC的宏

* STEP 4, modify your stm32xxxx_hal_config.h file to support adc peripherals. define macro related to the peripherals

* STEP 4,修改stm32xxxx_hal_config.h文件以支持adc外围设备。定义与外围设备相关的宏

* such as #define HAL_ADC_MODULE_ENABLED

第5步:移植ADC应用函数

官方ADC应用介绍:Docs » 设备和驱动 » ADC设备

https://www.rt-thread.org/document/site/programming-manual/device/adc/adc/

1. ADC 设备使用示例

        ADC 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:
1.首先根据 ADC 设备名称 “adc1” 查找设备获取设备句柄。
2.使能设备后读取 adc1 设备对应的通道 5 的采样值,然后根据分辨率为 12 位,参考电压为 3.3V         计算实际的电压值。
3.最后关闭 ADC 设备对应通道。
运行结果:打印实际读取到的转换的原始数据和经过计算后的实际电压值。

2.移植以下代码到工程里面测试

/*
 * 程序清单: ADC 设备使用例程
 * 例程导出了 adc_sample 命令到控制终端
 * 命令调用格式:adc_sample
 * 程序功能:通过 ADC 设备采样电压值并转换为数值。
 *           示例代码参考电压为3.3V,转换位数为12位。
*/

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

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

static int adc_vol_sample(int argc, char *argv[])
{
    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    rt_err_t ret = RT_EOK;

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

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

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

    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);

第6步:调试修改过的移植代码

/*
 * 程序清单: ADC 设备使用例程
 * 例程导出了 adc_sample 命令到控制终端
 * 命令调用格式:adc_sample
 * 程序功能:通过 ADC 设备采样电压值并转换为数值。
 *           示例代码参考电压为3.3V,转换位数为12位。
*/
#include "user_cfg.h"

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



/* 线程 AIR_ADC_Thread 的入口函数 */
static void AIR_ADC_entry(void *param)
{

    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    rt_err_t ret = RT_EOK;


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

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

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

        rt_thread_mdelay(1000);
        rt_thread_yield();/* 放弃剩余时间片,进行一次线程切换 */

    }

}

/* 线程创建 线程 函数 */
void AIR_ADC_Thread(void)
{
    rt_thread_t tid1;//创建线程控制块指针来接收线程创建函数的返回值,目的是通过返回值判断线程是否创建ok

    /* 创建线程 ,名称是 AIR_ZY_CON_Thread,入口是 AIR_ZY_CON_entry*/
        tid1 = rt_thread_create("AIR_ADC_Thread",
                                AIR_ADC_entry, RT_NULL,
                                500,//设置内存堆栈大小
                                10, 50);//设置优先级,时间片参数,时间片是在有多个相同优先级线程时,这个线程每次被执行多少个时间片

        /* 如果获得线程控制块,启动这个线程 */
        if (tid1 != RT_NULL)
            rt_thread_startup(tid1);
}
INIT_APP_EXPORT(AIR_ADC_Thread);

第7步:调试成功:输出结果如下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Dell 机架式服务器 - 高级定制服务

Dell 机架式服务器 - 高级定制服务 1. Dell Technologies2. 机架式服务器 - 高级定制服务2.1. Servers & Storage (服务器及存储) -> Servers2.2. Rack Servers (机架式服务器)2.3. Shop2.4. PowerEdge Rack Servers (PowerEdge 机架式服务器)2.5. PowerEdge R760 Rack …

SpringBoot 注解超全详解

使用注解的优势&#xff1a; 采用纯java代码&#xff0c;不在需要配置繁杂的xml文件 在配置中也可享受面向对象带来的好处 类型安全对重构可以提供良好的支持 减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 1 注解详解&#xff08;配备了完善的释义&#xff0…

数据库的导入导出以及备份

1.数据库的导出和导入 一.navicat导入导出 导入&#xff1a;右键➡运行SQL文件 导出选&#xff1a;中要导出的表➡右键➡转储SQL文件➡数据和结构 mysqldump命 1. 进入navicat安装目录的bin目录&#xff0c;cmd打开命令窗口 2. mysql -u用户名 -p ➡ 输入密码 3. creat…

Python基础知识:整理7 字典的定义及其相关操作

1 字典的定义 # 1. 字典的定义 # 定义字典的字面量 # {key: value, key: value, ......, key: value}# 定义字典变量 # my_dict {key: value, key: value, ......, key: value}# 定义空字典 # my_dict {} # my_dict dict()定义重复Key的字典 my_dict1 {"张三": …

Proxmox VE 超融合集群销毁Ceph Pool

作者&#xff1a;田逸&#xff08;formyz&#xff09; 销毁Ceph Pool的目的 一套五节点的Proxmox VE超融合集群&#xff0c;当初为有效利用资源&#xff0c;配备了Nvme高性能磁盘和大容量的SATA机械磁盘&#xff08;如图所示&#xff09;&#xff0c;高性能Nvme磁盘用于虚拟机…

图像中部分RGB矩阵可视化

图像中部分RGB可视化 今天室友有个需求就是模仿下面这张图画个示意图&#xff1a; 大致就是把图像中的一小部分区域的RGB值可视化了一下。他居然不知道该怎么画&#xff0c;我寻思这不直接秒了。 import cv2 as cv import numpy as np import matplotlib.pyplot as pltclass …

构建高效秒杀系统的设计原理及注意事项

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

OpenFegin日志增强

OpenFeign配置日志增强功能 OpenFeign提供了日志打印功能&#xff0c;我们可以通过配置来调整日恙级别&#xff0c;从而了解Feign 中 Http请求的细节。 说白了就是对Feign接口的调用情况进行监控和输出 日志级别 NONE&#xff1a;默认的&#xff0c;不显示任何日志; BASIC&…

Android平板浏览器远程Ubuntu服务器使用code-server编程写代码

文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以&#xff0c;这里以VMwhere ubuntu系统为例 下载code server服务,浏览器…

一文快速学会Docker软件部署

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;首期文章 &#x1f4da;订阅专栏&#xff1a;Docker 希望文章对你们有所帮助 做项目的时候&#xff0c;感觉很多地方的配置都特别…

RK3568上如何使用MPP进行硬解码

目录 前言正文一、FFmpeg 拉流处理二、RK3568 mpp硬解码1、简介2、普通mpp解码流程3、核心代码 END、总结的知识与问题1、一直出现jitter buffer full 这样的问题2、如何打印帧率&#xff1f;3、分析av_packet_alloc、av_init_packet、av_packet_unref、av_packet_free、av_fra…

zookeeper 与eureka区别

CAP定理 在分布式系统的发展中&#xff0c;影响最大的莫过于CAP定理了&#xff0c;是分布式系统发展的理论基石。 2000年&#xff0c;加州大学的计算机科学家 Eric Brewer提出了CAP猜想 2002 年&#xff0c;麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP 猜…

PTA✨C语言 组合数的和

7-5 组合数的和 分数 15 全屏浏览题目 切换布局 作者 陈越 单位 浙江大学 给定 N 个非 0 的个位数字&#xff0c;用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8&#xff0c;则可以组合出&#xff1a;25、28、5…

指针的含义、表示、规范、存储、运用

指针的含义、表示、规范、存储、运用 指针的含义指针的表示指针的规范先声明再定义声明和定义一起表示错误表示 指针的存储理解一个变量的存储过程和原理理解一个指针的存储过程和原理理解多个指针的存储过程和原理 指针的运用 指针的含义 表示某个变量或数据所在的内存地址 注…

SpringBoot 如何增强PageHelper入参的健壮性

PageHelper.startPage(int pageNum, int pageSize, boolean count) 参数为外部输入&#xff0c;故存在异常输入场景。比如 pageNum 和 pageSize 输入的值 负数 或者 0&#xff0c;所以引入PageUtils来对入参进行判断矫正&#xff0c;从而避免引入异常。 第1步&#xff1a;支持…

Copilot 插件的使用介绍:如何快速上手

GitHub Copilot 本文主要介绍如何通过脚本工具激活 GitHub Copilot 插件&#xff0c;提供安装及激活图文教程&#xff0c;大家按下面操作即可激活GitHub Copilot插件&#xff0c;免费使用Ai编码工具 一、GitHub Copilot 介绍 GitHub Copilot 是由 GitHub 和 OpenAI 共同开发的…

外包做了5个月,技术退步一大半了。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入深圳某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

苹果电脑RAW图像处理软件Capture One Pro 22 mac软件介绍

Capture One Pro 22 for mac是一款专业的RAW文件转换器和图像编辑软件&#xff0c;拥有更新的处理引擎、市场领先的性能和强大的新功能&#xff0c;可为 500 多台高端相机提供具有美丽色彩和令人难以置信的细节的终极图像质量。 Capture One Pro 22 for Mac版软件介绍 Capture…

OR-357,替代HCPL-181

提供隔离反馈 逻辑电路之间的接口 提供1通道和4通道 电平转换 DC和AC输入 高集电极-发射极电压 &#xff08;VCEO 80V&#xff09; 消除接地环路 特征 电流传输比&#xff08;CTR &#xff1a; 最低 50% 在 IF 5mA&#xff0c; VCE 5V&#xff0c; Ta25 C&#xff09;…

【npm link】Node命令中的npm link命令的使用,还有CLI全局命令的使用,开发命令行工具必不可少的部分

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;NodeJs &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续前进的勇气…