news 2026/6/10 14:46:14

Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(五)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(五)

前置文章:

Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(一)-CSDN博客Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(二)-CSDN博客

Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(三)-CSDN博客Freertos手把手教STM32CubeMx设置STM32F4芯片DMA发送ADC数据(四)-CSDN博客

在以上章节完成了对框架的初步探索以及对CubeMx的配置

在freertos的task中对buffer进行了一些测试

实现了ADC的启动 ,并且进入对应中断,发送ADC转换数据到任务1 , 然后任务1进行接收并且打印的功能

但是现在看起来这个转换只能进行一次 , 下面要对代码进行改进,以实现以下功能

下面继续上一章的内容继续完成本次目标

本期目标

理清本工程系统框架

弄懂CubeMx配置相关原理及设置的背后含义

对DMA以及ADC相关的重要API接口使用详解

梳理代码设计流程

线程A接收到邮箱后,实现两个任务

  1. 任务一:将DMA的下次目标Buffer设置为Buffer2

  2. 任务二:发送消息队列(邮箱)给线程B,然后回到邮箱接收处阻塞住

先将接收移到for循环里

for(;;) { printf("hello world \r\n"); ret_queue = xQueueReceive( xQueue1, &queue_data_2, portMAX_DELAY); printf("xQueueSend ret_queue = [%ld]\r\n" , ret_queue); printf("xQueueReceive queue_data_2 = [%d]\r\n" , queue_data_2); // osDelay(1000); }

portMAX_DELAY

阻塞的意义:

如果没有接收到队列信息后,会一直阻塞在这里,知道有中断发送过来后,才会离开

邮箱

xQueue1 = xQueueCreate(10 , 4 );

每个元素的大小是四个字节

回到正题

想要实现接收邮箱的切换实际上很简单 , 设立一个标志位切换就好了

uint32_t DMA_point = 0; //
for(;;) { printf("hello world \r\n"); ret_queue = xQueueReceive( xQueue1, &queue_data_2, portMAX_DELAY); printf("xQueueSend ret_queue = [%ld]\r\n" , ret_queue); printf("xQueueReceive queue_data_2 = [%d]\r\n" , queue_data_2); if( 0 == DMA_point) { printf("buffer1 data = [%d] \r\n" , buffer1[0]); HAL_ADC_Start_DMA(&hadc1 , buffer2 , BUFFER_SIZE); //将接收下一个数据的地址换成buffer2 DMA_point = 1 ; } else { DMA_point = 0 ; printf("buffer2 data = [%d] \r\n" , buffer2[0]); HAL_ADC_Start_DMA(&hadc1 , buffer1 , BUFFER_SIZE); //将接收下一个数据的地址换成buffer2 }

在point = 0 的时候由buffer1接收

在point = 1 的时候由buffer2接收

在接收完之后对point进行对应的操作,从而切换接收数组

由此完成

可以看到数据非常丝滑的在切换

本期代码:

/* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : freertos.c * Description : Code for freertos applications ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdlib.h> #include "queue.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ #define BUFFER_SIZE 1 uint32_t * buffer1 = NULL; uint32_t * buffer2 = NULL; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ #define DMA_ADC_CPLT_INT 0xA1 /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ extern ADC_HandleTypeDef hadc1; extern DMA_HandleTypeDef hdma_adc1; QueueHandle_t xQueue1 = NULL; uint32_t DMA_point = 0; // /* USER CODE END Variables */ /* Definitions for defaultTask */ osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = { .name = "defaultTask", .stack_size = 128 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void *argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* creation of defaultTask */ defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_EVENTS */ /* add events, ... */ /* USER CODE END RTOS_EVENTS */ } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ DMA_point = 0 ;//DMA_point = 0 往buffer1存入数据 //DMA_point = 1 往buffer2存入数据 buffer1 = (uint32_t *)malloc((sizeof(uint32_t)* BUFFER_SIZE)); buffer2 = (uint32_t *)malloc((sizeof(uint32_t)* BUFFER_SIZE)); if(NULL == buffer1) { printf("buffer1 malloc failed \r\n"); } if(NULL == buffer2) { printf("buffer2 malloc failed \r\n"); return; } printf("buffer1 , buffer2 malloc success\r\n "); memset(buffer1, 0xff , (sizeof(uint32_t)* BUFFER_SIZE)); memset(buffer2, 0xff , (sizeof(uint32_t)* BUFFER_SIZE)); printf("Unit test ADC + DMA\r\n "); xQueue1 = xQueueCreate(10 , 4 ); if(NULL == xQueue1) { printf("Queue create failed \r\n"); return ; } HAL_StatusTypeDef ret1 = HAL_OK; HAL_StatusTypeDef ret2 = HAL_OK; ret1 = HAL_ADC_Start_DMA(&hadc1, buffer1, BUFFER_SIZE); ret2 = HAL_ADC_Start_DMA(&hadc1, buffer2, BUFFER_SIZE); if(HAL_OK != ret1) { printf("HAL_ADC1 call failed "); } if(HAL_OK != ret2) { printf("HAL_ADC2 call failed "); } //UnitTest Queue send and receive BaseType_t ret_queue = pdPASS; uint32_t queue_data_2 = 0xff; /* Infinite loop */ for(;;) { printf("hello world \r\n"); ret_queue = xQueueReceive( xQueue1, &queue_data_2, portMAX_DELAY); printf("xQueueSend ret_queue = [%ld]\r\n" , ret_queue); printf("xQueueReceive queue_data_2 = [%d]\r\n" , queue_data_2); if( 0 == DMA_point) { printf("buffer1 data = [%d] \r\n" , buffer1[0]); HAL_ADC_Start_DMA(&hadc1 , buffer2 , BUFFER_SIZE); //将接收下一个数据的地址换成buffer2 DMA_point = 1 ; } else { DMA_point = 0 ; printf("buffer2 data = [%d] \r\n" , buffer2[0]); HAL_ADC_Start_DMA(&hadc1 , buffer1 , BUFFER_SIZE); //将接收下一个数据的地址换成buffer2 } // osDelay(1000); } /* USER CODE END StartDefaultTask */ } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { /* Prevent unused argument(s) compilation warning */ UNUSED(hadc); /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ADC_ConvCpltCallback could be implemented in the user file */ //printf("buffer1 data = [%d] \r\n" , buffer1[0]); BaseType_t xHigherPriorityTaskWoken;//PendSV悬起置位为true xHigherPriorityTaskWoken = pdFALSE;//初始化 uint32_t dma_pattern_cplt = DMA_ADC_CPLT_INT; BaseType_t ret_queue = pdPASS; ret_queue = xQueueSendFromISR( xQueue1, &dma_pattern_cplt, &xHigherPriorityTaskWoken ); if( xHigherPriorityTaskWoken ) { taskYIELD (); } printf("QueueSend ret_queue = [%ld]\r\n" , ret_queue); } void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc) { /* Prevent unused argument(s) compilation warning */ UNUSED(hadc); /* NOTE : This function Should not be modified, when the callback is needed, the HAL_ADC_ErrorCallback could be implemented in the user file */ printf("ADC trasfer error \r\n"); } /* USER CODE END Application */
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 13:19:48

Windows 11远程桌面多用户配置指南:RDP Wrapper完整教程

还在为Windows 11只能单用户远程连接而烦恼&#xff1f;RDP Wrapper Library这款开源工具能够帮你轻松实现多用户同时远程访问功能&#xff0c;让家庭版系统也能享受企业级的远程桌面体验。无论你是IT管理员、开发者还是普通用户&#xff0c;这份完整配置手册都将为你提供简单实…

作者头像 李华
网站建设 2026/6/9 20:08:56

GitHub热门项目复现:用Qwen-Image-Edit-2509做电商产品图智能修改

GitHub热门项目复现&#xff1a;用Qwen-Image-Edit-2509做电商产品图智能修改 在电商平台的日常运营中&#xff0c;一张主图可能决定一款商品的命运。每逢大促节点&#xff0c;运营团队常常面临这样的困境&#xff1a;几十个SKU需要统一更新价格标签、替换背景文案、调整促销横…

作者头像 李华
网站建设 2026/6/8 17:08:53

9个AI论文工具推荐,本科生期末论文写作轻松搞定

9个AI论文工具推荐&#xff0c;本科生期末论文写作轻松搞定 论文写作的“战场”&#xff1a;时间紧、任务重、压力山大 对于大多数本科生来说&#xff0c;期末论文不仅是对所学知识的一次综合检验&#xff0c;更是对时间管理、写作能力与抗压能力的全面挑战。随着课程内容的不断…

作者头像 李华
网站建设 2026/6/10 11:19:50

大模型微调监控指标:跟踪Qwen3-32B训练过程

大模型微调监控指标&#xff1a;跟踪Qwen3-32B训练过程 在当前大语言模型&#xff08;LLM&#xff09;快速演进的背景下&#xff0c;企业与研究机构正面临一个关键挑战&#xff1a;如何在有限算力资源下&#xff0c;高效微调出性能接近顶级闭源模型的定制化系统。以通义千问系列…

作者头像 李华
网站建设 2026/6/9 20:47:51

8 个文献综述 AI 工具,本科生降重查重率优化推荐

8 个文献综述 AI 工具&#xff0c;本科生降重查重率优化推荐 文献综述的“重担”与时间的“紧逼” 对于大多数本科生来说&#xff0c;论文写作从来不是一件轻松的事情&#xff0c;尤其是当任务涉及到文献综述时&#xff0c;更是让人感到压力山大。文献综述不仅是对已有研究成果…

作者头像 李华