• 准备电赛,简单写一下匿名飞控的分析
  • 基于TM4C主控的匿名拓空者飞控,介绍见匿名科创–匿名拓空者PRO—TI版全开源飞控使用入门—TM4C123

一、简介

  • 匿名飞控的任务调度还是比较简单的,没有操作系统什么的。
  • 可以大概分成两块:
    (1)利用systick定时器实现的定时执行任务,这部分都是各种逻辑,执行速度很快
    (2)借助Icm20602输出的1ms脉冲实现的外部中断任务。这里主要执行传感器数据获取,执行速度比较慢,但是可以打断第一部分的各种任务。经过咨询匿名客服,这里使用传感器1ms脉冲的原因是:用传感器自己提供的时钟会让检测更准确

二、代码分析

(1)1ms中断部分

//这部分代码位于 Drv_icm20602.c------------------------------------------------------------------------------
/*Icm20602引起的1ms中断*/
void Drv_Icm20602IrqHandler(void)
{//清除中断标记GPIOIntClear(ICM20602_READY_PORT, ICM20602_READY_PIN);//执行中断函数//Drv_Icm20602_Read();//利用icm的1ms中断做1ms任务INT_1ms_Task();
}/*配置PB2为上升沿外部中断,中断优先级为7(最低),捕获Icm20602输出的1ms周期脉冲*/
void Drv_Icm20602ReadyPinInit(void)
{ROM_SysCtlPeripheralEnable(ICM_READYPIN_SYSCTL);ROM_GPIODirModeSet(ICM20602_READY_PORT, ICM20602_READY_PIN, GPIO_DIR_MODE_IN);ROM_GPIOPinTypeGPIOInput(ICM20602_READY_PORT, ICM20602_READY_PIN);ROM_GPIOPadConfigSet(ICM20602_READY_PORT,ICM20602_READY_PIN,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPD);//上升沿中断ROM_GPIOIntTypeSet(ICM20602_READY_PORT, ICM20602_READY_PIN , GPIO_RISING_EDGE);//GPIO注册中断GPIOIntRegister(ICM20602_READY_PORT, Drv_Icm20602IrqHandler);//使能中断GPIOIntEnable(ICM20602_READY_PORT, ICM20602_READY_PIN);//设置中断优先级ROM_IntPrioritySet(ICM20602_READY_INT_PORT, USER_INT7);
}//这部分代码位于Ano_Scheduler.c-------------------------------------------------------------------------------
#define CIRCLE_NUM 20
static u8 lt0_run_flag;
static u8 circle_cnt[2];
/* Drv_Icm20602IrqHandler调用的1ms任务 */
void INT_1ms_Task()
{
//  if(fc_sta.start_ok == 0) return;//标记1ms执行,注意这个标志触发了Loop_Task_0lt0_run_flag ++;   //灯光驱动LED_1ms_DRV();circle_cnt[0] ++;circle_cnt[0] %= CIRCLE_NUM;if(!circle_cnt[0]){//20ms的周期,没有用到        }
}/* lt0_run_flag触发的1ms任务,包含所有传感器读取(具体调用地点见下文)  */
static void Loop_Task_0()//1ms执行一次
{/*传感器数据读取*/Fc_Sensor_Get();/*惯性传感器数据准备*/Sensor_Data_Prepare(1);/*姿态解算更新*/IMU_Update_Task(1);/*获取WC_Z加速度*/WCZ_Acc_Get_Task();WCXY_Acc_Get_Task();/*飞行状态任务*/Flight_State_Task(1,CH_N);/*开关状态任务*/Swtich_State_Task(1);/*数传数据交换*/ANO_DT_Data_Exchange();
}

(2)systick定时器调度部分

