织梦多个网站,wordpress 查询文章,哪个网站帮别人做ppt,深圳工程造价信息网本文链接上篇继续叙述#xff0c;如果没有看到看一篇的#xff0c;大家可以点击传送门观看。 作者#xff1a;良知犹存
转载授权以及围观#xff1a;欢迎添加wx#xff1a;Allen-Iverson-me-LYN
总述 1.通过运用RTOS#xff0c;线程里面调用系统提供的延时等函数… 本文链接上篇继续叙述如果没有看到看一篇的大家可以点击传送门观看。 作者良知犹存
转载授权以及围观欢迎添加wxAllen-Iverson-me-LYN
总述 1.通过运用RTOS线程里面调用系统提供的延时等函数实现解决阻塞。 2.全局变量方法定时器计数条件判断替代延时。 3.使用状态机方式分解动作替代延时实现。 4.使用链表式与第三种相似。 三、 状态机法 状态机执行与全局变量的区别在于状态机的方法是更进一层的定时操作可以通过状态机在主循环或者触发函数实现多个动作的延时操作。 状态机中大致会分为两类延时替代操作一种注重多个动作的延时一种叫精确时间的延时。第一种情况经常会在一些需要双方有来有往的应答操作出现而后一种出现在明确延时操作过程中。接下来我们展示一下代码风格吧。 /*堵塞型的代码*/
void clogged(void)
{taskfun1();delay(500);taskfun2();delay(100);taskfun3();delay(20);
}
int main(int argc,char** argv)
{SystemInit();while(1){clogged();taskfun();/*此段代码执行的时候会被堵塞*/}
} 1.注重动作的状态机 /*注重分解动作的状态机*/
void TIM_IRQ(void)/*定时器中断服务函数*/
{FSMtimer ;/*设置合适的中断时间间隔*/
}
static u32 FSMtimer 0,LastFSMtimer 0;/*用来计时变量*/
static u8 FSMSta 0;/*设置状态的工作步骤的变量*/
void actionFSM(void)
{switch(FSMSta){case 0: taskfun1();FSMSta 1;break;case 1: taskfun2();FSMSta 2;break;case 2:taskfun3();FSMSta 3; break;case 3:if(FSMtimer - LastFSMtimer 100 )/*定时判断完成任务*/{taskfun4();FSMSta 4; }else{taskfun5();FSMSta 1;/*条件判断出现问题实现动作跳转进行动作重复*/ }break; case 4:taskidle();/*状态机的状态执行完成可以进行空闲任务*/ break;
}int main(int argc,char** argv)
{SystemInit();FSMSta n;/*初始化设置状态机的起始步*/while(1){actionFSM();/*替换效果如下*/taskfun();/*此段代码执行的时候会被堵塞*/}
} 2.注重精确延时固定动作的状态机 /*延时操作的结构体*/
__packed typedef struct{bool IsFSM_start;/*延时计数的标志*/u8 FSM_Sta:7;/*状态机执行的状态*/u32 FSM_target;/*延时定时的目标值*/u32 FSM_count;/*状态机用来在计数器中累加计时的变量*/u8 FSM_flag;/*状态机part的标志*/
}DelayTypeDef;
DelayTypeDef DelayFSM;
/*定时中断服务函数*/
void TIM_IRQ(void)
{if(DelayFSM.FSM_flag1)/*执行状态机部分标志*/{if(DelayFSM.IsFSM_start 1)/*动作执行代码为零则不进入计时操作*/{(DelayFSM.FSM_countDelayFSM.FSM_target)?(DelayFSM.FSM_count):(DelayFSM.IsFSM_start0,DelayFSM.FSM_Sta);/*IsFSM_start0 进入状态机执行*/}}
}
u8 taskfun(void)
{if(DelayFSM.FSM_flag0)/*初始化代码部分*/{DelayFSM.FSM_flag 1;/*设置状态机flag为1 执行下一部分程序*/DelayFSM.IsFSM_start 0;/*开始状态机*/DelayFSM.FSM_Sta 1;/*初始化第一步*/}else if (DelayFSM.FSM_flag1){if(DelayFSM.IsFSM_start 0){switch(DelayFSM.FSM_Sta){case 0x01:DelayFSM.IsFSM_start 1;/*IsFSM_start1 进入计时器计时*/DelayFSM.FSM_count 0; /*计数器清零*/ DelayFSM.FSM_target 1000;/*设置计时的目标时间为1000个定时器触发时间间隔*/taskfun1();/*任意任务函数*/break;case 0x02:DelayFSM.IsFSM_start 1;/*注释如上*/DelayFSM.FSM_count 0; /*注释如上*/DelayFSM.FSM_target 500;/*目标值为500基数*/taskfun2();/*任意任务函数*/break; case 0x03:DelayFSM.IsFSM_start 0;/*状态机完成状态 start清零*/DelayFSM.FSM_Sta 0; /*清零代表状态机将进入空闲模式*/DelayFSM.FSM_target 0;/*目标值设置位零*/DelayFSM.FSM_flag 3;/*随意赋值这个值与你在主程序的判断重启状态机的标记相关可看main中程序*/taskfun3();/*任意任务函数*/break;default:break;}}}elsereturn 0;return 1;
}
int main(int argc,char** argv)
{SystemInit();while(1){taskfun();/*状态机执行*/if (DelayFSM.flag3)/*重复使用次状态机*/{DelayFSM.flag 0; } }
} 这就是我分享的通过状态机实现的解决堵塞方法里面代码是实践过的如果大家有什么更好的思路欢迎分享交流哈 四、 链表法 通过上面结构体状态机程序我们知晓通过一些特定的延时程序等待配合状态机可以替换很多的队列式延时。可是通过结构体 定义的时候如果需要很多处的延时阻塞替换则会产生很多的延时变量这个时候需要管理很多不同名称的变量这样容易造成混乱。所以我们可以选择链表使用链表定义好head之后只要模式一样数据变量我们只需要添加一个节点即可。
注这里使用链表是单链表双链表暂且不需要用到。链表的使用方法我是参考一位博主的文章而使用的如果需要大家也可以去欣赏他的文章这里是传送门。 #define ONCE 0
#define CYCLE 1
typedef struct Delay_TIMER
{bool mode;/*设置的模式 0 单次计时 1 循环计时*/bool isActivate;/*判定是否需要启动定时*/volatile u32 cnt;/*计数器*/u32 target;/*目标数值*/struct Delay_TIMER* next;/*下一个节点*/
}Delay_TIMER_t;
static struct Delay_TIMER *head NULL;/*定义链表的头*/
/* 定时器中断服务程序*/
void TIM_ISR(void)
{struct Delay_TIMER *t head;if (t NULL)return;while(t ! NULL){if (t-isActivate true)t-cnt;/*计数器定时累加*/t t-next;}
}
/*插入一个需要定时的链表节点并初始化成员变量*/
void Insert_delay_node(Delay_TIMER_t *node,bool mode,uint32_t target)
{struct Delay_TIMER *t head; node-isActivate true;/*设置为开*/node-mode mode;/*模式支持自己设置*/node-cnt 0;node-target target;/*设置目标时长数值*/node-next NULL;if (head NULL){head node;return;}while(t-next ! NULL ){if (t node) return; t t-next;}t-next node;
}
/*删除不需要使用的延时节点*/
void Delete_delay_node(Delay_TIMER_t *node)
{struct Delay_TIMER *p head,*t head;if (head node){head node-next;return;}while(t-next ! NULL )/*当需要删除尾部最后一个节点的时候tail-next NULL,这个时候循环跳出节点无法删除*/{if (t node) /*删除节点*/{p-next node-next;/*node-next NULL;*/node-next NULL;}else{p t;t t-next;/* t p-next;*/}}if(t-next NULL head ! node)/*删除最后一个节点*/{p-next NULL;/*尾部最后一个节点直接置NULL*/}
}
/*查询软件计时器是否超时*/
bool Is_delay_timer_Out(Delay_TIMER_t *node)
{bool res false;if (node-cnt node-target){res true;
if (node-mode CYCLE){node-cnt 0; node-isActivate true;}elsenode-isActivate false;
} return res;
}
/*主程序*/
int main(int argc,char** argv)
{SystemInit();u8 mode 0;/*单次模式*/static u8 STA 1;/*设置状态机初始step*/static Delay_TIMER_t task_delay; Insert_delay_node(task_delay,mode,1000);/*初始化节点设置为单次模式计时目标为1000个计数间隔*/while(1){switch(STA){case 1:taskfun1();STA 2;break;case 2:/*延时等待状态*/if (Is_delay_timer_Out(task_delay) true)STA 1; break;}}
}——END——