不使用操作系统实现时间片轮询
1.MCU的程序结构大致有三类:
1.1 简单的前后台顺序执行程序;
1.2 裸机时间片轮询法;
1.3 搭载操作系统。
2.什么情况下使用裸机时间片轮询法?
随着需求程序越来越复杂,简单的前后台顺序执行程序显得有些吃力、稳定性变差、bug也会增多。这是除了移植复杂的操作系统,还有一种更为轻便的方法来管理MCU的执行逻辑,即裸机时间片轮询法。
3.实现方法:
需要一个定时器中断资源去计时,计时周期如1ms,10ms,100ms,500ms…… 让这个定时器来管理我们的任务,中断程序中查询更新任务标志。然后在主循环中判断有无任务标志,在然后执行相应的任务即可。
4.实现步骤:
4.1 首先对对定时器初始化,我们选用定时器3,定时周期=(71+1)*(999+1)/(9x8M)=1ms。
void TIM3_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// TIM4 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 基础设置
TIM_TimeBaseStructure.TIM_Period = 999; //计数值 1000-1
TIM_TimeBaseStructure.TIM_Prescaler = 71; //预分频,此值+1为分频的除数 7200-1
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// Timer3中断配置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能预装载
TIM_ARRPreloadConfig(TIM3, ENABLE);
// 预先清除中断位
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
// 允许更新中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
// 停止TIM3
TIM_Cmd(TIM3, ENABLE);
}
4.2 然后定义TIM3的中断服务程序。
void TIM3_IRQHandler(void)
{
static u16 tim_10ms = 0,tim_100ms = 0,tim_500ms = 0,tim_on = 0;
if ( TIM_GetITStatus(TIM3 , TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM3 , TIM_FLAG_Update);
if(pro.on_flag == 0)
{
if(++ tim_on >= 1500)
{
pro.on_flag = 1;
}
}
pro.flag_1ms = 1;
if(++ tim_10ms >= 10)
{
tim_10ms = 0;
pro.flag_10ms = 1;
}
if(++ tim_100ms >= 100)
{
tim_100ms = 0;
pro.flag_100ms = 1;
}
if(++ tim_500ms >= 500)
{
tim_500ms = 0;
pro.flag_500ms = 1;
}
}
}
4.3 最后在主函数中查询标志位执行对应的代码块。
int main(void)
{
Delay_10us(100000);//待驱动器供电稳定
BSP_Init();
pro.id_num = per_read_idnum(6);
while(1)
{
axle_zero_handle();
if(pro.axle_zero_flag == 4)
{
pro.init_flag = 1;
break;
}
if(pro.flag_10ms)
{
pro.flag_10ms = 0;
motor_stat_handle(&pro.pwm_out,&pro.motor_dir);
}
if(pro.flag_100ms)
{
pro.flag_100ms = 0;
led_cpu_handle();
}
}
dev_xbee_init(&xbee,COM2,115200);
while(1)
{
motor_stop_handle();
brake_handle();
axle_feedback_handle();
xbee_tx_hanle();
if(pro.flag_500ms)
{
pro.flag_500ms = 0;
}
if(pro.flag_1s)
{
pro.flag_1s = 0;
}
if(pro.flag_1ms)
{
pro.flag_1ms = 0;
dev_xbee_time_proc(&xbee);
}
if(pro.flag_10ms)
{
pro.flag_10ms = 0;
motor_handle();
motor_down_handle();
motor_stat_handle(&pro.pwm_out,&pro.motor_dir);
hit_detection();
}
if(pro.flag_100ms)
{
pro.flag_100ms = 0;
led_cpu_handle();
xbee_rx_hanlde();
}
}
}
5 总结
使用裸机时间片轮询法可以提高轻量级程序代码的稳定性和可靠性,实现过程方便快捷。