ANO匿名飞控时间片调度移植至普通STM32工程

编程入门 行业动态 更新时间:2024-10-15 22:29:58

ANO匿名飞控<a href=https://www.elefans.com/category/jswz/34/1771441.html style=时间片调度移植至普通STM32工程"/>

ANO匿名飞控时间片调度移植至普通STM32工程

工程结构

时间片调度相关的代码位于SCHEDULER目录下的Scheduler和Task文件中,匿名飞控原本的时钟由传感器输出的1ms脉冲实现的外部中断提供,为使时间片调度算法可以用于一般的工程,此处改为使用定时器TIM7的1ms定时器中断,位于HAEDWARE目录下的timer文件(原因:f407的TIM7无法用于PWM输出,使用定时器TIM7可减少移植的冲突,如有需要,可改为其他定时器)

具体代码

1.Task.c用于存放用户任务函数,线程中的用户任务的执行不应占用太长时间

#include "Task.h"
#include "usart.h"
#include "delay.h"
void task1()
{printf("任务1执行\r\n");}void task2()
{printf("任务2执行\r\n");}void task3()
{printf("任务3执行\r\n");}

2.Scheduler.c,存放有调度器初始化函数,调度器运行函数,用户任务在此文件中进行注册(如task2()和task1()函数)

#include "Scheduler.h"
#include "Task.h"
//
//用户程序调度器
//static void Loop_1000Hz(void) //1ms执行一次
{////
}static void Loop_500Hz(void) //2ms执行一次
{////
}static void Loop_200Hz(void) //5ms执行一次
{////
}static void Loop_100Hz(void) //10ms执行一次
{////
}static void Loop_50Hz(void) //20ms执行一次
{////
}static void Loop_20Hz(void) //50ms执行一次
{//task2();//
}static void Loop_2Hz(void) //500ms执行一次
{//task1();//
}
//
//调度器初始化
//
//系统任务配置,创建不同执行频率的“线程”
static sched_task_t sched_tasks[] ={{Loop_1000Hz, 1000, 0, 0},{Loop_500Hz, 500, 0, 0},{Loop_200Hz, 200, 0, 0},{Loop_100Hz, 100, 0, 0},{Loop_50Hz, 50, 0, 0},{Loop_20Hz, 20, 0, 0},{Loop_2Hz, 2, 0, 0},
};
//根据数组长度,判断线程数量
#define TASK_NUM (sizeof(sched_tasks) / sizeof(sched_task_t))void Scheduler_Setup(void)
{uint8_t index = 0;//初始化任务表for (index = 0; index < TASK_NUM; index++){//计算每个任务的延时周期数sched_tasks[index].interval_ticks = 1000 / sched_tasks[index].rate_hz;//最短周期为1,也就是1msif (sched_tasks[index].interval_ticks < 1){sched_tasks[index].interval_ticks = 1;}}
}
//这个函数放到main函数的while(1)中,不停判断是否有线程应该执行
void Scheduler_Run(void)
{uint8_t index = 0;//循环判断所有线程,是否应该执行for (index = 0; index < TASK_NUM; index++){//获取系统当前时间,单位MSuint32_t tnow = GetTimeMs();//进行判断,如果当前时间减去上一次执行的时间,大于等于该线程的执行周期,则执行线程if (tnow - sched_tasks[index].last_run >= sched_tasks[index].interval_ticks){//更新线程的执行时间,用于下一次判断sched_tasks[index].last_run = tnow;//执行线程函数,使用的是函数指针sched_tasks[index].task_func();}}
}/************************END OF FILE************/

相关说明匿名的注释已经说的很清楚了,这里做简单补充和移植说明。Scheduler_Setup函数是调度器初始化函数,需在主函数的while(1)前调用一次。Scheduler_Run函数是调度器运行函数,需放到main函数的while(1)中循环调用,主要内容为获取系统当前时间,用当前时间减去上一次执行的时间,若大于等于该线程的执行周期,则执行对应的线程,线程中的用户任务的执行不应占用太长时间,否则会阻塞线程。匿名飞控的调度器是软实时调度,而非FreeRTOS式的硬实时调度。(硬实时是系统执行一个程序,只要规定的时间用完,那么就一定跳出去,不管执行完还是没有执行完。软实时没有硬性的时间限制,它可以推迟一段时间来完成自己的任务。)Scheduler_Run中调用的GetTimeMs()函数位于timer.c文件中,如下。
3.timer.c,存放定时器初始化、定时器中断和GetTimeMs()函数

#include "timer.h"
#include "usart.h"static uint64_t TimeMs = 0;//定时器7中断服务程序		    
void TIM7_IRQHandler(void)
{ 	if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//是更新中断{	 	TimeMs++;TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIM7更新中断标志     }	    
}//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数		 
void TIM7_Int_Init(u16 arr,u16 psc)
{	NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7时钟使能    //定时器TIM7初始化TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); //使能指定的TIM7中断,允许更新中断TIM_Cmd(TIM7,ENABLE);//使能定时器7NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器}uint32_t GetTimeMs(void)
{return TimeMs;
}

4.main.c,软硬件初始化,调用Scheduler_Run()开启调度器

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "timer.h"
#include "Scheduler.h"int main(void)
{uart_init(115200);delay_init(168);TIM7_Int_Init(10-1,8400-1);Scheduler_Setup();while(1){Scheduler_Run();}
}

如有需要,这里提供完整工程可供参考。


更多推荐

ANO匿名飞控时间片调度移植至普通STM32工程

本文发布于:2024-02-19 13:01:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1764250.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时间   工程   ANO

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!