基于RT-Thread的STM32F4开发第二讲第一篇——ADC

文章目录

  • 前言
  • 一、RT-Thread工程创建
  • 二、ADC工程创建
  • 三、ADC功能实现
    • 1.ADC.c
    • 2.ADC.h
    • 3.mian.c
  • 四、效果展示和工程分享
  • 总结


前言

ADC是什么不多讲了,前面裸机操作部分有很多讲述。我要说的是RT-Thread对STM32的ADC外设的适配极其不好,特别是STM32G4系类,这一章先讲STM32F4的ADC应用。本文使用的是RT-Thread最新的驱动5.1.0,兼容下面的所有驱动。使用的开发板是正点原子的STM32F4探索者


一、RT-Thread工程创建

先在RT-Thread studio中创建好工程,参考下面的文章使得驱动5.1.0全构建不报错和警告,如图所示。
RT-Thread studio的驱动5.1.0报错修改
在这里插入图片描述
不要着急修改时钟配置,这里按我方法来,打开自动生成的CubeMX Settings(找不到的话点击窗口,恢复窗口布局,在项目资源管理器下。在CubeMX中按裸机编程一样,把时钟和需要用到的外设都配置好。配置详情我就不说了,看前面的文章就行,这里放几张图示例。
注意使用到的外设都要配置,开局使用串口1作为控制台串口,所以这里也配置了。
在这里插入图片描述
这里我使用了ADC1和ADC2,配置如下,对于每个外设的详细工作参数,我建议也配置一下,可以作为后面RT-Thread的参考,关于ADC的详情配置见下文。
STM32LL库编程系列第八讲——ADC模数转换
在这里插入图片描述
在这里插入图片描述
这里的IDE要选择EWARM,也就是保持默认,很重要,其他照常
在这里插入图片描述
在这里插入图片描述
到这一步就可以生成工程了
在这里插入图片描述
第一次生成工程后要把cubeMX关闭掉,这样RT-Thread studio才会同步,如下
在这里插入图片描述
点击确认,重点来了
点击左边文件,cubemx(没有的话,刷新一下),右键Src,资源配置,排除构建
在这里插入图片描述
打开cubemx的mian.c复制函数void SystemClock_Config(void),包括函数名全部复制,在打开drivers/drv_clk.c,把void system_clock_config(int target_freq_mhz)函数删了,把复制的void SystemClock_Config(void)粘贴原地,接着全编译,没有问题。
在这里插入图片描述
到这一步你可以把工程保存好,在RT-Thread studio中基于STM32F407系类的驱动5.1.0的初始工程创建完成,以后再用就直接复制工程就行,不用重复创建了。这一点也希望官方优化,不需要我们这么麻烦。

二、ADC工程创建

接下来,工程名更改为IO_ADC2。
打开cubemx/src/adc.h。复制函数void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)到drivers/board.c的末尾,也就是这样。
在这里插入图片描述
这两个函数不需要在board.h中去声明,有其他.h已经声明好了,所以这里复制过来就可以用。
打开board.h需要的ADC的宏,不需要再去stm32f4xx_hal_config.h中注释宏#define HAL_ADC_MODULE_ENABLED了,细心的同学可以发现了,drivers中更名为了stm32f4xx_hal_config_bak.h。而stm32f4xx_hal_config.h在cubemx/inc中了,已经在创建时开启宏HAL_ADC_MODULE_ENABLED了。
在这里插入图片描述
接着在RT-Thread Settings中打开ADC驱动
在这里插入图片描述
注意开启ulog日志,进入到里面开启使能浮点数支持,这将会使我们rt_kprintf能够输出浮点数。
在这里插入图片描述

在这里插入图片描述
到此全编译程序没有错误,到这里ADC工程创建完成了
在这里插入图片描述

三、ADC功能实现

