历史上的今天
今天是:2025年04月25日(星期五)
2019年04月25日 | UCOSIII中断和时间管理
2019-04-25 来源:eefocus
一、中断服务函数
1、中断:应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要求的任务的过程叫做中断。
学会如何在UCOSIII下编写中断服务函数!
如果用UCOIII会先进行条件编译,然后执行中断服务程序,最后会退出UCOIII中断。中断函数如下:
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //使用UCOS操作系统
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
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-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS
OSIntExit(); //退出中断
#endif
}
进入和退出中断服务函数
进入中断服务函数以后使用函数OSIntEnter()
void OSIntEnter (void)
{
if (OSRunning != OS_STATE_OS_RUNNING)//判断UCOSIII是否运行
{
return
}
if (OSIntNestingCtr >= (OS_NESTING_CTR)250u)//判断中断嵌套次数
{
return;
}
OSIntNestingCtr++;//记录中断嵌套次数,UCOSIII最多支持250级的中断嵌套
}
退出中断服务函数时要调用函数OSIntExit();
UCOSIII临界段代码保护
临界段代码也叫做临界区,是指那些必须完整连续运行,不可被打断的代码段。当访问这些临界段代码的时候需要对这些临界段代码进行保护。
两种不同的保护方式:
①当宏OS_CFG_ISR_POST_DEFERRED_EN为0时,UCOSIII使用关中断的方式来保护临界段代码,当设置为1的时候就会采用给调度器上锁的方式来保护临界段代码。
②UCOSIII定义了一个进入临界段代码的宏:OS_CRITICAL_ENTER(),定义了两个退出临界段代码的宏:OS_CRITICAL_EXIT和OS_CRITICAL_EXIT_NO_SCHED()。
比如在主函数,在创建开始函数时,认为是不可打断的,所有进行保护,创建完后再解除保护:
int main(void)
{
OS_ERR err;//错误值:都是宏定义,根据对应数值找到返回错误值代表的意思
CPU_SR_ALLOC();
delay_init(168); //时钟初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
uart_init(115200); //串口初始化
LED_Init(); //LED初始化
OSInit(&err); //初始化UCOSIII
OS_CRITICAL_ENTER();//进入临界区
//创建开始任务
OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
(CPU_CHAR * )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启UCOSIII
while(1);
}
UCOSIII时间管理
任务延时
UCOSIII中的任务是一个无限循环并且还是一个抢占式内核,为了使高优先级的任务不至于独占CPU,可以给其他优先级较低任务获取CPU使用权的机会,UCOSIII中除空闲任务外的所有任务必须在合适的位置调用系统提供的延时函数,让当前的任务暂停运行一段时间并进行一个任务切换。
延时函数有两种,OSTimeDly()和OSTimeDlyHMSM()。
OSTimeDly()函数有三种工作模式:相对模式、周期模式和绝对模式。
void OSTimeDly (OS_TICK dly,//时间片数
OS_OPT opt,//工作模式
OS_ERR *p_err)//错误码
OSTimeDlyHMSM()函数仅在相对模式下工作。
void OSTimeDlyHMSM (CPU_INT16U hours,//时
CPU_INT16U minutes,//分
CPU_INT16U seconds,//秒
CPU_INT32U milli,//微妙
OS_OPT opt,//工作模式,不同的工作模式时间范围不一致
OS_ERR *p_err)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
取消任务的延时
延时任务任务可通过在其他任务中调用函数OSTimeDlyResume()取消延时而进入就绪状态,此函数最后会引发一次任务调度。
获取和设置系统时间
UCOSIII定义了一个CPU_INT32U类型的全局变量OSTickCtr来记录系统时钟节拍数,在调用OSInit()时被初始化为0,以后每发生1个时钟节拍,OSTickCtr加1。
OSTimeSet()允许用户改变当前时钟节拍计数器的值,慎用!!!!!
OSTimeGet()用来获取动迁时钟节拍计数器的值。
上一篇:UCOSIII任务间的通信
史海拾趣
|
CMD 它是用来分配rom和ram空间用的,告诉链接程序怎样计算地址和分配空间…… TI DSP .CMD 文件的编写 CMD 它是用来分配rom和ram空间用的,告诉链接程序怎样计算地址和分配空间. 所以不同的芯片就有不同大小的rom和ram.放用户程序的地方也不尽相 ...… 查看全部问答> |
|
问题:想在Eboot里响应中断,现在中断无响应 我是这样设置中断向量的 #define pISR (*(unsigned *)(0x30000000+0x18)) 0x30000000换成过0x00000000,0x8C000000,都没作用 pISR =(unsig ...… 查看全部问答> |
|
拦截ZwCreateSection 屏蔽某个进程的创建,NTSTATUS 返回哪个值不会弹出消息 如果返回 STATUS_ACCESS_DENIED, 会弹出“不是有效程序“的信息,返回哪个值 才不会弹出消息又能屏蔽进程的创建?… 查看全部问答> |
|
LM3S的SPI,用SPI读写TC72一直都不到数据,读时,在主模式下SCK有波形吗?设置如下。 // Enables a peripheral SSI0 SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); &nb ...… 查看全部问答> |
|
个人跟踪定位器是一种很神奇的装置,以前我们经常在电视,电影中看到这样的场景,在显示生活中到不是很经常看到。今天就揭开个人跟踪定位器的神秘面纱,然后我们就会感叹现代技术的发达。 跟踪定位器 ...… 查看全部问答> |




