我的惯性导航开发开篇---架构
2019-04-15 13:50发布
生成海报
有人问我,学空气动力学到底有什么用?学好了就能玩航模了吗?有些人说,我一点空气动力学知识都没有,可我玩的还是很好啊.... 诸如此类问题,我想大家误解了,其实学好空气动力学是一劳永逸的,是往更高层次发展的基础,学好它,虽然不能很快立竿见影的带来什么,但总之,学则加冕,没坏处的,希望大家正确认识。 好了,有些人说我理论哥,你做过没?见过没?有本事来点实际的,要不竟是扯淡,没干货一切白瞎。此话,并非无道理。不过在此声明,我不是什么理论哥,我不是科班出身,完全是爱好,自学的,很多专业问题还需大家多指教。 好了,闲话少说。 在接下来,我会从零开始,从无到有开发一个简单的IMU惯性导航系统,满足航模级应用,希望对大家有所帮助,也请大家多提建议。 构思架构: CPU:ARM MEMS三轴陀螺 MEMS三轴加速度计 网上有很多种IMU的硬件方案和软件方案,也有很多很好的开源作品,我为什么还要再多此一举呢? 原因有二吧: 1、我本身也是爱好者,希望通过在做的过程中,熟悉各个环节,得到更好的理解与体会; 2、也希望能对大家在该方面有所帮助,有一个不一样的认识; 希望大家在当前拿来应用主义极盛的情况下,能更多的深入了解并应用它,因为只有深入其中,才能知道其中的滋味,简单的拿来用,也没什么错,我们想问题的角度或用意关注点不同罢了! 毕竟现在的系统都是由前辈们从理论从无到有,一点一滴做起来的,一个人的力量也有限的,突然让我们做一个大系统,从经验来讲有很大的难度,更多的时候做项目,以节点为根,成果为本,很难深入弄个明白。 都说是站在巨人的肩膀上嘛!我们都是应用工程师。 而我个人而言,我想砸破砂锅问到底。要不然不知道根本就不知道如何提升,从长远来说还是要搞好理论基础,再来搞应用比较实在。所以先搞清楚理论,成为我们不可逾越的坎。好了,说了这么多,我慢慢一一道来,如有什么错误,希望博得同仁们的理解,也希望你们多提建议。在此非常感激。 IMU惯性导航模块架构声明:1、该架构不含操作系统,希望该架构简单,硬件成本低廉,CPU的主频,Flash和RAM较小的情况下也能应用; 2、本系统嵌入式程序可用C开发,也可以用C++开发,希望大家可以灵活运用。以下将用C或伪代码来表示:首先分为几大模块:1、主程序main;2、调度模块Schedule;3、加速度计底层驱动模块ACC_BSP4、陀螺仪底层驱动模块GYRO_BSP5、初始化模块Init6、错误信息处理及记录模块Error7、系统时钟模块System_Time8、通信模块Com9、滤波模块Filter10、配置模块Config11、消息模块MSG12、警告、显示模块 Warn,Display13、存储模块Flash14、数学运算模块math15、异常重构模块 construct先构想这么多吧,大家可以讨论下,是否合理,可以进行添加或减少。首先,根据系统需求,估算下该系统会占用多大的CPU资源,Flash和RAM占用情况,模块调度允许周期,计算时间等。当前我定义Stack:6K,RAM 2K 系统关键线程周期5ms 非关键线程周期20ms,大家也可以根据实际情况自己定义。今天先写主程序的系统时钟模块吧,这是其他模块允许时基的基础。声明回调函数:static void (UserCallback)(void);定义系统时钟滴答结构体struct Sys_Tick sys_time;定义系统时钟计数static volatile unsigned long SysTick = 0;系统时钟初始化,返回初始化成功与否 SINT8 System_Tick_Init(void) { SysTick_Config(xxxxx);/*根据嵌入式CPU晶振大小进行,系统时钟配置 */ sys_time.Sys_Ticks_Per_us = SystemCoreClock /xxxx;/*根据系统时钟,计算每us的滴答数 */SetPriority(xxxx);/*设置系统时钟中断优先级 */ .......判断设置初始化成功与否 if(xxxx){return FAULT;}elsereturn SUCESS;} /*系统时钟中 */void SysTick_Handler(void){ __disable_irq();/*关闭所有中断 */Check_SysTick_Underflow(); /*检查系统时钟溢出 */SysTick++;/*系统时钟计数*/__enable_irq(); /*打开所有中断*/UserCallback(); /*调用回调函数*/}定义返回当前时间函数UINT32 micros(void){ do{ xxxxxxxx= xxxx; 获取当前值 asm volatile("nop");/*精确时间调整 */}while(!xxxxx);判断时间是否达到Check_SysTick_Underflow(); /*检查系统时钟溢出 */ 时间转换 return (timeMs * 1000) + (重新装载值 + 1 - 当前值) / sys_time.Sys_Ticks_Per_us;返回需要的一定单位的时间}返回系统时间UINT32 millis(void){ xxxxxxxxx}回调函数void SysTic_Callback(void (*callback)(void)){ UserCallback = callback;}定义看们狗,此处用软件方式实现SINT8 WatchDog(void){ 判断看门狗计数值设定值是否超过 WatchDogCounter = 0;}系统时钟部分完成了,我们来写下main主函数,之后验证下。int main(void){if(Power_On_Task() == SUCESS)//系统执行上电任务,包括我们刚完成的系统时钟设置初始化和各种其他初始化等给出提示信息获取系统当前时间Last_Time = micros();while(1){ Current_Time = micros(); 获取系统当前时间Time_Passed = Current_Time - Last_Time;if(Time_Passed > 5) /*5ms*/ //0.122093 0.14209{ 启动状态机,调用5ms任务 //0.127093 0.14709 Small_Period_Loop(); 判断时间,调用大周期任务xxxxxWatchDogCounter = 0;看门狗计数清零Last_Time = Current_Time;}}}主函数部分和系统时基部分都很简单,经过验证,时间调度周期精确,满足设计要求。未完待续,敬请关注。
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