Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
ADC
【内核和外设学习营】十里 ADC光敏电阻电压采集实验
发布于 2018-09-05 18:12:24 浏览:2470
订阅该版
* 本帖最后由 hyz_rtt 于 2018-9-6 19:40 编辑 * 1、实验要求: 要求硬件上:至少有一路带ADC输入功能的GPIO,能够用来连接光敏电阻; 有一路串口用来做 msh shell 终端 软件上:BSP 中已经实现如下驱动:串口驱动,PIN 驱动,ADC驱动(裸机写的) 2、准备工作: 硬件:野火霸天虎stm32407开发板 软件:rtt3.1.0 stm32f40x(STD库)、env0.7.1 3、示例代码 (1)adc_test()可以直接在主函数调用,这里采用MSH输出 ```#include
#include
#include "stm32f4xx.h" #include "stm32f4_adc.h" // ADC1转换的电压值通过MDA方式传到SRAM extern __IO uint16_t ADC_ConvertedValue; // 局部变量,用于保存转换计算后的电压值 int ADC_ConvertedValueLocal; void adc_test(void) { /* 初始化滑动变阻器用到的DAC,ADC数据采集完成后直接由DMA运输数据到ADC_ConvertedValue变量 DMA直接改变ADC_ConvertedValue的值*/ Rheostat_Init(); rt_kprintf("----这是一个光敏电阻电压采集实验(DMA传输)----
"); while (1) { ADC_ConvertedValueLocal =ADC_ConvertedValue*(3.3/4096); // 读取转换的AD值 rt_kprintf("The current AD value = 0x%04X
", ADC_ConvertedValue); rt_kprintf("The current AD value = %d
",ADC_ConvertedValueLocal); rt_thread_delay(100); } } //导出到MSH命令 MSH_CMD_EXPORT(adc_test,adc test)``` (2)裸机驱动:ADC的GPIO配置、ADC的DMA传输配置 ```#include
#include "stm32f4_adc.h" __IO uint16_t ADC_ConvertedValue; //配置ADC的GPIO static void Rheostat_ADC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能 GPIO 时钟 RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE); // 配置 IO GPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉 GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure); } //配置ADC,DMA传输 static void Rheostat_ADC_Mode_Config(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; // 开启ADC时钟 RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE); // ------------------DMA Init 结构体参数 初始化-------------------------- // ADC1使用DMA2,数据流0,通道0,这个是手册固定死的 // 开启DMA时钟 RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址 DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR; // 存储器地址,实际上就是一个内部SRAM的变量 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADC_ConvertedValue; // 数据传输方向为外设到存储器 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // 缓冲区大小为1,缓冲区的大小应该等于存储器的大小 DMA_InitStructure.DMA_BufferSize = 1; // 外设寄存器只有一个,地址不用递增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 存储器地址固定 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; // // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 存储器数据大小也为半字,跟外设数据大小相同 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 循环传输模式 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响 DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 禁止DMA FIFO ,使用直连模式 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO 大小,FIFO模式禁止时,这个不用配置 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 选择 DMA 通道,通道存在于流中 DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道 DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure); // 使能DMA流 DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE); // -------------------ADC Common 结构体 参数 初始化------------------------ // 独立ADC模式 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; // 时钟为fpclk x分频 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; // 禁止DMA直接访问模式 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; // 采样时间间隔 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); // -------------------ADC Init 结构体 参数 初始化-------------------------- ADC_StructInit(&ADC_InitStructure); // ADC 分辨率 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; // 禁止扫描模式,多通道采集才需要 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 连续转换 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //外部触发通道,本例子使用软件触发,此值随便赋值即可 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //数据右对齐 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //转换通道 1个 ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure); //--------------------------------------------------------------------------- // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期 ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_3Cycles); // 使能DMA请求 after last transfer (Single-ADC mode) ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC, ENABLE); // 使能ADC DMA ADC_DMACmd(RHEOSTAT_ADC, ENABLE); // 使能ADC ADC_Cmd(RHEOSTAT_ADC, ENABLE); //开始adc转换,软件触发 ADC_SoftwareStartConv(RHEOSTAT_ADC); } //ADC1初始化 void Rheostat_Init(void) { Rheostat_ADC_GPIO_Config(); Rheostat_ADC_Mode_Config(); } ``` (3)串口部分:串口驱动里已经有了 (4)宏定义 ```#ifndef __STM32F4_ADC_H__ #define __STM32F4_ADC_H__ #include "stm32f4xx.h" // RHEOSTAT: 滑动变阻器/电位器 // ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里 #define RHEOSTAT_ADC_DR_ADDR ((u32)ADC1+0x4c) // ADC IO宏定义 #define RHEOSTAT_ADC_GPIO_PORT GPIOB #define RHEOSTAT_ADC_GPIO_PIN GPIO_Pin_1 #define RHEOSTAT_ADC_GPIO_CLK RCC_AHB1Periph_GPIOB // ADC 序号宏定义 #define RHEOSTAT_ADC ADC1 #define RHEOSTAT_ADC_CLK RCC_APB2Periph_ADC1 #define RHEOSTAT_ADC_CHANNEL ADC_Channel_9 // ADC DMA 通道宏定义,这里我们使用DMA传输 #define RHEOSTAT_ADC_DMA_CLK RCC_AHB1Periph_DMA2 #define RHEOSTAT_ADC_DMA_CHANNEL DMA_Channel_0 #define RHEOSTAT_ADC_DMA_STREAM DMA2_Stream0 void Rheostat_Init(void); #endif /*__STM32F4_ADC_H__ */``` 4、实验步骤 env配置芯片型号stm32f407ZG、外部时钟源HSE25M、串口驱动、PIN驱动、ADC驱动(移植裸机) 5、实验结果:如下图 ![打印整型.png](/uploads/201809/05/180346oq2gzg7k53w5ec57.png) 6、遇到的问题:打印不出浮点型电压值 adc_test()部分的 int ADC_ConvertedValueLocal; rt_kprintf("The current AD value = %d
",ADC_ConvertedValueLocal); 若改为 float ADC_ConvertedValueLocal; rt_kprintf("The current AD value = %f
",ADC_ConvertedValueLocal); 打印结果如下图所示 ![打印浮点型失败.png](/uploads/201809/05/180706eoldrg7bckm7h7rv.png) 7、解决方法 百度了一下,有人说RTT不支持浮点型,自己看了一下rtdef.h文件里没有关于浮点型的定义。 还有就是有人说添加libc API配置,如下图 ![ENV配置选项.png](/uploads/201809/05/180859kj5559b5uwb54575.png) 配置之后,再实验,问题仍未得到解决。 可以肯定的是裸机是可以打印出来浮点型的。如下图 ![裸机支持浮点型.png](/uploads/201809/05/181021x9dihxid9hdydzdx.png)
查看更多
3
个回答
默认排序
按发布时间排序
hyz_rtt
2018-09-06
这家伙很懒,什么也没写!
[i=s] 本帖最后由 hyz_rtt 于 2018-9-6 19:41 编辑 [/i] (1)原因分析、解决思路针对小数部分无法显示的原因,经过大神的指点,M4的芯片是支持浮点型数据据处理的, 打印不出小数部分是因为rt_kprintf()函数不支持浮点型打印,具体解决的思路是:将读 取的值先扩大(例如100000倍,可根据需要扩大),然后分别把电压值的整数和小数部分 通过处理获得,最后打印出来即可。 (2)具体措施,如下程序: 将之前void adc_test(void)里的while(1)循环里的部分做修改如下 ``` //定义转换的变量 int inter_part;//采集电压值整数部分 int fraction_part;//采集电压值小数部分 while (1) { /*鉴于rt_kprintf函数不能打印浮点类型数据,所以对打印出的带有小数点的电压值做如下处理*/ // 读取转换的AD值并扩大100000倍 ADC_ConvertedValueLocal = ADC_ConvertedValue*100000*(3.3/4096); //整数部分用整除得到,因为整型不会有小数点 inter_part = ADC_ConvertedValueLocal/100000; //小数部分的数字利用取余得到 fraction_part = ADC_ConvertedValueLocal%100000; rt_kprintf("\r\n The current AD value = 0x%04X——", ADC_ConvertedValue); //打印扩大100000倍后的值 rt_kprintf("\r\n The current AD value = %d ", ADC_ConvertedValueLocal); //打印整数部分 rt_kprintf("\r\n The current AD value = %d",inter_part); //打印小数部分 rt_kprintf(".%d\r\n",fraction_part); //每1秒读取一次光敏电阻电压值 rt_thread_delay(100); } ``` (3)打印输出 [attach]6089[/attach][attach]6090[/attach] 也可看到如果用手遮挡光敏电阻,电压值会变化 (4)易错点 扩大时一定是对ADC_ConvertedValue就扩大,不能是ADC_ConvertedValueLocal, 因为ADC_ConvertedValueLocal是整型,扩大再处理还是整型,而ADC_ConvertedValue 是浮点型的。 打印时“%d.%d”、“%d.” 这种写法在编译时会报错(“.%d”则是合法的), 所以利用多个rt_kprintf函数。
yangjie
认证专家
2018-09-06
hello
[i=s] 本帖最后由 yangjie 于 2018-9-6 17:20 编辑 [/i] 贴代码的时候不以正文的方式贴,可以修改帖子中代码部分改为插入代码的方式,这样看起来清晰很多呢, 如下:
hyz_rtt
2018-09-06
这家伙很懒,什么也没写!
>贴代码的时候不以正文的方式贴,可以修改帖子中代码部分改为插入代码的方式,这样看起来清晰很多呢, 如下 ... --- 好的。发过的帖子题目如何更改
撰写答案
登录
注册新账号
关注者
0
被浏览
2.5k
关于作者
hyz_rtt
这家伙很懒,什么也没写!
提问
10
回答
38
被采纳
0
关注TA
发私信
相关问题
1
请大神帮忙看下风格 还是哪里有问题 照着串口驱动写的ADC驱动
2
ADC config
3
rt_thread_delay()和ADC采样之间的冲突
4
请教在官方BSP中的STM32F40X程序中加入ADC,串口没输出。
5
给RT-Thread添加ADC驱动框架
6
求助:ADC采样被干扰
7
<内核学习营>+坦然+探索者stm32f407板子的ADC测试光传感器实验
8
【内核学习营】+青春+ADC读取光敏传感器实验
9
《内核学习营》+水一方+项目中应用的ADC实现电压采集
10
STM32F10X HAL ADC+TIM+DMA+USART程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
TinyUSB Demo运行教程
2
RT-Thread学习大礼包一键带走!
3
freemodbus从机调试说明
4
【1024】瑞萨 RA 系列 BSP 制作与适配最新版本的 Keil 、 RSC、固件,较新的 FSP
5
基于 RT-Thread 星火一号开发板的俄罗斯方块
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
cubemx
PWM
flash
packages_软件包
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
出出啊
1516
个答案
342
次被采纳
小小李sunny
1440
个答案
289
次被采纳
张世争
799
个答案
171
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
4
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部