FreeRTOS 软件定时器

实验

创建2个任务,start_task、timercontrol_task。

start_stask:创建timercontrol_task任务;创建周期定时器AutoReloadTimer 和单次定时器OneShotTimer;创建二值信号量BinarySemaphore。

BinarySemaphore:接收串口命名,在中断中释放信号,在timercontrol_task中等待信号量,解析命名,通过不同的命令控制周期定时器AutoReloadTimer和单次定时器OneShotTimer的开启和关闭。

AutoReloadTimer 的回调函数会输出运行的次数

OneShotTimer的回电函数会输出运行的次数

任务分配:

//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters); //任务优先级
#define TIMERCONTROL_TASK_PRIO 2
//任务堆栈大小
#define TIMERCONTROL_STK_SIZE 50
//任务句柄
TaskHandle_t TimerControlTask_Handler;
//任务函数
void timercontrol_task(void *pvParameters); SemaphoreHandle_t BinarySemaphore_Handle; // 二值信号量句柄 TimerHandle_t AutoReloadTimer_Handle ; // 周期定时器句柄
TimerHandle_t OneShotTimer_Handle; // 单次定时器句柄 void AutoReloadTimerCallback(void); // 周期定时器回调函数
void OneShotTimerCallback(void); // 周期定时器回调函数

main() 函数

int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
delay_init(); //延时函数初始化
uart_init(); //初始化串口
LED_Init(); //初始化LED //创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}

命令解析相关函数:

// 将字符串中的小写字母转换为大写
// str:要转换的字符串
// len:字符串长度
void LowerToCap(u8 *str,u8 len)
{
u8 i; for(i=;i<len;i++)
{
if((<str[i])&&(str[i]<)) // 小写字母
str[i] = str[i]-; // 转换为大写
}
} // 命令处理函数,将字符串命令转换成命令值
// str:命令
// 返回值:0xFF-命令错误 其他值-命令值
u8 CommandProcess(u8 *str)
{
u8 CommandValue = 0xFF; if(strcmp((char*)str,"KEY1")==) CommandValue = ;
else if(strcmp((char*)str,"KEY2")==) CommandValue = ;
else if(strcmp((char*)str,"KEY3")==) CommandValue = ;
else if(strcmp((char*)str,"KEY4")==) CommandValue = ; return CommandValue;
}

任务函数:

