硬汉嵌入式论坛

 找回密码
 立即注册
查看: 818|回复: 3
收起左侧

[FreeRTOS] 在FreeRTOS中,一个软件定时器的回调函数中启动另一个软件定时器

[复制链接]

35

主题

106

回帖

211

积分

高级会员

积分
211
发表于 2023-9-18 19:26:13 | 显示全部楼层 |阅读模式
Snipaste_2023-09-18_19-13-54.png 图中只是一个大体的示意,在FreeRTOS中,一个软顶定时器的回调函数中启动另一个定时器:在一个软件定时器的回调函数中执行
if(xTimerStart(BBB, 0) == pdPASS)
{
        DEBUG_TRACE(debugLevel, "Successful start");
}
也已经打印出来了“Successful start”,说明指令已经发送给定时器的队列了,请问为什么定时器BBB到时间了,其软件回调函数没有执行?

回复

使用道具 举报

35

主题

106

回帖

211

积分

高级会员

积分
211
 楼主| 发表于 2023-9-18 19:29:35 | 显示全部楼层
Snipaste_2023-09-18_19-28-30.png
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2023-9-18 21:02:22 | 显示全部楼层
帮你测试了,我这里没问题,正常启动。

下载.png

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*	模块名称 : 主程序模块。
*	文件名称 : main.c
*	版    本 : V1.0
*	说    明 : 本实验主要学习FreeRTOS的定时器组
*              实验目的:
*                1. 学习FreeRTOS的定时器组
*              实验内容:
*                1. 按下按键K1可以通过串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)
*                   =================================================
*                   任务名      任务状态 优先级   剩余栈 任务序号
*                   vTaskUserIF     R       1       320     1
*                   IDLE            R       0       117     5
*                   Tmr Svc         B       2       224     6
*                   vTaskMsgPro     B       3       483     3
*                   vTaskLED        B       2       483     2
*                   vTaskStart      B       4       489     4
*                   
*                   任务名       运行计数         使用率
*                   vTaskUserIF     641             <1%
*                   IDLE            171716          99%
*                   vTaskMsgPro     0               <1%
*                   vTaskLED        0               <1%
*                   vTaskStart      1               <1%
*                   Tmr Svc         43              <1%
*                  串口软件建议使用SecureCRT(V6光盘里面有此软件)查看打印信息。
*                  各个任务实现的功能如下:
*                   vTaskTaskUserIF 任务: 接口消息处理	
*                   vTaskLED        任务: LED闪烁
*                   vTaskMsgPro     任务: 消息处理,这里用作LED闪烁
*                   vTaskStart      任务: 启动任务,也就是最高优先级任务,这里实现按键扫描
*                2. 任务运行状态的定义如下,跟上面串口打印字母B, R, D, S对应:
*                    #define tskBLOCKED_CHAR		( 'B' )  阻塞
*                    #define tskREADY_CHAR		    ( 'R' )  就绪
*                    #define tskDELETED_CHAR		( 'D' )  删除
*                    #define tskSUSPENDED_CHAR	    ( 'S' )  挂起
*                3. 创建两个软件定时器。
*              注意事项:
*                1. 本实验推荐使用串口软件SecureCRT,要不串口打印效果不整齐。此软件在
*                   V6开发板光盘里面有。
*                2. 务必将编辑器的缩进参数和TAB设置为4来阅读本文件,要不代码显示不整齐。
*
*	修改记录 :
*		版本号    日期         作者            说明
*       V1.0    2016-03-15   Eric2013    1. ST固件库到V1.6.1版本
*                                        2. BSP驱动包V1.2
*                                        3. FreeRTOS版本V8.2.3
*
*	Copyright (C), 2016-2020, 安富莱电子 [url]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "includes.h"