//这部分代码位于Ano_Scheduler.h-------------------------------------------------------------------------------
typedef struct
{void(*task_func)(u32 dT_us);   //任务函数指针
//  u16 rate_hz;u32 interval_ticks;             //任务执行周期(us)u32 last_run;                 //上次执行任务的时间
}sched_task_t;//这部分代码位于Ano_Scheduler.c-------------------------------------------------------------------------------//系统任务配置,创建不同执行频率的“线程”
static sched_task_t sched_tasks[] =
{//任务n,        周期us, 上次时间us{Loop_Task_1 ,  2000,  0 },      //姿态角速度环控制 & 电机输出控制 {Loop_Task_2 ,  6000,  0 },     //获取姿态欧拉角 & 姿态角度环控制
//  {Loop_Task_2 ,  2500,  0 },
//  {Loop_Task_3 ,  2500,  0 },
//  {Loop_Task_4 ,  2500,  0 },{Loop_Task_5 ,  11000, 0 },      //遥控器数据处理 & 飞行模式设置任务 & 高度数据融合任务 & 高度速度环控制 & 高度环控制 & 光流数据分析 & 灯光控制
//  {Loop_Task_6 ,  9090,  0 },
//  {Loop_Task_7 ,  9090,  0 },{Loop_Task_8 , 20000,  0 },      //罗盘数据处理任务 & 程序指令控制 & UWB数据计算 & 位置速度环控制{Loop_Task_9 , 50000,  0 },      //电压相关任务 & 陀螺仪恒温控制 & 延时存储任务
//  {Loop_Task_10,100000,  0 },
};//根据数组长度,判断线程数量
#define TASK_NUM (sizeof(sched_tasks)/sizeof(sched_task_t))//Main_Task在main.c的while循环中轮询
u8 Main_Task(void)
{uint8_t index = 0;//查询1ms任务是否需要执行if(lt0_run_flag!=0){lt0_run_flag--;Loop_Task_0();   //注意这里触发1ms中断任务}//循环判断其他所有线程任务,是否应该执行uint32_t time_now,delta_time_us;for(index=0;index < TASK_NUM;index++){//获取系统当前时间,单位UStime_now = GetSysRunTimeUs();//SysTick_GetTick();//进行判断,如果当前时间减去上一次执行的时间,大于等于该线程的执行周期,则执行线程if(time_now - sched_tasks[index].last_run >= sched_tasks[index].interval_ticks){delta_time_us = (u32)(time_now - sched_tasks[index].last_run);//更新线程的执行时间,用于下一次判断sched_tasks[index].last_run = time_now;//执行线程函数,使用的是函数指针sched_tasks[index].task_func(delta_time_us);}    }return 0;
}
  • 可以看到这里用了一个sched_task_t型的数组,存储了若干不同执行频率的“线程”,利用systick定时器判断执行时机。如果有两个任务赶在同一个时间执行,会根据任务在数组中的位置从小到大依次执行。
  • 最后再看一下systick定时器读取当前时间的实现方法
//以下程序位于 Drv_Bsp.c----------------------------------------------------------------------
static uint64_t SysRunTimeMs = 0;void SysTick_Init(void )
{ROM_SysTickPeriodSet(ROM_SysCtlClockGet()/1000);ROM_SysTickIntEnable();ROM_SysTickEnable();
}
void SysTick_Handler(void)
{SysRunTimeMs++;
}
uint32_t GetSysRunTimeMs(void)
{return SysRunTimeMs;
}
uint32_t GetSysRunTimeUs(void)
{return SysRunTimeMs*1000 + (SysTick->LOAD - SysTick->VAL) * 1000 / SysTick->LOAD;
}