//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区 // 创建二值信号量
BinarySemaphore_Handle = xSemaphoreCreateBinary(); // 创建二值信号量
if(BinarySemaphore_Handle ==NULL)
{
printf("BinarySemaphore Create Failed!\r\n");
}else{
xSemaphoreGive(BinarySemaphore_Handle); // 释放信号量
} // 创建周期定时器
AutoReloadTimer_Handle = xTimerCreate( (const char *)"AutoReloadTimer",
(TickType_t) ,
(UBaseType_t) pdTRUE,
(void *) ,
(TimerCallbackFunction_t)AutoReloadTimerCallback );
if(AutoReloadTimer_Handle == NULL)
{
printf("AutoReloadTimer Created Failed \r\n");
}else{
printf("AutoReloadTimer Created Success \r\n");
} // 创建单次定时器
OneShotTimer_Handle = xTimerCreate( (const char *)"OneShotTimer",
(TickType_t) ,
(UBaseType_t) pdFALSE,
(void *) ,
(TimerCallbackFunction_t)OneShotTimerCallback );
if(OneShotTimer_Handle == NULL)
{
printf("OneShotTimer Created Failed \r\n");
}else{
printf("OneShotTimer Created Success \r\n");
} //创建TIMECONTRFOL任务
xTaskCreate((TaskFunction_t )timercontrol_task,
(const char* )"timercontrol_task",
(uint16_t )TIMERCONTROL_STK_SIZE,
(void* )NULL,
(UBaseType_t )TIMERCONTROL_TASK_PRIO,
(TaskHandle_t* )&TimerControlTask_Handler); vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
} //TIMERCONTROL任务函数
void timercontrol_task(void *pvParameters)
{
u8 len = ;
u8 CommandValue = 0xFF;
u8 CommandStr[USART_REC_LEN];
BaseType_t err; while()
{
xSemaphoreTake( BinarySemaphore_Handle, portMAX_DELAY ); // 死等
len = USART_RX_STA&0x3fff; // 得到此次接收到的数据长度 sprintf((char *)CommandStr,"%s",USART_RX_BUF); // 装载数据
CommandStr[len] = '\0'; // 加上字符串结尾符号
LowerToCap(CommandStr,len); // 将字符串转换为大写
CommandValue = CommandProcess(CommandStr); // 命令解析 if(CommandValue != 0xFF) // 接收到正确的命令
{
switch(CommandValue)
{
case : // 开启周期定时器
err = xTimerStart( AutoReloadTimer_Handle, );
if(err == pdFAIL)
{
printf("AutoReloadTimer Start Failed! \r\n");
}else{
printf("AutoReloadTimer Start Succeed! \r\n");
}
break;
case : // 关闭周期定时器
err = xTimerStop( AutoReloadTimer_Handle, );
if(err == pdFAIL)
{
printf("AutoReloadTimer Stop Failed! \r\n");
}else{
printf("AutoReloadTimer Stop Succeed! \r\n");
}
break;
case : // 开启单次定时器
err = xTimerStart( OneShotTimer_Handle, );
if(err == pdFAIL)
{
printf("OneShotTimer Start Failed! \r\n");
}else{
printf("OneShotTimer Start Succeed! \r\n");
}
break;
case : // 关闭周期定时器
err = xTimerStop( OneShotTimer_Handle, );
if(err == pdFAIL)
{
printf("OneShotTimer Stop Failed! \r\n");
}else{
printf("OneShotTimer Stop Succeed! \r\n");
}
break;
}
}else{
printf("Cmd error!\r\n");
}
USART_RX_STA = ;
}
}

定时器回调函数:

// 周期定时器回调函数
void AutoReloadTimerCallback(void)
{
static u8 count = ; count ++;
printf("AutoReloadTimerCallback running %d timers\r\n",count);
} // 周期定时器回调函数
void OneShotTimerCallback(void)
{
static u8 count = ; count ++;
printf("OneShotTimerCallback running %d timers\r\n",count);
}

串口中断初始化和中断处理函数

u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=; //接收状态标记 void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
} extern SemaphoreHandle_t BinarySemaphore_Handle; // 二值信号量句柄
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
BaseType_t xHigherPriorityTaskWoken = pdFALSE; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据 if((USART_RX_STA&0x8000)==)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-))USART_RX_STA=;//接收数据错误,重新开始接收
}
}
}
} if((BinarySemaphore_Handle != NULL) && (USART_RX_STA&0x8000))
{
xSemaphoreGiveFromISR( BinarySemaphore_Handle, &xHigherPriorityTaskWoken ); // 释放互斥信号量
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); // 如果需要进行一次任务切换
} }
#define USART_REC_LEN              20      //定义最大接收字节数 200
#define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符

注意:串口中断的优先级在FreeRTOS的优先级管理范围内。

运行结果:

输入KEY1命令,周期定时器开始运行,周期性调用其回调函数,直到输入KEY2命令,停止周期定时器,其回调函数不再被调用。

输入KYE3命令,单次定时器开始运行,调用其回调函数,只调用一次,就不再调用。再次输入KEY3命令,还是只调其回调函数一次。

可以看出,停止单次定时器命令KEY4,可以不存在。