这里我要讲点网上没有的(起码此刻孤陋寡闻的我没找到)
点击drivers/include/confing/adc_confing.h这里有我们使用的ADC的初始化参数,rtthread studio并没有ADC参数控制函数,想要修改,只能在这改,希望官方更新一下,可以像uart外设这样,建一个ADC参数结构体,里面包含了所有参数设计,再利用rt_device_control函数写进去,这样才符合常理,不能老是去驱动文件里改啊,很难找的。
这里说笑了,对于国产软件生态,还需要我们大家共同努力完善。所以我愿意把我的发现免费分享出来。
打开cubemx/src/adc.c对照里面的参数设置,对adc_confing.h进行更改(这也是我前面说最好把参数配置完全,后面好参照。我这里修改了ADC的位数。
在这里插入图片描述
打开drivers/drv_adc.c找到函数stm32_get_adc_value这里面有如下设置语句

ADC_ChanConf.Channel =  stm32_adc_get_channel(channel);
ADC_ChanConf.Rank = 1;
ADC_ChanConf.SamplingTime = ADC_SAMPLETIME_112CYCLES;
ADC_ChanConf.Offset = 0;

这些语句不是在一起的,这里设置了通道的参数,可以修改。后面有HAL_ADC_ConfigChannel(stm32_adc_handler, &ADC_ChanConf);到这ADC的初始化才结束。编译程序没有错误。
APP文件夹里是我自定义的文件夹,其他函数不用管,本工程只用到ADC.c和ADC.h。注意创建文件夹要把头文件目录添加进构建啊。如何添加见本系列第一讲
在这里插入图片描述

1.ADC.c

这里面包含adc初始化和线程初始化,代码逻辑我就不讲了,我的代码风格应该挺正规的,具体编写流程去看官方文档或其他人文章

#include "ADC.h"#define     ADC1_NAME   "adc1"
#define     ADC2_NAME   "adc2"
#define     REFER_VOLTAGE   3.3
#define     CONVERT_BITS    (1<<10)static void adc_thread_entry(void *parameter);
rt_adc_device_t adc1_handle,adc2_handle;
int adc_init(void)
{rt_err_t adc1_flag,adc2_flag;adc1_handle = (rt_adc_device_t)rt_device_find(ADC1_NAME);adc2_handle = (rt_adc_device_t)rt_device_find(ADC2_NAME);if((adc1_handle == RT_NULL) || (adc2_handle == RT_NULL)){rt_kprintf("failed to adc handle fine\n");return -1;}adc1_flag = rt_adc_enable(adc1_handle, 1);adc2_flag = rt_adc_enable(adc2_handle, 0);if((adc1_flag != RT_EOK) || (adc2_flag != RT_EOK)){rt_kprintf("failed to adc enable\n");return -1;}rt_kprintf("adc1 and adc2 init success\n");return 0;
}
int adc_thread_init(void)
{rt_thread_t adc_thread;adc_thread = rt_thread_create("adc_thread", adc_thread_entry, RT_NULL, 1024, 9, 100);if(adc_thread == RT_NULL){rt_kprintf("failed to adc thread create");return -1;}if(rt_thread_startup(adc_thread) != RT_EOK){rt_kprintf("failed to adc startup\n");return -1;}return 0;
}
static void adc_thread_entry(void *parameter)
{float adc1_V_old = 0,adc2_V_old = 0;float adc1_V_new,adc2_V_new;while(1){adc1_V_new = (float)rt_adc_read(adc1_handle, 1)*REFER_VOLTAGE/CONVERT_BITS;adc2_V_new = (float)rt_adc_read(adc2_handle, 0)*REFER_VOLTAGE/CONVERT_BITS;if( ((int)(adc1_V_old *100) != (int)(adc1_V_new *100)) || ((int)(adc2_V_old *100) != (int)(adc2_V_new *100)) ){rt_kprintf("get voltage for adc1 and adc2 is: %.2f and %.2f\n",adc1_V_new, adc2_V_new);adc1_V_old = adc1_V_new;adc2_V_old = adc2_V_new;}rt_thread_mdelay(100);}
}

2.ADC.h

#ifndef APP_ADC_H_
#define APP_ADC_H_#include <board.h>
#include <rtdevice.h>int adc_init(void);
int adc_thread_init(void);#endif /* APP_ADC_H_ */

3.mian.c

#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "ADC.h"int main(void)
{adc_init();adc_thread_init();while (1){rt_thread_mdelay(1000);}return RT_EOK;
}

编译0错误0警告,到此工程结束。

四、效果展示和工程分享

在这里插入图片描述
因为探索者开发板没有滑动变阻器测试ADC模块的设置,这里我直接把PA1的接了3.3V,PA0悬空。所以ADC2的读数不重要,按理说ADC1读数应该保持3.3V不变啊,即使便,应该也要非常小,看输出结果都有2点多伏了,这里我开始也怀疑,然后我用裸机的官方HAL库例程看了一下,发现官方HAL库例程也一样会有这种跳变误差。后面知道是ADC的滤波函数没有用,STM32f4的HAL库我就没找到有这个函数(下一章的STM32g4的就有),那就不管了,功能是没问题的,ADC检测也没问题。
工程上传百度网盘,包括IO_ADC2和初始工程文件,免费下载。同时也上传到CSDN,被强制成为VIP才能下载(其实我是想每个工程收1积分)。如果你刚好有VIP,就请CSDN下载支持一下,嘻嘻。没有的话,千万别开,死贵,去百度网盘下载。

通过网盘分享的文件:IO_ADC2.zip
链接: https://pan.baidu.com/s/1uql0Hphcij3f9HFUfNTTxw?pwd=fdm9 提取码: fdm9
通过网盘分享的文件:RT_driver_5.1.0_STM32F407ZGx.zip
链接: https://pan.baidu.com/s/1uZD_JULeHrG_pVsWSjOggQ?pwd=mp41 提取码: mp41


总结

创建工程有点繁琐,如果有某些地方我没说到导致报错了,请下载工程,这些工程我是验证过的,没有问题。把问题发在评论区,我看到了会修改回来。

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

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

相关文章

FoMo 数据集是一个专注于机器人在季节性积雪变化环境中的导航数据集,记录了不同季节(无雪、浅雪、深雪)下的传感器数据和轨迹信息。

2025-05-02&#xff0c;由加拿大拉瓦尔大学北方机器人实验室和多伦多大学机器人研究所联合创建的 FoMo 数据集&#xff0c;目的是研究机器人在季节性积雪变化环境中的导航能力。该数据集的意义在于填补了机器人在极端季节变化&#xff08;如积雪深度变化&#xff09;下的导航研…

vue3+ts继续学习

我们再写点东西&#xff0c;这里面都是vue2的语法&#xff0c;应该都能看明白&#xff01;我们写完直接去运行一下代码&#xff01; 发现什么都没有发生&#xff01;为什么呢&#xff1f;因为我们在App.vue中没有引入&#xff01;哈哈哈哈&#xff01;这样就好了&#xff01;注…

LIO-Livox

用单台Livox Horizon (含内置IMU) 实现高鲁棒性的激光-惯性里程计&#xff0c;可在各类极端场景下鲁棒运行&#xff0c;并达到高精度的定位和建图效果。(城区拥堵、高速公路、幽暗隧道) 注&#xff1a;该系统主要面向大型室外环境中的汽车平台设计。用户可以使用 Livox Horizo…

day18-API(常见API,对象克隆)

课程目标 能够熟练使用Math类中的常见方法 能够熟练使用System类中的常见方法 能够理解Object类的常见方法作用 能够熟练使用Objects类的常见方法 能够熟练使用BigInteger类的常见方法 能够熟练使用BigDecimal类的常见方法 1 Math类 1.1 概述 tips&#xff1a;了解内容…

用OMS从MySQL迁移到OceanBase,字符集utf8与utf8mb4的差异

一、问题背景 在一次从MySQL数据库迁移到OceanBase的MySQL租户过程中&#xff0c;出现了一个转换提示&#xff1a; [WARN][CONVER] he table charset:utf8->utf8mb4&#xff0c; 你可能会担心这种转换可能导致字符集不兼容的问题。但通过查阅相关资料可知&#xff0c;utf8m…

MATLAB中tabulate函数——先验概率的简单估计

load fisheriris X meas(:,1:2); Y species; labels unique(Y); tabulate(Y)ValueCountPercentsetosa5033.33%versicolor5033.33%virginica5033.33%

《Python星球日记》第28天:数据获取与可视化(综合项目)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏:《Python星球日记》,限时特价订阅中ing 目录 一、项目概述二、数据获取1. 准备工作2. 使用 `requests` 获取网页内容3. 使用 `BeautifulSoup`…

基于深度学习的图像识别技术:从原理到应用

前言 在当今数字化时代&#xff0c;图像识别技术已经渗透到我们生活的方方面面&#xff0c;从智能手机的人脸解锁功能到自动驾驶汽车对交通标志的识别&#xff0c;再到医疗影像诊断中的病变检测&#xff0c;图像识别技术正以其强大的功能和广泛的应用前景&#xff0c;改变着我们…

限免开关实施版本保护措施,保证项目灰度发布安全

迭代用户限免权限校验业务 新增限免开关实现普通用户权益更新&#xff0c;实施版本保护措施&#xff0c;保证项目灰度发布安全&#xff1b; // 是否展示限免标识 func (t *BasePrivilegeService) IsPromotionFree(p consumParams) bool {// 限免开关isFreeUseOpen : p.cfg.Vip…

从 AWS Marketplace 开始使用 AssemblyAI 的语音转文本模型构建语音智能

语音智能和语音转文本 &#xff08;STT&#xff09; 技术已变得至关重要&#xff0c;因为组织每天收集数千小时的电话、会议和客户互动。仅靠原始音频并不能推动决策 - 组织需要智能来大规模地从语音数据中提取价值。语音智能结合了语音识别、自然语言处理 &#xff08;NLP&…

Android组件化 -> Debug模式下,本地构建module模块的AAR和APK

本地构建module模块的AAR gradle.properties isCommonApp false模块的build.gradle apply plugin: com.android.library&#xff1a;module模块编译manifest.srcFile src/main/AndroidManifest.xml&#xff1a;读取没有启动App和Activity的配置文件 if (isCommonApp.toBoo…

FlexibleButton:一个轻巧灵活的按键处理库,让你的按键处理更简单

在嵌入式系统开发中&#xff0c;按键输入处理是一个常见且重要的环节。然而&#xff0c;许多开发者在处理按键时&#xff0c;往往会遇到按键消抖、组合按键、长按/短按等功能实现的复杂性。如何在保证系统高效运行的同时&#xff0c;简化按键事件的处理呢&#xff1f; 今天&…

探索程序员薪资背后的秘密与未来:智能化工具如何助力职场发展

最新接入DeepSeek-V3模型&#xff0c;点击下载最新版本InsCode AI IDE 探索程序员薪资背后的秘密与未来&#xff1a;智能化工具如何助力职场发展 引言 在当今数字化时代&#xff0c;程序员作为科技发展的核心力量&#xff0c;其职业前景和薪资水平备受关注。随着人工智能和自…

【STM32单片机】#14 PWR电源控制

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 目录 PWR…

第十五届蓝桥杯单片机国赛-串口解析

串口通信像是蓝桥杯单片机组国赛中一个若隐若现的秘境&#xff0c;总在不经意间为勇者们敞开大门。然而&#xff0c;初次探索这片领域的冒险者&#xff0c;常常会被其神秘莫测的特性所震慑&#xff0c;黯然退场&#xff08;编不下去了&#xff0c;直接进入正题&#xff09;。 附…

深入探索 51 单片机:从入门到实践的全面指南

深入探索 51 单片机&#xff1a;从入门到实践的全面指南 一、引言 在嵌入式系统发展的漫长历程中&#xff0c;51 单片机犹如一颗璀璨的明星&#xff0c;虽然诞生已有数十年&#xff0c;但至今仍在众多领域发挥着重要作用。它以结构简单、易于学习、成本低廉等优势&#xff0c…

GD32F470+CH395Q

第一步&#xff1a;资料下载 以太网协议栈芯片 CH395 - 南京沁恒微电子股份有限公司 第二步&#xff1a;准备工程 &#xff08;1&#xff09; 首先准备一个编译无报错、可以正常打印和延时的工程文件&#xff0c;官方例程采用STM32F1芯片&#xff0c;但本文采用GD32F470芯片 …

Linux 怎么使用局域网内电脑的网络访问外部

一次性 export http_proxy"http://192.168.0.188:7890" export https_proxy"http://192.168.0.188:7890"一直生效 写入 ~/.bashrc&#xff08;或 ~/.bash_profile&#xff09; nano ~/.bashrc加入这一行&#xff1a; export http_proxy"http://19…

Mysql进阶篇1_存储引擎、索引、SQL性能分析指令

文章目录 1.存储引擎InnoDBMyISAMMemory存储引擎选择和对比 2.索引索引结构索引分类索引语法索引使用&#xff08;建议看完第3节后观看&#xff09;&#xff01;&#xff01;&#xff01;mysql如何使用索引查询数据&#xff08;个人理解&#xff09; 3.SQL性能分析SQL执行频率慢…

LeetCode 热题 100 118. 杨辉三角

LeetCode 热题 100 | 118. 杨辉三角 大家好&#xff0c;今天我们来解决一道经典的算法题——杨辉三角。这道题在 LeetCode 上被标记为简单难度&#xff0c;要求生成杨辉三角的前 numRows 行。杨辉三角是一个经典的组合数学问题&#xff0c;每一行的数字都是其正上方和正左上方…