梳理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****************************/