FreeRTOS_软件定时器的更多相关文章

  1. rt-thread中软件定时器组件超时界限的一点理解

    @2019-01-15 [小记] 对 rt-thread 中的软件定时器组件中超时界限的一点理解 rt_thread_timer_entry(void *parameter)函数中if ((next_ ...

  2. 【iCore4 双核心板_uC/OS-II】例程四:软件定时器

    一.实验说明: 一些应用程序执行它们的任务时需要延迟一段特定的时间,因此uC/OS-II为我们提供了一些相应的 延时函数,本例程我们使用软件定时器定时500ms点亮相应的LED实现三色LED循环闪烁. ...

  3. 6.1-uC/OS-III软件定时器

    1.软件定时器是 uC/OS 操作系统的一个内核对象,软件定时器是基于时钟节拍和系统管理创建的软件性定时器,理论上可以创建无限多个,但精准度肯定比硬件定时稍逊一筹. 2.软件定时器启动之后是由软件定时 ...

  4. 6.0-uC/OS-III软件定时器管理

    1.软件定时器管理 uC/OS-III提供了软件定时器服务(相关代码在OS_TMR.C中).当设置OS_CFG.H中的OS_CFG_TMR_EN为1时软件定时器服务被使能. 2.uC/OS-III 定 ...

  5. 【STM32H7教程】第22章 STM32H7的SysTick实现多组软件定时器

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第22章       STM32H7的SysTick实现 ...

  6. uC/OS-III 软件定时器(三)

    软件定时器是uC/OS 操作系统的一个内核对象,软件定时器是基于时钟节拍和系统管理创建的软件性定时器,理论上可以创建无限多个,操作简单,但精准度肯定比硬件定时稍逊一筹. 原理和实现过程 要用到的函数: ...

  7. 【TencentOS tiny】深度源码分析(8)——软件定时器

    软件定时器的基本概念 TencentOS tiny 的软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受硬件定时器资源限制的定时器服务,本质上软件定时器的使用相当 ...

  8. liteos软件定时器(十)

    1 概述 1.1 基本概念 软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数.定时精度与系统Tick时钟的周期有关. 硬件定时器受 ...

  9. 分享一个简单易用的软件定时器模块(MultiTimer)——基于keil+stm32f103zet+hal库(裸机实现)

    公众号上看到一个比较好的一个github项目:https://github.com/0x1abin/MultiTimer 今天看了看,简单的,就移植了- 且看文档的说明, ============== ...

随机推荐

  1. uuid安装 插件安装

    yum -y install uuid uuid-devel 安装uuid包tar -zxvf uuid-1.6.1.tar.gzcd uuid-1.6.1./configuremakemake in ...

  2. mybatis复习01

    1.mybatis的历史: mybatis是apache的一个开源项目,2010被google收购,转移到google code. mybatis是一个优秀的持久层框架,对jdbc操作进行了封装,是操 ...

  3. js 为对象添加和删除属性

    对于一个普通的js对象: var obj = { name:"mary", age:21 } 如果我们要对它添加新属性的话可以使用下列方式: obj.address = " ...

  4. 自动检测GD库支持的图像类型

    以下代码通过自动检测GD库支持的图像类型 来写出移直性更好的PHP代码 <?php if(function_exists("imagegif")){ header(" ...

  5. python大战机器学习——半监督学习

    半监督学习:综合利用有类标的数据和没有类标的数据,来生成合适的分类函数.它是一类可以自动地利用未标记的数据来提升学习性能的算法 1.生成式半监督学习 优点:方法简单,容易实现.通常在有标记数据极少时, ...

  6. JS——封闭函数、闭包、内置对象

    封闭函数:时javascript中匿名函数的另一种写法,创建一个一开始就执行而不用命名的函数 示例: 1) (function(){ var str = '欢迎访问我的主页'; alert(str); ...

  7. 使用gulp构建工具

    之前一个demo中用的是grunt,照着grunt用到的插件找了下gulp的,总体使用还算顺畅,说实话并不觉得学习成本有降低什么的,差不多.不过也遇到一些问题: 1.gulp.dest()输出目录需要 ...

  8. bzoj 3732: Network 树上两点边权最值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3732 首先想到,要使得最长边最短,应该尽量走最短的边,在MST上. 然后像LCA那样倍增娶个最大值 ...

  9. PHPCMS的自增长标签

    设置幻灯片的时候,需要用到自增长ID. <div class="tt_pic"><img src="images/1.gif" />&l ...

  10. ajax无刷新评论示例

    下面就为大家带来一篇 ajax无刷新评论示例.学习还是有点帮助的,给大家做个参考吧. 这是留言板的界面,当用户点击提交留言的时候,自动提交到我的留言下面 留言内容中为空,或者为灰色的“没有填写留言内容 ...