0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RTT下ADC+DMA裸机程序移植成功经验分享

冬至子 来源:VHMK_9546 作者:VHMK_9546 2023-08-03 15:55 次阅读

1、实验环境
RT-Thread 4.03
STM32F407VET6
STM3F4库版本 0.2.2
SDK资源管理器中可以查看版本信息如下图。(小编遇见过因版本不兼容出现的编译错误问题)

1.jpg

2、创建RT-Thread项目

1.jpg

此时编译结果没有错误

1.jpg

打开CubeMX软件(不使用CubeMX Setting)step1:配置时钟。step2、配置ADC+DMA

1.jpg

根据自己板子晶振确定时钟

1.jpg

根据ADC引脚配置

1.jpg

配置ADC1通道

1.jpg

配置DMA

1.jpg

ADC参数设置

1.jpg

生成项目

1.jpg

在RTT中如图文件夹下新建源文件

1.jpg

1.jpg

从CubeMX生成的工程中复制如下图函数到RTT文件中;具体代码有所修改,可参考代码部分

1.jpg

参考代码

#include "stm32f4xx_hal.h"
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
static void MX_DMA_Init(void)
{
/* DMA controller clock enable /
__HAL_RCC_DMA2_CLK_ENABLE();
/
DMA interrupt init /
/
DMA2_Stream0_IRQn interrupt configuration /
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
void HAL_ADC_MspInit(ADC_HandleTypeDef
hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
MX_DMA_Init();
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 /
/
USER CODE END ADC1_MspInit 0 /
/
Peripheral clock enable /
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/ADC1 GPIO Configuration
PC0 ------> ADC1_IN10
PC1 ------> ADC1_IN11
PC2 ------> ADC1_IN12
PC3 ------> ADC1_IN13
PA0-WKUP ------> ADC1_IN0
PA1 ------> ADC1_IN1
/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/
ADC1 DMA Init /
/
ADC1 Init /
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_adc1);
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
/
USER CODE BEGIN ADC1_MspInit 1 /
/
USER CODE END ADC1_MspInit 1 /
}
}
void MX_ADC1_Init(void)
{
/
USER CODE BEGIN ADC1_Init 0 /
/
USER CODE END ADC1_Init 0 /
ADC_ChannelConfTypeDef sConfig = {0};
/
USER CODE BEGIN ADC1_Init 1 /
/
USER CODE END ADC1_Init 1 /
/
Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 6;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);
/
Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = 2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
* Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_13;
sConfig.Rank = 3;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
* Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = 4;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
* Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = 5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
* Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
/
sConfig.Channel = ADC_CHANNEL_10;
sConfig.Rank = 6;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/
USER CODE BEGIN ADC1_Init 2 /
/
USER CODE END ADC1_Init 2 /
}
void DMA2_Stream0_IRQHandler(void)
{
/
USER CODE BEGIN DMA2_Stream0_IRQn 0 /
/
USER CODE END DMA2_Stream0_IRQn 0 /
HAL_DMA_IRQHandler(&hdma_adc1);
// rt_kprintf("11111111 n");
/
USER CODE BEGIN DMA2_Stream0_IRQn 1 /
/
USER CODE END DMA2_Stream0_IRQn 1 */
}

配置RT-Thread Setting

1.jpg

1.jpg

1.jpg

编译通过,结果如下图

1.jpg

修改drv_adc.c文件

1.jpg

编译通过,结果如下图

1.jpg

3、添加业务测试代码

新建user_adc.c源文件添加业务测试代码如下

#include
#include
#include
rt_thread_t Adc_thread1= RT_NULL;
#define ADC_MAX_SAMPLE 12
#define ADC_MAX_CHANLE 6
extern ADC_HandleTypeDef hadc1;
extern rt_uint16_t value[ADC_MAX_SAMPLE][ADC_MAX_CHANLE];
rt_uint16_t ADC_ConvertedValue[ADC_MAX_SAMPLE][ADC_MAX_CHANLE];
rt_uint16_t ADC_AverageValue[ADC_MAX_CHANLE];
extern ADC_HandleTypeDef hadc1;
static void CalADC_Average(void)
{
unsigned short i, j;
unsigned short uIntMax,uIntMin,i_Max,i_Min;
unsigned int sum;
for(i=0;i<(ADC_MAX_CHANLE);i++)
{
uIntMax = ADC_ConvertedValue[0][i];
uIntMin = ADC_ConvertedValue[1][i];
i_Max = 0; i_Min = 1;
for(j=0;j if(uIntMax uIntMax=ADC_ConvertedValue[j][i];
i_Max = j;
}
if(uIntMin>ADC_ConvertedValue[j][i]){
uIntMin=ADC_ConvertedValue[j][i];
i_Min = j;
}
}
ADC_ConvertedValue[i_Max][i]=0;
ADC_ConvertedValue[i_Min][i]=0;
sum = 0;
for(j=0; j sum += ADC_ConvertedValue[j][i];
}
if(i_Min==i_Max){
ADC_AverageValue[i] = sum/(ADC_MAX_SAMPLE-1)/11.91;
}
else {
ADC_AverageValue[i] = sum/(ADC_MAX_SAMPLE-2)/11.91;
}
}
}
static void Adc_entry(void *parameter)
{
HAL_ADC_Start_DMA(&hadc1, ADC_ConvertedValue, (uint32_t)(ADC_MAX_SAMPLE * ADC_MAX_CHANLE));
while (1)
{
CalADC_Average();
rt_kprintf("/************************/n");
rt_kprintf("avg0 is :%d n",ADC_AverageValue[0]);
rt_kprintf("avg1 is :%d n",ADC_AverageValue[1]);
rt_kprintf("avg2 is :%d n",ADC_AverageValue[2]);
rt_kprintf("avg3 is :%d n",ADC_AverageValue[3]);
rt_kprintf("avg4 is :%d n",ADC_AverageValue[4]);
rt_kprintf("avg5 is :%d n",ADC_AverageValue[5]);
rt_thread_mdelay(500);
}
}
static int adc_deal(void)
{
rt_err_t ret = RT_EOK;
/*创建第一个线程,用于采集IN8的值*/
Adc_thread1 = rt_thread_create("adc1",
Adc_entry,
(void*)0,
512,
16,
20);
if(Adc_thread1 != RT_NULL)
rt_thread_startup(Adc_thread1);
else
ret = RT_ERROR;
return ret;
}
INIT_APP_EXPORT(adc_deal);

