uCOS 学习随笔 StepbyStep-4—— 电机驱动任务(基于STM32控制的第四代圆梦小车)
0赞
[提要] 本篇为“uCOS 学习随笔”第四篇。本篇开始将逐一实现上一篇所构思的各个任务。本篇完成电机驱动任务,让小车跑起来。
一、 概述
在前一步已经初步构建了电机驱动任务,以及电机驱动的实现方式,这一步只是将其实施,让小车动起来。
二、实施
在实施这一步具体内容前,先做了一个准备工作,即将第三步所构建的程序优化,将新增的通讯功能从 app.c 中剥离出来,构建一个独立的文件:app_USART.c 以及app_USART.h。
为何要这样做呢?
在编写二代小车示例程序时,为了减少初学者的困难,将所有的内容汇集于一个文件,这样编译是比较简单了,而且也不必考虑变量的作用域,不必声明 public、extern。为了便于循序渐进,还特意将程序按照追加的功能编排,而不是逻辑上的顺序,本以为效果不错。可随着程序的内容增加,到了最后基本无法阅读了,所以这次吸取教训。
而且,由于是在 uCOSII 下编程,本身就是多文件工程,应用程序按多文件形式不会增加难度,但对阅读程序有很大帮助。
所以,从这一步开始,每增加一个功能,会创建一对文件 *.c 和 *.h。
关于 BSP 部分,还是继续在原来的 BSP.c 中添加,因为每次增加的内容有限,最关键的是,我认为BSP部分不影响对程序逻辑的理解。
按我的理解,所谓 BSP 程序,是将程序逻辑和硬件隔开的部分,通过 BSP 函数,使得程序逻辑功能的实现可以和硬件无关。不知道我的理解是否合适?
所以,所有和硬件相关的操作最好设置一个函数,将其隔开。中断服务程序一般为了提高效率,通常会直接操作硬件,本该放置在 BSP 中,但由于中断服务程序中的操作往往和程序功能实现有密切关系,对理解程序帮助很大,所以我还是将其放在对应的应用程序中。从我编写少量的 windows 和 Linux 程序的体验看,由于这些系统均将中断部分包裹在系统中,作为 BSP,所以使用它们的对应功能(如事件、定时器等)时就有些“虚”,有时需要靠“尝试”来理解之,不知各位读者是否有此体会?
如果日后做产品为了保密,BSP以库的方式提供,那可能应该将中断处理放入库中。此处是学习,以“易于理解”为基本需求。
2.1 实现方式
电机驱动主要有以下三部分操作:
1) 工作状态控制输出:由 2 个IO口组合实现4种电机工作状态;
2) PWM信号形成:产生125Hz的脉冲信号,根据 PWM 值控制脉冲宽度;
3) 接收电机控制命令:将容易理解、容易处理的电机命令解析,变换为控制用参数,作为前两部分操作的依据。
第一项操作比较简单,按照电机控制真值表输出相应的电平即可。
第二项有些难度,首先要生成脉冲周期,利用 Timer2 的 Counter,减计数和自动重加载组合,形成 8ms 的 PWM 周期。
根据第三步的“电机驱动任务”设计,从硬件初始化开始,逐步构建程序。
2.2 程序构建
第一步:初始化硬件
电机驱动涉及的硬件有6个I/O输出口和1个定时器,以及定时器中断。
因为电机驱动频率较低,且由于PCB排版和资源分配的限制,没有使用定时器的硬件 PWM功能,而是在定时器中断服务中由软件控制I/O口实现 PWM输出,所以I/O选择比较灵活。在 BSP 中初始化如下:
……
第二步:定义任务、消息及全局变量
……
用全局变量向Timer2中断服务程序传递信息,因为在中断中使用消息机制怕占用过长的时间;但其它任务向电机驱动任务传递消息采用OS提供的邮箱机制。
第三步:编写中断服务程序
定时器中断主要任务是产生 PWM 信号,使用 2 个通道比较器方式中断触发 PWM 输出,用Count 归零(Timer2 工作于减计数方式,见初始化程序)中断结束PWM输出。
因为 PWM 的改变是在电机驱动任务中,所以用全局标志通知中断是否需要修改比较值。
此外,为了支持PWM为100% 的连续输出,设置了全速标志 FullSpeed。
……
第四步:编写电机驱动任务
电机驱动任务在完成相关初始化之后,进入等到邮件状态,收到邮件后,根据邮件内容设置电机工作状态(正转、反转、惰行、刹车)和PWM值,之后再次进入等待。维持电机工作的任务实际上是中断服务程序完成的。
……
因为设置电机工作状态和硬件强相关,故将其作为BSP函数,内容很简单,就是用STM32库函数中的 I/O 口位操作命令设置相应的输出端即可。
为了增加点噱头,在将电机PWM命令转化为电机工作状态和PWM值过程中,增加了一点“智能”:因为电机直接从正转到反转电流会很大,故人为插入一个刹车状态,不一定实用,供参考。这样处理就比较复杂,因为左、右电机要处理两次,所以设计了函数,同时定义了电机控制的数据结构,以便于传递参数。
电机控制参数数据结构:
……
这样将数据结构指针传入函数即可。
……
至此,电机驱动任务已完成,只需将左右电机的PWM值通过邮件发送给电机驱动任务即可操作电机。
为了便于调试,还是按照圆梦小车二代的方式,在通讯中增加一个电机测试命令,为简化,借用小车二代的通讯协议和PC程序,在接收后将原来的PWM值转换为本次所定义的PWM数据格式。
第五步:在通讯任务中增加电机测试命令: MOTOR_PWM
在命令解析函数 do_Command中增加:
……
这样,就可以很方便的用PC通过串口测试电机驱动功能了。
读者如果有兴趣,可以对照圆梦小车 StepbyStep -3 的程序,看看两种编程方式有何差别?
2.3 调试中所遇到的问题
程序逻辑没有遇到任何问题,应该说对于 uCOS的理解还是正确的,邮箱的应用一次成功。
唯一出现问题的还是硬件,不知为何?每次定时器Count归零时,不但将自己的溢出标志置位,还将其它几个通道的中断标志也置位了,导致PWM输出不对,从手册中未找到答案,只好在归零中断时将其它标志清除。
三、结语
总体来说,电机驱动程序编写还算顺利,只是觉得还有些“散”,似乎还需要进一步“包装”,使应用程序使用时可以更简洁、易懂。
同时,由于电机是共享资源,目前只有一个测试任务控制,如果有多个任务控制,可能需要设置互斥锁,以免冲突。而且由于邮箱只能存放一份邮件,所以多个任务驱动共同控制时,在发送邮件时似乎需要判断,以免邮件发送失败,导致电机控制无效。
下一步编写电机电流、电压检测程序,因为和电机驱动关系密切,所以先着手实现。
————————————
2011年1月24日星期一
(注:因文中代码编排较烦,故略去,有兴趣可下载 PDF 文档)
PDF格式文档下载
参考资料:
1、《嵌入式实时操作系统 uC/OS-II(第二版)》邵贝贝 等译 ISBN7-81077-290-2
2、《基于嵌入式实时操作系统的程序设计技术》周航慈 吴光文著 ISBN978-7-81077-941-8
3、《Cortex-M3 + uCOS-II嵌入式系统开发入门与应用》陈瑶等著 ISBN978-7-115-23105-5
4、《uC/OS-II 标准教程》杨宗德 张兵 著 ISBN978-7-115-20442-4
5、uC/OS-II 官方网站资料
6、STM32LIB V 2.03 库例程和手册