/*
**********************************************************************************************************
											函数声明
**********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters);
static void vTaskLED(void *pvParameters);
static void vTaskMsgPro(void *pvParameters);
static void vTaskStart(void *pvParameters);
static void AppTaskCreate (void);
static void AppObjCreate (void);
static void vTimerCallback(xTimerHandle pxTimer);

/*
**********************************************************************************************************
											变量声明
**********************************************************************************************************
*/
static TaskHandle_t xHandleTaskUserIF = NULL;
static TaskHandle_t xHandleTaskLED = NULL;
static TaskHandle_t xHandleTaskMsgPro = NULL;
static TaskHandle_t xHandleTaskStart = NULL;
static TimerHandle_t xTimers[2] = {NULL};

/*
*********************************************************************************************************
*	函 数 名: main
*	功能说明: 标准c程序入口。
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
int main(void)
{
	/* 
	  在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
	  这样做的好处是:
	  1. 防止执行的中断服务程序中有FreeRTOS的API函数。
	  2. 保证系统正常启动,不受别的中断影响。
	  3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
	  在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
	  和cpsie i是等效的。
     */
	__set_PRIMASK(1);  
	
	/* 硬件初始化 */
	bsp_Init(); 
	
	/* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
		  目中不要使用,因为这个功能比较影响系统实时性。
	   2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。 
	*/
	vSetupSysInfoTest();
	
	/* 创建任务 */
	AppTaskCreate();

	/* 创建任务通信机制 */
	AppObjCreate();
	
    /* 启动调度,开始执行任务 */
    vTaskStartScheduler();

	/* 
	  如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
	  heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
	  #define configTOTAL_HEAP_SIZE	      ( ( size_t ) ( 17 * 1024 ) )
	*/
	while(1);
}

/*
*********************************************************************************************************
*	函 数 名: vTaskTaskUserIF
*	功能说明: 接口消息处理。
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters)
{
	uint8_t ucKeyCode;
	uint8_t pcWriteBuffer[500];

    while(1)
    {
		ucKeyCode = bsp_GetKey();
		
		if (ucKeyCode != KEY_NONE)
		{
			switch (ucKeyCode)
			{
				/* K1键按下 打印任务执行情况 */
				case KEY_DOWN_K1:			 
					printf("=================================================\r\n");
					printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
					vTaskList((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
				
					printf("\r\n任务名       运行计数         使用率\r\n");
					vTaskGetRunTimeStats((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
					break;
				
				/* 其他的键值不处理 */
				default:                     
					break;
			}
		}
		
		vTaskDelay(20);
	}
}

/*
*********************************************************************************************************
*	函 数 名: vTaskLED
*	功能说明: LED闪烁	
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 2  
*********************************************************************************************************
*/
static void vTaskLED(void *pvParameters)
{
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 200;

	/* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
	
    while(1)
    {
		bsp_LedToggle(3);
		
		/* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
        vTaskDelayUntil(&xLastWakeTime, xFrequency);
    }
}

/*
*********************************************************************************************************
*	函 数 名: vTaskMsgPro
*	功能说明: 消息处理,这里用作LED闪烁
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 200;

	/* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
	
    while(1)
    {
		bsp_LedToggle(4);
		
		/* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
        vTaskDelayUntil(&xLastWakeTime, xFrequency);
    }
}

/*
*********************************************************************************************************
*	函 数 名: vTaskStart
*	功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 4  
*********************************************************************************************************
*/
static void vTaskStart(void *pvParameters)
{
    while(1)
    {
		/* 按键扫描 */
		bsp_KeyScan();
        vTaskDelay(10);
    }
}
				
/*
*********************************************************************************************************
*	函 数 名: AppTaskCreate
*	功能说明: 创建应用任务
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
static void AppTaskCreate (void)
{
    xTaskCreate( vTaskTaskUserIF,   	/* 任务函数  */
                 "vTaskUserIF",     	/* 任务名    */
                 512,               	/* 任务栈大小,单位word,也就是4字节 */
                 NULL,              	/* 任务参数  */
                 1,                 	/* 任务优先级*/
                 &xHandleTaskUserIF );  /* 任务句柄  */
	
	
	xTaskCreate( vTaskLED,    		/* 任务函数  */
                 "vTaskLED",  		/* 任务名    */
                 512,         		/* stack大小,单位word,也就是4字节 */
                 NULL,        		/* 任务参数  */
                 2,           		/* 任务优先级*/
                 &xHandleTaskLED ); /* 任务句柄  */
	
	xTaskCreate( vTaskMsgPro,     		/* 任务函数  */
                 "vTaskMsgPro",   		/* 任务名    */
                 512,             		/* 任务栈大小,单位word,也就是4字节 */
                 NULL,           		/* 任务参数  */
                 3,               		/* 任务优先级*/
                 &xHandleTaskMsgPro );  /* 任务句柄  */
	
	
	xTaskCreate( vTaskStart,     		/* 任务函数  */
                 "vTaskStart",   		/* 任务名    */
                 512,            		/* 任务栈大小,单位word,也就是4字节 */
                 NULL,           		/* 任务参数  */
                 4,              		/* 任务优先级*/
                 &xHandleTaskStart );   /* 任务句柄  */
}