ANO匿名飞控分析(2)— 任务调度相关推荐

  1. ANO匿名飞控STM32代码解读(一)任务调度——Ano_Scheduler.c

    我所学习的代码是匿名飞控使用STM32芯片ANO_PioneerPro-20190825的版本. 匿名飞控的整体代码是跑裸机的,任务调度是用STM32F4芯片中的系统时钟计时,做了一个任务调度系统,举 ...

  2. ANO匿名飞控STM32代码解读(二)数据传输——Ano_DT.c

    我使用代码对应的上位机版本为v6,具体通信协议格式在打开V6版本上位机–帮助信息–通信协议里可以看到. 这部分数据传输的核心简单的解帧.这部分的讲解以及匿名的通信协议的简介可以看另一篇文章**< ...

  3. 匿名飞控openmv寻色块代码分析

    本人最近一段时间在学习匿名飞控(使用的是匿名拓空者),也去网上看了很多资料和一些大佬的见解,学到了一些东西,所以想和大家一起学习讨论一下,互帮互助,共同进步.同时也是为了方便查找,防止遗忘.若是我有什 ...

  4. 匿名飞控TI版_姿态解算

    匿名飞控TI版_姿态解算 准备电赛 准备大创 先看看匿名姿态解算的代码 文章目录 匿名飞控TI版_姿态解算 一,姿态解算原理 1.介绍 2.方向余弦矩阵 (1)方向余弦 (2)DCM矩阵 3.欧拉角 ...

  5. 匿名飞控TI版_PID部分,串级PID,微分先行,前馈控制

    文章目录 PID介绍 有趣的故事 控制模型 位置式PID和增量式PID 位置式PID 增量式PID 串级PID 前馈控制 微分先行 匿名代码分析 PID介绍 PID介绍 有趣的故事 PID的故事 \s ...

  6. ANO匿名上位机V7协议STM32

    ANO匿名上位机V7协议&STM32 说明:以下程序为自己编写,若有误欢迎各位指出. 基于ANO匿名V7上位机的通信协议编写的代码 文章目录 ANO匿名上位机V7协议&STM32 前言 ...

  7. 基于tiva的匿名飞控学习笔记(1)

    基于tiva的匿名飞控学习笔记(1) 开关状态任务 遥控器数据处理任务 数传数据交换 延时存储任务 开关状态任务 匿名飞控的开关状态任务为函数Swtich_State_Task(u8 dT_ms),定 ...

  8. 匿名飞控修改pwm输出脉宽和频率

    项目中要用到飞控板去控制一个单独的pwm电子开关,但是这个电子开关只有在输入特定脉冲频率和脉宽的作用下会执行开关作用.因为也是一直做上层算法,缺少底层开发经验,网上也没有现成的技术文档告诉我怎么改,只 ...

  9. 【开源飞控】匿名飞控TI版解析(1)

    准备电赛的飞控题,买来了匿名的飞控学习一下,这里整理了一下匿名飞控中比较关键的几部分,学习了一下原理,然后代码解读都写注释里了,篇幅较长. 目录 一.遥控器信号接收 1.代码解读 2.ppm原理 二. ...

最新文章

  1. 基于LVS-DR集群的持久链接实验
  2. Python——接口开发
  3. docker迁移与备份
  4. Linux系统【四】进程间通信-管道
  5. mysql访问类型最好的_【干货满满】最全的MySQL性能指南(一):选择最佳的数据类型...
  6. LeetCode 1374. 生成每种字符都是奇数个的字符串
  7. 【TensorFlow】TensorFlow函数精讲之 tf.nn.relu()
  8. linux下设置物联网卡apn,负控终端物联网卡APN参数修改步骤
  9. 基于JSP的美食论坛系统毕业设计
  10. 什么是计算机网络体系结构?
  11. Celeste中的平台游戏设计(思维导图)
  12. 解决服务器网卡不识别问题
  13. Elasticsearch设置ip访问
  14. 机器人系统的基本概念及外部模型参数详解
  15. 32 --> 详解 OpenWRT系统框架基础软件模块之netifd
  16. word图文混排复制到JMEditor图片不显示
  17. Ubuntu boot menu
  18. 7-6 判断题 (15分)
  19. 【Unity3D】3D游戏学习
  20. 信息学奥赛一本通——2068:【例2.6】鸡兔同笼

热门文章

  1. 014 Unbox failed! RequestError: Error: getaddrinfo ENOENT raw.githubusercontent.com raw.githubuserco
  2. docker进入到某个容器
  3. 形态学填充孔洞的几个问题
  4. iOS Resume【简历模板】
  5. 父进程与子进程间相互发送信号
  6. 手机闪存速度排行_手机闪存性能排行
  7. javascript Array系列函数之9:slice拷贝一个数组
  8. CSS图片保持原比例
  9. android 触摸屏干扰,如何解决电容触摸屏的抗干扰问题?
  10. VsCode使用及常用命令汇总(Win10)