news 2026/7/28 7:42:00

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博客

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

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

完成了队列的发送接收测试以及对ADC触发的中断函数进行了编写

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

本期目标

理清本工程系统框架

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

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

梳理代码设计流程

xQueueSendFromISR()

当你在中断里面发送这个函数的时候 , 如果有优先级更高的队列接收任务,正在等待队列唤醒,他会在发送队列的过程中立马切换任务, 去执行优先级更高的任务 , 以保证系统的实时性

对于立刻切换的这个动作 , 一定会使用PendSV中断 , 但是这个中断在任何时候优先级都是最低的 , 所以就不可能在我们当前这个DMA里面去中断

所以在这里用这个函数会被卡死

ret_queue = xQueueSend( xQueue1, &dma_pattern_cplt, 0 );

而xQueueSendFromISR这个函数相较于xQueueSend , 在任务切换时做了一个延迟的动作

xHigherPriorityTaskWoken

在发送过程中,这个函数(xQueueSendFromISR)如果发现有更高优先级的任务要切换 , 它将会把xHigherPriorityTaskWoken置为true

如果xHigherPriorityTaskWoken置为true了 , 系统就会暂时先把PendSV置位,等退出了当前中断函数,并且比PendSV更高优先级的中断都结束了,再去执行PendSV

if( xHigherPriorityTaskWoken ) { taskYIELD (); }

就是这个taskYIELD , 其原理就是会在这里进行一个悬起 ,在离开这个中断之后就会立即响应此悬起 , 从而完成任务切换

注意:

xQueue1 = xQueueCreate(10 , 4 ); if(NULL == xQueue1) { printf("Queue create failed \r\n"); return ; }

创建队列的代码要放在ADC启动前 ,ADC一启动,中断立马就产生,但是队列还没创建 , 会出问题

/* 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 0xA1A1A1A1 /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ extern ADC_HandleTypeDef hadc1; extern DMA_HandleTypeDef hdma_adc1; QueueHandle_t xQueue1 = NULL; /* 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 */ 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; ret_queue = xQueueReceive( xQueue1, &queue_data_2, 0 ); printf("xQueueSend ret_queue = [%ld]\r\n" , ret_queue); printf("xQueueReceive queue_data_2 = [%d]\r\n" , queue_data_2); /* Infinite loop */ for(;;) { printf("hello world \r\n"); //printf("buffer1 data = [%d] \r\n" , buffer1[0]); //printf("buffer2 data = [%d] \r\n" , buffer2[0]); 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; 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/7/26 12:26:20

干货!大数据数据增强的实际应用技巧

大数据环境下数据增强的实战宝典&#xff1a;用更少的数据、更大的价值 标题选项&#xff1a; 数据稀缺不再是瓶颈&#xff01;大数据场景下数据增强的硬核实战技巧从1TB到10万维&#xff1a;揭秘工业级大数据增强的核心技术与避坑指南高维、稀疏、不均衡&#xff1f;大数据增强…

作者头像 李华
网站建设 2026/7/28 3:29:50

大数据领域中Power BI与其他工具的对比分析

大数据领域中Power BI与其他工具的对比分析关键词&#xff1a;大数据、Power BI、对比分析、数据可视化、数据分析工具摘要&#xff1a;本文聚焦于大数据领域&#xff0c;对Power BI与其他常见数据分析和可视化工具进行全面的对比分析。通过深入探讨各工具的核心概念、算法原理…

作者头像 李华
网站建设 2026/7/21 15:47:07

ensp下载官网被屏蔽?国内镜像站提供备份资源

Qwen3-32B 模型部署困境与国内镜像的破局之道 在AI基础设施自主可控日益重要的今天&#xff0c;一个现实问题正困扰着不少企业和开发者&#xff1a;想本地部署高性能开源大模型&#xff0c;却发现官方下载源访问缓慢甚至无法连接。尤其是像 Qwen3-32B 这类体积庞大、依赖复杂的…

作者头像 李华
网站建设 2026/7/25 4:01:26

付费墙绕过技术深度解析:Bypass Paywalls Clean实现原理与应用指南

付费墙绕过技术深度解析&#xff1a;Bypass Paywalls Clean实现原理与应用指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在数字内容付费订阅日益普及的今天&#xff0c;如何合理…

作者头像 李华
网站建设 2026/7/25 3:24:47

小米运动步数自动同步工具:2025年免费刷步数完整教程

小米运动步数自动同步工具&#xff1a;2025年免费刷步数完整教程 【免费下载链接】mimotion 小米运动刷步数&#xff08;微信支付宝&#xff09;支持邮箱登录 项目地址: https://gitcode.com/gh_mirrors/mimo/mimotion 小米运动步数自动同步工具是一款专门为Zepp Life用…

作者头像 李华
网站建设 2026/7/24 10:49:34

Ubuntu安装GNOME桌面增强PyTorch开发体验

Ubuntu 安装 GNOME 桌面增强 PyTorch 开发体验 在深度学习项目开发中&#xff0c;很多开发者都曾面临这样的困境&#xff1a;好不容易配置好 CUDA 和 PyTorch 环境&#xff0c;却因为缺乏图形界面而无法直观查看训练曲线&#xff1b;想拖拽上传数据集时只能靠 scp 命令反复折腾…

作者头像 李华