/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
	uint8_t i;
	const TickType_t  xTimerPer[2] = {100, 100};
static void AppObjCreate (void)
{

	
	/* 
	  1. 创建定时器,如果在RTOS调度开始前初始化定时器,那么系统启动后才会执行。
	  2. 统一初始化两个定时器,他们使用共同的回调函数,在回调函数中通过定时器ID来区分
	     是那个定时器的时间到。当然,使用不同的回调函数也是没问题的。
	*/
	for(i = 0; i < 1; i++)
	{
		xTimers[i] = xTimerCreate("Timer",          /* 定时器名字 */
							       xTimerPer[i],    /* 定时器周期,单位时钟节拍 */
							       pdFALSE,          /* 周期性 */
							       (void *) i,      /* 定时器ID */
							       vTimerCallback); /* 定时器回调函数 */

		if(xTimers[i] == NULL)
		{
			/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
		}
		else
		{
			 /* 启动定时器,系统启动后才开始工作 */
			 if(xTimerStart(xTimers[i], 100) != pdPASS)
			 {
				 /* 定时器还没有进入激活状态 */
			 }
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: vTimerCallback
*	功能说明: 定时器回调函数
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void vTimerCallback(xTimerHandle pxTimer)
{
	uint32_t ulTimerID;

	configASSERT(pxTimer);

	/* 获取那个定时器时间到 */
	ulTimerID = (uint32_t)pvTimerGetTimerID(pxTimer);
	
	/* 处理定时器0任务 */
	if(ulTimerID == 0)
	{
//		bsp_LedToggle(1);
		for(i = 1; i < 2; i++)
		{
			xTimers[i] = xTimerCreate("Timer",          /* 定时器名字 */
									   xTimerPer[i],    /* 定时器周期,单位时钟节拍 */
									   pdFALSE,          /* 周期性 */
									   (void *) i,      /* 定时器ID */
									   vTimerCallback); /* 定时器回调函数 */

			if(xTimers[i] == NULL)
			{
				printf("ulTimerID000");
				/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
			}
			else
			{
				 /* 启动定时器,系统启动后才开始工作 */
				 if(xTimerStart(xTimers[i], 100) != pdPASS)
				 {
					 /* 定时器还没有进入激活状态 */
					 printf("ulTimerID1111");
				 }
			}
		}
	}
	
	/* 处理定时器1任务 */
	if(ulTimerID == 1)
	{
		printf("ulTimerID333");
		bsp_LedToggle(2);
	}
}


/***************************** 安富莱电子 [url]www.armfly.com[/url] (END OF FILE) *********************************/

回复

使用道具 举报

35

主题

106

回帖

211

积分

高级会员

积分
211
 楼主| 发表于 2023-9-19 09:08:51 | 显示全部楼层
eric2013 发表于 2023-9-18 21:02
帮你测试了,我这里没问题,正常启动。

谢谢,问题解决了!是个人粗心的原因!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 14:46 , Processed in 0.229522 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表