梳理STM32F429之通信传输部分---NO.3 串口空闲IDEL中断+DMA+FreeRTOS
梳理STM32F429之通信傳輸部分---NO.3 串口空閑IDEL中斷+DMA+FreeRTOS
目錄
一、串口空閑IDEL中斷:
二、串口及串口中斷的配置:
三、stm32f4xx_it.h 的配置:
四、DMA?的配置:
五、主函數
如果大家有什么問題,歡迎在下面評論交流!
串口部分的詳解:梳理STM32F429之通信傳輸部分---NO.1 串口通訊
DMA直接存儲器訪問:梳理STM32F429之通信傳輸部分---NO.2 DMA—直接存儲區訪問
FreeRTOS-二值信號量:從0到1學習FreeRTOS:FreeRTOS 內核應用開發:(十一)信號量 NO.1 基本概念
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??從0到1學習FreeRTOS:FreeRTOS 內核應用開發:(十二)信號量 NO.2 常用信號量函數接口講解
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 從0到1學習FreeRTOS:FreeRTOS 內核應用開發:(十三)信號量 NO.3 信號量實驗
這里補充一下:串口空閑IDEL中斷的一些注意事項:
一、串口空閑IDEL中斷:
1、串口空閑IDEL中斷的作用:
? ? ? ?現在有很多數據處理都要用到不定長數據,而單片機串口的RXNE中斷一次只能接收一個字節的數據,沒有緩沖區,無法接收一幀多個數據,利用串口IDLE空閑中斷的方式接收一幀數據,方法如下:
? ? ? ?實現思路:采用STM32F429的串口1,并配置成空閑中斷IDLE模式且使能DMA接收,并同時設置接收緩沖區和初始化DMA。那么初始化完成之后,當外部給單片機發送數據的時候,假設這幀數據長度是200個字節,那么在單片機接收到一個字節的時候并不會產生串口中斷,而是DMA在后臺把數據默默地搬運到你指定的緩沖區里面。當整幀數據發送完畢之后串口才會產生一次中斷,此時可以利用DMA_GetCurrDataCounter();函數計算出本次的數據接受長度,從而進行數據處理。
2、注意事項:避免一直進入空閑中斷!
? ? ? ?空閑中斷是在檢測到在數據收受后,總線上在一個字節的時間內沒有再接收到數據時發生。即串口的RXNE位被置位之后才開始檢測,檢測到空閑之后,串口的CR1寄存器的IDLE位被硬件置1,必須采用軟件將IDLE位清零才能避免反復進入空閑中斷。具體的做法是先讀取USART_SR,再讀取USART_DR。需要注意的是,不能采用庫函數USART_ClearFlag()或者USART_ClearItPending()來清除IDEL標志位。
USART_ReceiveData(USART1); 清除標志位二、串口及串口中斷的配置:
bsp_usart.c
/********************************************************************************* @file bsp_usart.c* @author Sumjess* @version V1.0* @date 2019-09-xx* @brief MDK5.27******************************************************************************* @attention** 實驗平臺 :STM32 F429 * CSDN Blog :https://blog.csdn.net/qq_38351824* 微信公眾號 :Tech云********************************************************************************/#include "bsp_usart.h"/*** @brief 配置嵌套向量中斷控制器NVIC* @param 無* @retval 無*/// 中斷服務函數 在#include "stm32f4xx_it.h"中 為了防止寫錯中斷服務函數,請去startup_stm32f429_439xx.s中粘貼 static void NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中斷控制器組選擇 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/* 配置USART為中斷源 */NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; //USART1_IRQn 串口1/* 搶斷優先級為1 */NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;/* 子優先級為1 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;/* 使能中斷 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure); }void Debug_USART_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure; / //--------------------------------------串口1--------------------------------------------------///* -----------------------------串口相關的GPIO初始化-------------------------------------- */ RCC_AHB1PeriphClockCmd(DEBUG_USART1_RX_GPIO_CLK|DEBUG_USART1_TX_GPIO_CLK,ENABLE);/* 使能 USART 時鐘 */RCC_APB2PeriphClockCmd(DEBUG_USART1_CLK, ENABLE); //注意!只有串口1和6是APB2為90M,其他均為APB1為45M/* GPIO初始化 */GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //輸出推挽GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHZ/* 配置Tx引腳為復用功能 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART1_TX_PIN ;//GPIO_Pin_9 GPIO_Init(DEBUG_USART1_TX_GPIO_PORT, &GPIO_InitStructure); //GPIOA/* 配置Rx引腳為復用功能 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART1_RX_PIN; //GPIO_Pin_10 GPIO_Init(DEBUG_USART1_RX_GPIO_PORT, &GPIO_InitStructure);/* 連接 PXx 到 USARTx_Tx*/GPIO_PinAFConfig(DEBUG_USART1_RX_GPIO_PORT,DEBUG_USART1_RX_SOURCE,DEBUG_USART1_RX_AF);//GPIOA---9---GPIO_AF_USART1/* 連接 PXx 到 USARTx__Rx*/GPIO_PinAFConfig(DEBUG_USART1_TX_GPIO_PORT,DEBUG_USART1_TX_SOURCE,DEBUG_USART1_TX_AF);//GPIOA--10---GPIO_AF_USART1/* -----------------------------串口配置-------------------------------------- */ /* 配置串DEBUG_USART 模式 *//* 波特率設置:DEBUG_USART_BAUDRATE */USART_InitStructure.USART_BaudRate = DEBUG_USART1_BAUDRATE; //115200 串口波特率/* 字長(數據位+校驗位):8 */USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* 停止位:1個停止位 */USART_InitStructure.USART_StopBits = USART_StopBits_1; /* 校驗位選擇:不使用校驗 */USART_InitStructure.USART_Parity = USART_Parity_No; /* 硬件流控制:不使用硬件流 */ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;/* USART模式控制:同時使能接收和發送 */USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;/* 完成USART初始化配置 */USART_Init(DEBUG_USART1, &USART_InitStructure);/* 配置串口的接收中斷 */NVIC_Configuration();/ //USART_IT_IDLE和USART_IT_RXNE區別 //當接收到1個字節,會產生USART_IT_RXNE中斷 //當接收到一幀數據,就會產生USART_IT_IDLE中斷// 開啟 串口空閑IDEL 中斷USART_ITConfig(DEBUG_USART1, USART_IT_IDLE, ENABLE); // /* 使能串口接收中斷 */ // USART_ITConfig(DEBUG_USART1, USART_IT_RXNE, ENABLE); //* 使能串口 */USART_Cmd(DEBUG_USART1, ENABLE); }/***************** 發送一個字符 **********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) {/* 發送一個字節數據到USART */USART_SendData(pUSARTx,ch);/* 等待發送數據寄存器為空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }/***************** 發送一個16位數 **********************/ void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch) {uint8_t temp_h, temp_l;/* 取出高八位 */temp_h = (ch&0XFF00)>>8;/* 取出低八位 */temp_l = ch&0XFF;/* 發送高八位 */USART_SendData(pUSARTx,temp_h); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);/* 發送低八位 */USART_SendData(pUSARTx,temp_l); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }/***************** 發送字符串 **********************/ void Usart_SendString( USART_TypeDef * pUSARTx, char *str) {unsigned int k=0;do {Usart_SendByte( pUSARTx, *(str + k) );k++;} while(*(str + k)!='\0');/* 等待發送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET){} }//重定向c庫函數printf到串口,重定向后可使用printf函數 int fputc(int ch, FILE *f) {/* 發送一個字節數據到串口 */USART_SendData(DEBUG_USART_printf_choose, (uint8_t) ch);/* 等待發送完畢 */while (USART_GetFlagStatus(DEBUG_USART_printf_choose, USART_FLAG_TXE) == RESET); return (ch); }//重定向c庫函數scanf到串口,重寫向后可使用scanf、getchar等函數 int fgetc(FILE *f) {/* 等待串口輸入數據 */while (USART_GetFlagStatus(DEBUG_USART_printf_choose, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(DEBUG_USART_printf_choose); }bsp_usart.h
#ifndef __BSP_USART_H #define __BSP_USART_H /********************************************************************************* @file bsp.usart.c* @author Sumjess* @version V1.0* @date 2019-09-10* @brief MDK5.27******************************************************************************* @attention** 實驗平臺 :STM32 F429 * CSDN Blog :https://blog.csdn.net/qq_38351824* 微信公眾號 :Tech云********************************************************************************/ #include "stm32f4xx.h" #include <stdio.h> //---------------------------------------------------------------------------------------------// // //① 重定向c庫函數printf到串口,重定向后可使用printf等函數 //② 重定向c庫函數scanf到串口,重寫向后可使用scanf、getchar等函數 //選擇使用串口被允許使用 ① ② #define DEBUG_USART_printf_choose DEBUG_USART1 ////------------------------------------------------------// //引腳定義 /*******************************************************/#define DEBUG_USART1 USART1 #define DEBUG_USART1_CLK RCC_APB2Periph_USART1 //注意!只有串口1和6是APB2為90M,其他均為APB1為45M #define DEBUG_USART1_BAUDRATE 115200 //串口波特率#define DEBUG_USART1_RX_GPIO_PORT GPIOA #define DEBUG_USART1_RX_GPIO_CLK RCC_AHB1Periph_GPIOA #define DEBUG_USART1_RX_PIN GPIO_Pin_10 #define DEBUG_USART1_RX_AF GPIO_AF_USART1 //映射 #define DEBUG_USART1_RX_SOURCE GPIO_PinSource10 //!!!一個引腳有許多功能,通過映射將引腳與你要選的功能連接起來。 #define DEBUG_USART1_TX_GPIO_PORT GPIOA #define DEBUG_USART1_TX_GPIO_CLK RCC_AHB1Periph_GPIOA #define DEBUG_USART1_TX_PIN GPIO_Pin_9 #define DEBUG_USART1_TX_AF GPIO_AF_USART1 //映射 #define DEBUG_USART1_TX_SOURCE GPIO_PinSource9//中斷部分配置// #define DEBUG_USART_IRQHandler USART1_IRQHandler #define DEBUG_USART_IRQ USART1_IRQn //串口1中斷void Debug_USART_Config(void); //串口初始化 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch); //發送一個字符 void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch);//發送一個16位數 void Usart_SendString( USART_TypeDef * pUSARTx, char *str); //發送字符串 int fputc(int ch, FILE *f); //重定向c庫函數printf到串口,重定向后可使用printf函數 int fgetc(FILE *f); //重定向c庫函數scanf到串口,重寫向后可使用scanf、getchar等函數三、stm32f4xx_it.h 的配置:
/* 聲明引用外部二值信號量 */ extern SemaphoreHandle_t BinarySem_Handle;void USART1_IRQHandler(void) {uint32_t ulReturn;/* 進入臨界段,臨界段可以嵌套 */ulReturn = taskENTER_CRITICAL_FROM_ISR();if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET){ Uart_DMA_Rx_Data(); /* 釋放一個信號量,表示數據已接收 */USART_ReceiveData(USART1); /* 清除標志位 */} /* 退出臨界段 */taskEXIT_CRITICAL_FROM_ISR( ulReturn ); }四、DMA?的配置:
bsp_DMA.c
char RevBuff[REVBUFF_SIZE];void USART1_RX_DMA_Config(void) {DMA_InitTypeDef DMA_InitStructure;// 開啟DMA時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);// DMA復位DMA_DeInit(USART1_RX_DMA_STREAM); // 設置DMA通道DMA_InitStructure.DMA_Channel = USART1_DMA_CHANNEL; /*設置DMA源:串口數據寄存器地址*/DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART1_DR_BASE;// 內存地址(要傳輸的變量的指針)DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RevBuff;// 方向:從內存到外設 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;// 傳輸大小 DMA_InitStructure.DMA_BufferSize = (uint32_t)REVBUFF_SIZE;// 外設地址不增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 內存地址自增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 外設數據單位 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// 內存數據單位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // DMA模式,一次或者循環模式//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 優先級:中 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; // 禁止內存到內存的傳輸/*禁用FIFO*/DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; /*存儲器突發傳輸 1個節拍*/DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; /*外設突發傳輸 1個節拍*/DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; /*配置DMA2的數據流7*/ DMA_Init(USART1_RX_DMA_STREAM, &DMA_InitStructure);// 清除DMA所有標志DMA_ClearFlag(USART1_RX_DMA_STREAM,DMA_FLAG_TCIF2);DMA_ITConfig(USART1_RX_DMA_STREAM, DMA_IT_TE, ENABLE);// 開啟串口DMA接收USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); // 使能DMADMA_Cmd (USART1_RX_DMA_STREAM,ENABLE); }信號量 extern SemaphoreHandle_t BinarySem_Handle;void Uart_DMA_Rx_Data(void) {BaseType_t pxHigherPriorityTaskWoken;// 關閉DMA ,防止干擾DMA_Cmd(USART1_RX_DMA_STREAM, DISABLE); // 清DMA標志位DMA_ClearFlag(USART1_RX_DMA_STREAM,DMA_FLAG_TCIF2); // 重新賦值計數值,必須大于等于最大可能接收到的數據幀數目DMA_SetCurrDataCounter(USART1_RX_DMA_STREAM,REVBUFF_SIZE); DMA_Cmd(USART1_RX_DMA_STREAM, ENABLE); /* xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken);*///給出二值信號量 ,發送接收到新數據標志,供前臺程序查詢xSemaphoreGiveFromISR(BinarySem_Handle,&pxHigherPriorityTaskWoken); //釋放二值信號量//如果需要的話進行一次任務切換,系統會判斷是否需要進行切換portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);}bsp_DMA.h
/*存儲器到外設串口1TX*/ #define USART1_DR_BASE (uint32_t)(&USART1->DR) //數據發送到 USART_DR 寄存器,該寄存器相對 USART 偏移地址為0x04 #define SENDBUFF_SIZE 5000 //發送的數據量 小于65535#define USART1_DMA_CLK RCC_AHB1Periph_DMA2 #define USART1_DMA_CHANNEL DMA_Channel_4 //通道4 #define USART1_TX_DMA_STREAM DMA2_Stream7 //數據流 7 /*存儲器到外設串口1RX*/ #define USART1_DR_BASE (uint32_t)(&USART1->DR) //數據發送到 USART_DR 寄存器,該寄存器相對 USART 偏移地址為0x04 #define REVBUFF_SIZE 5000 //接收的數據量 小于65535#define USART1_DMA_CLK RCC_AHB1Periph_DMA2 #define USART1_DMA_CHANNEL DMA_Channel_4 //通道4 #define USART1_RX_DMA_STREAM DMA2_Stream2 //數據流 2void USART1_TX_DMA_Config(void); void USART1_RX_DMA_Config(void); void Uart_DMA_Rx_Data(void);五、主函數
/********************************************************************************* @file main.c* @author Sumjess* @version V1.0* @date 2019-09-xx* @brief MDK5.27******************************************************************************* @attention** 實驗平臺 :STM32 F429 * CSDN Blog :https://blog.csdn.net/qq_38351824* 微信公眾號 :Tech云********************************************************************************//* ************************************************************************* * 包含的頭文件 ************************************************************************* */ /* 標準庫頭文件 */ #include <string.h>/* FreeRTOS頭文件 */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" //消息隊列 #include "semphr.h" //信號量、互斥信號量 #include "event_groups.h" //事件 #include "timers.h" //軟件定時器/* 開發板硬件bsp頭文件 */ #include "sum_common.h" #include "limits.h" //任務通知使用的 /**************************** 任務句柄 ********************************/ /* * 任務句柄是一個指針,用于指向一個任務,當任務創建好之后,它就具有了一個任務句柄* 以后我們要想操作這個任務都需要通過這個任務句柄,如果是自身的任務操作自己,那么* 這個句柄可以為NULL。*/ static TaskHandle_t AppTaskCreate_Handle = NULL;/* 創建任務句柄 */static TaskHandle_t LED_Task_Handle = NULL;/* LED_Task任務句柄 */ static TaskHandle_t Uart_Task_Handle = NULL;/* KEY任務句柄 *//********************************** 內核對象句柄 *********************************/ /** 信號量,消息隊列,事件標志組,軟件定時器這些都屬于內核的對象,要想使用這些內核* 對象,必須先創建,創建成功之后會返回一個相應的句柄。實際上就是一個指針,后續我* 們就可以通過這個句柄操作這些內核對象。** 內核對象說白了就是一種全局的數據結構,通過這些數據結構我們可以實現任務間的通信,* 任務間的事件同步等各種功能。至于這些功能的實現我們是通過調用這些內核對象的函數* 來完成的* */SemaphoreHandle_t BinarySem_Handle =NULL; //二值信號量/******************************* 全局變量聲明 ************************************/ /** 當我們在寫應用程序的時候,可能需要用到一些全局變量。*/ extern char RevBuff[REVBUFF_SIZE];/********************************** 宏定義 **************************************/ /** 當我們在寫應用程序的時候,可能需要用到一些宏定義。*//* ************************************************************************* * 函數聲明 ************************************************************************* */ static void AppTaskCreate(void);/* 用于創建任務 */static void LED_Task(void* pvParameters);/* LED_Task任務實現 */ static void Uart_Task(void* pvParameters);/* KEY_Task任務實現 */static void BSP_Init(void);/* 用于初始化板載相關資源 *//****************************************************************** @brief 主函數* @param 無* @retval 無* @note 第一步:開發板硬件初始化 第二步:創建APP應用任務第三步:啟動FreeRTOS,開始多任務調度****************************************************************/ int main(void) { BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS *//* 開發板硬件初始化 */BSP_Init();printf("開發板硬件初始化完畢!\r\n");/* 創建AppTaskCreate任務 */xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任務入口函數---即任務函數的名稱,需要我們自己定義并且實現。*/(const char* )"AppTaskCreate",/* 任務名字---字符串形式, 最大長度由 FreeRTOSConfig.h 中定義的configMAX_TASK_NAME_LEN 宏指定,多余部分會被自動截掉,這里任務名字最好要與任務函數入口名字一致,方便進行調試。*/(uint16_t )512, /* 任務棧大小---字符串形式, 最大長度由 FreeRTOSConfig.h 中定義的configMAX_TASK_NAME_LEN 宏指定,多余部分會被自動截掉,這里任務名字最好要與任務函數入口名字一致,方便進行調試。*/(void* )NULL,/* 任務入口函數參數---字符串形式, 最大長度由 FreeRTOSConfig.h 中定義的configMAX_TASK_NAME_LEN 宏指定,多余部分會被自動截掉,這里任務名字最好要與任務函數入口名字一致,方便進行調試。*/(UBaseType_t )1, /* 任務的優先級---優先級范圍根據 FreeRTOSConfig.h 中的宏configMAX_PRIORITIES 決定, 如果使能 configUSE_PORT_OPTIMISED_TASK_SELECTION,這個宏定義,則最多支持 32 個優先級;如果不用特殊方法查找下一個運行的任務,那么則不強制要求限制最大可用優先級數目。在 FreeRTOS 中, 數值越大優先級越高, 0 代表最低優先級。*/(TaskHandle_t* )&AppTaskCreate_Handle);/* 任務控制塊指針---在使用內存的時候,需要給任務初始化函數xTaskCreateStatic()傳遞預先定義好的任務控制塊的指針。在使用動態內存的時候,任務創建函數 xTaskCreate()會返回一個指針指向任務控制塊,該任務控制塊是 xTaskCreate()函數里面動態分配的一塊內存。*/ /* 啟動任務調度 */ if(pdPASS == xReturn)vTaskStartScheduler(); /* 啟動任務,開啟調度 */elsereturn -1; while(1); /* 正常不會執行到這里 */ }/************************************************************************ @ 函數名 : AppTaskCreate* @ 功能說明: 為了方便管理,所有的任務創建函數都放在這個函數里面* @ 參數 : 無 * @ 返回值 : 無**********************************************************************/ static void AppTaskCreate(void) {BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */taskENTER_CRITICAL(); //進入臨界區/// /* 創建LED_Task任務 */xReturn = xTaskCreate((TaskFunction_t )LED_Task, /* 任務入口函數 */(const char* )"LED_Task",/* 任務名字 */(uint16_t )512, /* 任務棧大小 */(void* )NULL, /* 任務入口函數參數 */(UBaseType_t )2, /* 任務的優先級 */(TaskHandle_t* )&LED_Task_Handle);/* 任務控制塊指針 */if(pdPASS == xReturn)printf("創建LED_Task任務成功\r\n"); ////* 創建 BinarySem */BinarySem_Handle = xSemaphoreCreateBinary(); if(NULL != BinarySem_Handle)printf("BinarySem_Handle二值信號量創建成功!\r\n");/* 創建Uart_Task任務 */xReturn = xTaskCreate((TaskFunction_t )Uart_Task, /* 任務入口函數 */(const char* )"Uart_Task",/* 任務名字 */(uint16_t )512, /* 任務棧大小 */(void* )NULL,/* 任務入口函數參數 */(UBaseType_t )3, /* 任務的優先級 */(TaskHandle_t* )&Uart_Task_Handle);/* 任務控制塊指針 */ if(pdPASS == xReturn)printf("創建Uart_Task任務成功!\r\n"); ///vTaskDelete(AppTaskCreate_Handle); //刪除AppTaskCreate任務taskEXIT_CRITICAL(); //退出臨界區 }/*********************************************************************** @ 函數名 : LED_Task* @ 功能說明: LED_Task任務主體* @ 參數 : * @ 返回值 : 無********************************************************************/ static void LED_Task(void* parameter) { while (1){LED1_ON;vTaskDelay(500); /* 延時500個tick */printf("LED_Task Running,LED1_ON\r\n");LED1_OFF; vTaskDelay(500); /* 延時500個tick */ printf("LED_Task Running,LED1_OFF\r\n");} } /*********************************************************************** @ 函數名 : LED_Task* @ 功能說明: LED_Task任務主體* @ 參數 : * @ 返回值 : 無********************************************************************/ static void Uart_Task(void* parameter) { BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */while (1){//獲取二值信號量 xSemaphore,沒獲取到則一直等待xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信號量句柄 */portMAX_DELAY); /* 等待時間 */if(pdPASS == xReturn){LED2_TOGGLE;printf("收到數據:%s\r\n",RevBuff);memset(RevBuff,0,REVBUFF_SIZE);/* 清零 */}} }/************************************************************************ @ 函數名 : BSP_Init* @ 功能說明: 板級外設初始化,所有板子上的初始化均可放在這個函數里面* @ 參數 : * @ 返回值 : 無*********************************************************************/ static void BSP_Init(void) {/** STM32中斷優先級分組為4,即4bit都用來表示搶占優先級,范圍為:0~15* 優先級分組只需要分組一次即可,以后如果有其他的任務需要用到中斷,* 都統一用這個優先級分組,千萬不要再分組,切忌。*/NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );/* LED 初始化 */LED_GPIO_Config();/* 串口初始化 */Debug_USART_Config();/* 按鍵初始化 */Key_GPIO_Config();/* DMA初始化 */USART1_RX_DMA_Config();}/********************************END OF FILE****************************/?
?
總結
以上是生活随笔為你收集整理的梳理STM32F429之通信传输部分---NO.3 串口空闲IDEL中断+DMA+FreeRTOS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MAC设置JDK环境变量
- 下一篇: delphi 发送html邮件,delp