测试结果

本测试板模拟量是采集4~20MA电流。使用信号发生器输出电流信号对各个通道测试正常。下图是对chanle_10通道采集数据(12MA电流显示118。其他通道接输入信号也可以正常采集,其他通道不超过40为干扰信号,不会计入有效采集)。

1.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • adc
    adc
    +关注

    关注

    95

    文章

    5654

    浏览量

    539583
  • 信号发生器
    +关注

    关注

    28

    文章

    1278

    浏览量

    107776
  • dma
    dma
    +关注

    关注

    3

    文章

    536

    浏览量

    99116
  • ADC采样
    +关注

    关注

    0

    文章

    126

    浏览量

    12712
  • RTThread
    +关注

    关注

    7

    文章

    129

    浏览量

    40525
  • STM32F407VET6
    +关注

    关注

    1

    文章

    5

    浏览量

    2762
收藏 人收藏

    评论

    相关推荐

    使用STM32L031F6在hal库进行ADC+DMA多通道采集,采集的电压值始终为0的原因?

    使用STM32L031F6芯片 在hal库进行ADC+DMA多通道采集时候,采集的电压值始终为0是什么原因?
    发表于 03-14 07:06

    stm32cubemx建立多通道ADC+DMA,想使用DMA中断要怎么实现?

    各位大神: 我在用stm32 cubemx建立ADC+DMA多通道,想使用DMA中断,百度了个设置在DMA里增加ADC1,然后在中断里开启DMA
    发表于 04-02 07:14

    STM32G4 ADC+DMA中断异常是什么原因导致的?

    高级定时器1 3路互补pwm ,pwm ch4 触发adc,出现的问题是 单独启动pwm ch4 adc+dma 正常,如果不启动ch4正常情况是不会触发 adc+dma中断,但是正常启动3路互补PWM 没启动pwm ch4 情
    发表于 04-02 06:52

    请问stm32F302有16个通道是用ADC+DMA的方式转换多个通道的模拟量吗?

    看stm32f302c8的芯片资料,里面的ADC只有一个,但有16个通道,请问用ADC+DMA的方式转换多个通道的模拟量吗?求高手帮忙解答
    发表于 09-26 09:25

    为什么STM32F103C8T6加上ADC+DMA后液晶不能显示?

    STM32F103C8T6加上ADC+DMA后,液晶不能显示,但是ADC+DMA使用正常,液晶是LCM19264,已经检查了I/O没有冲突,具体配置如下: 说明: 一:I/O口: 1:LCD
    发表于 08-16 05:12

    STM32多通道ADC+DMA为什么无法进入中断

    STM32 多通道ADC+DMA无法进入中断问题中断函数名称不一致stm32f10x_it.c 中断名称DMA1_ChanneMl1_IRQHandler.启动文件DMA1_Channel1_IRQHandler
    发表于 08-02 08:33

    STM32F103定时器触发ADC+DMA传输 精选资料分享

    STM32F103定时器触发ADC+DMA传输ADC除了软件触发方式之外还有外部触发模式,我用TIM2定时器触发ADC,并用DMA传输ADC
    发表于 08-11 06:05

    MM32F103 ADC+DMA 多通道采样

    MM32F103 ADC+DMA 多通道采样请问软件如何配置?
    发表于 08-27 14:48

    怎样去解决STM32多通道ADC+DMA无法进入中断的问题

    STM32多通道ADC+DMA为什么会无法进入中断呢?怎样去解决STM32多通道ADC+DMA无法进入中断的问题?
    发表于 09-26 08:04

    如何对单缓冲模式的ADC+DMA如何进行配置

    怎样去操作单缓冲模式的ADC+DMA呢?如何对单缓冲模式的ADC+DMA如何进行配置?
    发表于 10-18 09:29

    STM32F407的ADC+DMA该如何去使用呢

    怎样去读取ADC的值?STM32F407的ADC+DMA该如何去使用呢?
    发表于 10-18 08:34

    请问一在RT-Thread studio上怎样去添加ADC+DMA呢?

    请问一在RT-Thread studio上怎样去添加ADC+DMA呢?
    发表于 10-11 10:33

    对一起特殊故障处理的成功经验

    对一起特殊故障处理的成功经验
    发表于 05-26 13:40 21次下载

    STM32F103定时器触发ADC+DMA传输

    STM32F103定时器触发ADC+DMA传输ADC除了软件触发方式之外还有外部触发模式,我用TIM2定时器触发ADC,并用DMA传输ADC
    发表于 11-30 10:36 50次下载
    STM32F103定时器触发<b class='flag-5'>ADC+DMA</b>传输

    STM32U5 ADC+DMA配置演示

    随意选择ADC1的4个通道,扫描模式,连续转换,DMA传输转换结果并令DMA工作在外设字到内存字的循环传输模式。使用CubeMx进行配置。其中DMA通道使用Channel 1。
    的头像 发表于 07-29 16:19 867次阅读
    STM32U5 <b class='flag-5'>ADC+DMA</b>配置演示