Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
ADC
《内核学习营》+水一方+项目中应用的ADC实现电压采集
发布于 2018-09-13 16:05:17 浏览:3163
订阅该版
* 本帖最后由 吉帅虎 于 2018-9-13 16:05 编辑 * 通过参考网友们关于RTT中ADC外设的整理,完成了在STM32F103VCT6上的应用。不过我依然对RTT的外设有一些疑问,我也专门针对这些疑问发了帖子,希望能得到一些解答。疑问贴在这里[https://club.rt-thread.org/ask/question/8007.html](https://club.rt-thread.org/ask/question/8007.html) 不过除去这些疑问。我别人的驱动的基础上也完成了自己的ADC移植。参考的别人的代码是这个![driver_adc_example.zip](/uploads/201809/13/154149rxckvendz4tvqxxv.zip),在此感谢原作者! ********************************************************************************************* 硬件:自用STM32F103VCT6板卡 实验目的:实现多路ADC信号采集。 扩展功能:1、使用env配置对应的AD通道(暂未完成) 2、使用env配置是否使用ADC的DMA功能(暂未完成) 软件平台:env_released_1.0.0 ,mdk5.25 ********************************************************************************************* ADC外设的文件结构如下,一共有4个文件。其中_adc.c和drv_adc.h是与硬件无关的代码,rv_adc.c是与硬件相关的驱动部分;test_adc.c很明显就是测试代码了,我没有用这一部分代码,自己在项目的应用中新建了一个文件。 ![TIM图片20180913154220.png](/uploads/201809/13/154313wurg8rggbnqbu6z6.png) 按照如下文件结构放置上述三个文件,drv_adc.h跟drv_adc.c放到了一个文件夹下。不知道我对这个文件结构的理解有没有问题。明白的大侠们可以给指点一下。 接下来就是修改与硬件相关的代码部分。在drv_adc.c文件内添加如下代码 ``` //初始化ADC //ch: ADC_channels //通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16 void ADC1_Config(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; /********************************************************************************/ //DMA配置 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能MDA1时钟 /* DMA channel1 configuration */ DMA_DeInit(DMA1_Channel1); //指定DMA通道 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//设置DMA外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //设置DMA内存地址,ADC转换结果直接放入该地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设为设置为数据传输的来源 DMA_InitStructure.DMA_BufferSize = 14; //DMA缓冲区设置为12; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 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_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道 x拥有高优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Enable DMA channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道 //ADC配置 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div8); /* ADC1 configuration */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //使用独立模式,扫描模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //需要外接触发器 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//使用数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 14; // 只有12个转换通道 ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel11 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 10, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 13, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 14, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 11, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 12, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); //使能ADC的DMA /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); //使能ADC1 /* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); /* Start ADC1 Software Conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开始一次转换 } rt_err_t convert(struct rt_device *device, int channel, int *value) { rt_err_t result = RT_EOK; if(channel > (ADC_CHANNEL_MAX - 1)) { result = -RT_EIO; goto _exit; } //*value = (channel << 8) | (rand() % 0xFF); /* ch=4, return: 0x4xx */ *value = *((Uint16 *)(device->user_data )+channel); _exit: return result; } ```这些代码是针对我自己的应用配置的,一共需要转换14个通道,使用DMA方式。其中通道和DMA的配置在通道序号上可能有些错误,由于这个不是原则性错误,暂时没有修改。使用的时候根据实际硬件修改就可以了。有人想参考的话需要注意一下。 ADC的配置按照裸机的方式配置的。一个是IO配置,一个的ADC的参数配置,包括DMA配置。使用DMA的时候,我自己定义了一个全局数组,存放DMA传输的数据。(在操作系统中使用全局变量有没有不合适的地方也请大侠们指点一下。) rt_err_t convert(struct rt_device *device, int channel, int *value)函数是读取数据的最终执行者。参考文件中返回的是一个随机数,我一开始没有注意看,受到的数据总是不对。修改成*value = *((Uint16 *)(device->user_data )+channel);就可以了。 接下来修改修改的是rt_hw_adc_init()函数,代码如下 ```int rt_hw_adc_init(void) { int ret = RT_EOK; /* add ADC initial. */ ADC1_GPIO_Config(); ADC1_Config(); //ADC_ConvertedValue ret = rt_device_adc_create(RT_ADC_NAME, &adc_ops, RT_NULL); ret = rt_device_adc_create(RT_ADC_NAME, &adc_ops, &ADC_ConvertedValue); return ret; } INIT_DEVICE_EXPORT(rt_hw_adc_init);```初始化部分除了初始化模拟输入的IO和ADC参数配置之外,就是创建ADC外设。注意用户数据指针的是存放DMA数据的数组。这样在rt_err_t convert(struct rt_device *device, int channel, int *value)函数里就可以通过*value = *((Uint16 *)(device->user_data )+channel);这样的操作来传递数据了。 int rt_hw_adc_init(void)需要在board.c初始化部分调用,这个大家应该都明白,就不贴代码了 接下来就是应用部分的代码,由于时间比较仓促。只做了一下数据的验证,没有最终按我的项目修改ADC的计算,核心代码如下,代码也是参考的学习营里的外设代码和网友的代码实现的。操作过程分为查找外设。打开外设。读取外设三部分。每一步都可以加错误提示。 ``` while(1) { rt_uint8_t i; rt_uint16_t val=0; dev = rt_device_find(RT_ADC_NAME); if(!dev) { rt_kprintf("not found!
"); } result = rt_device_open(dev, RT_DEVICE_FLAG_RDONLY); if(result != RT_EOK) { rt_kprintf("open faild!
"); } if(rt_device_read(dev,6,&temp,sizeof(temp))!=sizeof(temp)) { rt_kprintf("channel %d: faild!
", 1); } rt_kprintf("ADC Vaule is:%d
", temp); // val += temp; // rt_thread_delay(1); /* #define RT_TICK_PER_SECOND 1000 */ rt_thread_delay(RT_TICK_PER_SECOND); }``` 编译后执行效果如下: ADC是输入是通过电位器调整实现的,暂时没有进行数据处理,直接显示的是ADC转换之后的结果。 ![TIM图片20180913160307.png](/uploads/201809/13/160342wkzkhde11ee310p2.png) ADC外设部分虽然做出来了。依然有一些疑惑。扩展的功能还没有完成。但是最新实在是有点儿忙。先完成其他外设的实验再来完成 此实验的扩展功能
查看更多
3
个回答
默认排序
按发布时间排序
mreasonlee
2019-04-13
这家伙很懒,什么也没写!
DMA转换不是直接赋值给地址吗?我还没搞明白那个ADC框架怎么去兼容DMA模式和普通模式
mreasonlee
2019-04-16
这家伙很懒,什么也没写!
谢谢 你的资料很有用,给我很大帮助
mreasonlee
2019-04-16
这家伙很懒,什么也没写!
另外还有一篇很好的 ADC多通道 DMA的资料,详情以下链接,给有需要的人参考: [https://blog.csdn.net/weixin_42653531/article/details/81123770](https://blog.csdn.net/weixin_42653531/article/details/81123770)
撰写答案
登录
注册新账号
关注者
0
被浏览
3.2k
关于作者
吉帅虎
这家伙很懒,什么也没写!
提问
12
回答
12
被采纳
0
关注TA
发私信
相关问题
1
请大神帮忙看下风格 还是哪里有问题 照着串口驱动写的ADC驱动
2
ADC config
3
rt_thread_delay()和ADC采样之间的冲突
4
请教在官方BSP中的STM32F40X程序中加入ADC,串口没输出。
5
给RT-Thread添加ADC驱动框架
6
求助:ADC采样被干扰
7
【内核和外设学习营】十里 ADC光敏电阻电压采集实验
8
<内核学习营>+坦然+探索者stm32f407板子的ADC测试光传感器实验
9
【内核学习营】+青春+ADC读取光敏传感器实验
10
STM32F10X HAL ADC+TIM+DMA+USART程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
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
【RT-Thread 全球电子设计大赛】基于vision board 的巡检除冰机器人
2
新手教程-Pin设备使用
3
基于嵌入式的智能关怀系统#24嵌入式设计大赛
4
基于机器视觉识别自动跟踪器
5
[24嵌入式设计大赛]基于Vision-Board的智能应急环境监测控制小车
热门标签
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
ota在线升级
WIZnet_W5500
UART
flash
packages_软件包
cubemx
PWM
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
中断
flashDB
socket
Debug
GD32
编译报错
msh
keil_MDK
at_device
MicroPython
rt_mq_消息队列_msg_queue
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
5
个答案
2
次被采纳
rv666
6
个答案
1
次被采纳
用户名由3_15位
5
个答案
1
次被采纳
xiaorui
2
个答案
1
次被采纳
张世争
2
个答案
1
次被采纳
本月文章贡献
jaffer
1
篇文章
5
次点赞
rtt_dmx
1
篇文章
4
次点赞
flytianya2010
1
篇文章
2
次点赞
BRICK PORTER
1
篇文章
2
次点赞
不灬忘初心
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部