FreeRTOS_软件定时器
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_软件定时器的更多相关文章
- rt-thread中软件定时器组件超时界限的一点理解
@2019-01-15 [小记] 对 rt-thread 中的软件定时器组件中超时界限的一点理解 rt_thread_timer_entry(void *parameter)函数中if ((next_ ...
- 【iCore4 双核心板_uC/OS-II】例程四:软件定时器
一.实验说明: 一些应用程序执行它们的任务时需要延迟一段特定的时间,因此uC/OS-II为我们提供了一些相应的 延时函数,本例程我们使用软件定时器定时500ms点亮相应的LED实现三色LED循环闪烁. ...
- 6.1-uC/OS-III软件定时器
1.软件定时器是 uC/OS 操作系统的一个内核对象,软件定时器是基于时钟节拍和系统管理创建的软件性定时器,理论上可以创建无限多个,但精准度肯定比硬件定时稍逊一筹. 2.软件定时器启动之后是由软件定时 ...
- 6.0-uC/OS-III软件定时器管理
1.软件定时器管理 uC/OS-III提供了软件定时器服务(相关代码在OS_TMR.C中).当设置OS_CFG.H中的OS_CFG_TMR_EN为1时软件定时器服务被使能. 2.uC/OS-III 定 ...
- 【STM32H7教程】第22章 STM32H7的SysTick实现多组软件定时器
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第22章 STM32H7的SysTick实现 ...
- uC/OS-III 软件定时器(三)
软件定时器是uC/OS 操作系统的一个内核对象,软件定时器是基于时钟节拍和系统管理创建的软件性定时器,理论上可以创建无限多个,操作简单,但精准度肯定比硬件定时稍逊一筹. 原理和实现过程 要用到的函数: ...
- 【TencentOS tiny】深度源码分析(8)——软件定时器
软件定时器的基本概念 TencentOS tiny 的软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受硬件定时器资源限制的定时器服务,本质上软件定时器的使用相当 ...
- liteos软件定时器(十)
1 概述 1.1 基本概念 软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数.定时精度与系统Tick时钟的周期有关. 硬件定时器受 ...
- 分享一个简单易用的软件定时器模块(MultiTimer)——基于keil+stm32f103zet+hal库(裸机实现)
公众号上看到一个比较好的一个github项目:https://github.com/0x1abin/MultiTimer 今天看了看,简单的,就移植了- 且看文档的说明, ============== ...
随机推荐
- 洛谷P3396 哈希冲突(分块)
传送门 题解在此,讲的蛮清楚的->这里 我就贴个代码 //minamoto #include<iostream> #include<cstdio> #include< ...
- 从技术 Leader 的招聘需求看,如何转岗为当前紧缺的大数据相关人才?
前段时间,跟候选人聊天的时候,一个有多年工作经验的资深 iOS 工程师告诉我,他最近正在学习 Machine Learning 相关的知识.他觉得,对于程序员来说,技术进步大大超过世人的想象,如果你不 ...
- 原来C#可以直接写二进制数的
二进制数在C#中的写法: byte b=0b01111110 二进制字符串的解释: string bstr="0111110"; byte b=Convert.ToByte(bst ...
- 解决element-ui中el-menu组件作为vue-router模式在刷新页面后default-active属性与当前路由页面不一致问题的方法
解决办法是给menu的default-active绑定route.path形如:<el-menu :default-active="$route.path" ...>每 ...
- Linux下iptables总结
linux下防火墙iptables 工作于网络或主机边缘,对进出本网络或本主机的网络报文安装事先设定好的匹配规则进行检查,对能够被规则所匹配的报文按照规则定义的处理机制进行处理的组件 通常情况下ipt ...
- CF24D Broken robot 后效性DP
这题咕了好久..... 设$f[i][j]$表示从$(i,j)$到最后一行的期望步数: 则有 $ f[i][1]=\frac{1}{3}(f[i][1]+f[i][2]+f[i+1][1])+1$ $ ...
- PIE使IE浏览器支持CSS3属性(圆角、阴影、渐变)
http://www.360doc.com/content/12/1214/09/11181348_253939277.shtml PIE使IE浏览器支持CSS3属性(圆角.阴影.渐变) 2012-1 ...
- python_魔法方法(五):描述符和定制序列
描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...
- Dell 笔记本触摸板网页双指滑动黑屏
# 问题如题 # 解决方法: -- 在网上搜了解决方法,最靠谱的一个是说,开机进BIOS,然后什么都不修改退出,重启就能解决(但是我采用这种方法并没有解决) -- 我自己的解决方法:设备管理器里面卸载 ...
- 【Java】在eclipse中使用maven进行项目构建 入门篇
maven配置的简单说明 从\192.168.30.150\103.初级人员培训资料\新建文件夹 (2)\环境下提取apache-maven-3.0.4.zip压缩包,解压缩至E盘下 在E盘下新建&q ...