本文介绍项目是有关机器人控制的实现。控制部分采用PICl6F7X系列单片机,运用汇编语言编程,运行速度较快,能够达到系统的要求。在这里使用的大多是数字信号的控制,电机的控制只有开和合两种状态。在动作的过程中需要两只手臂、身体、头部、脚部等的协调动作。整个控制系统比较复杂,因而在PIC程序编写和空间分配方面需要注意一些问题。 4 w! w, N; A" N7 J 1、 动作标志位的使用 ( L0 `# s: q7 `6 y在整个控制中,组合的动作很多,当所有动作定位都通过光电开关控制时,在程序编写上就有一些问题。如要求左手上升到鼓掌位、右手上升到举手位(手初始位置在最下的放下位),光电开关0有效(即为0时是挡住),到达正确位置。用简单的理解可以写成下面的程序: " y0 C: P& I" ~7 vlist P=16c73 call lefthandup i: Z$ c5 e" v" V N6 b* Rcall righthandup % s, `1 ]5 q' q$ O& _LO call readinsignal 9 \8 t+ X' B2 {5 cbdss csl_v,1efthandligbts $ G' K) Q' }+ p) P& \call lefthandstop btfsc csl_v,righthandlight4 goto L0 2 f% X/ t; [/ z- n; o- Ycall righthandstop L1 call readinsignal 4 a# i* Z% a9 @ J7 N6 c' _btfsc csl_v,lefthandlight3 ( U* g2 K* v7 z) ~* |; ~3 L( jgoto L1 ' i2 O% E0 X' q8 t" Q. m dcall lefthandstop & [+ \) [& z* @+ {8 a: lefthandlight表示光电开关,由此判断是否到相应的位置。1表示在手臂最下面的位置;2表示在手臂的握手位置;3表示在手臂的鼓掌位置;4表示在手臂的高举手位置。上面程序描写左手臂上升到举手位置和右手臂上升到鼓掌位置并停止的过程。先判断左手到达否,到达则左手停止,接着看右手是否到达举手位,到达则停止,否则循环上述的检测,直到左手到达鼓掌位,右手到达举手位。 注意,这里的3,4表示的就是鼓掌位,举手位。经过循环检测可以让手臂停在各位上,然而机械动作是有惯性的,机械停止位可能在该位的上一点或下一点,这就影响下面动作的进行,可能在若干动作后机械动作出现失常,也就是程序没法正常的运行。在此情况下,需要修改程序的编写方式,采用标志位来控制动作的进行。如果采用控制标志位,一定要在动作子函数中对标志位置零。程序如下: 1 b9 N0 n7 G/ q" P- tlist p=16c73 5 u' V% l& I( _9 g( |: * }; Y) v5 G) j6 u6 CactlONstopflag equ Ox6e ;位定义 3 I p% K0 D% }. l* S( flefthandfla8 cqu 0x0 ;0表示停止左手动作 rightbandflag equ Oxl ;O表示停止右手动作 : movlw Ox03 ' e* C( G9 I' h& L. LmovWf actionstopflag 3 N7 E# ]" z2 O! o3 Ycall lefthanduo call righthandup L2 call readinsignal btfss csl_v,lefthandhght3 call lefthatldotop btfss csl_v,righthandlight4 9 z( O! J5 E7 \( j) Qcall righthandstop movlw Ox00 & X$ N2 R7 ~) _+ X: Csubwf acTIonstopflag,w btfss status,z * I: J* B$ j$ z Cgoto L2 继续下面的程序 acTIonstopflag 表示动作标志位参数,给动作标志位赋值,动作停止函数中将清零标志位的值。上述程序和前面所述程序的功能一样,实现两支手臂的动作。上面程序描写左手是否到达鼓掌位,到达停止,右手是否到达举手位,到达停止。看动作标志位是否为零,不是,不断地循环检测;是,执行下面的程序。 2 、GOTO,CALL指令的不同使用 在PIC的汇编程序中,CALL与GOT0指冷使用的场合不同。一般情况下,在于程序与主程序之间大多用CALL指令;而状态转换模块之间大多用GOTO 指令,即由此状态进入另一种状态不需返回。由于PIC单片机的堆栈有限,在程序中,不能无止境地使用GOTO语句,这样会使堆栈溢出,程序无法正常运行。各个小程序内部循环占用堆栈的级数不多,使用GOTO指令是可行的,但在大的程序中用GOTO则无法返回到调用前程序的下一条指令。CALL指令完成调用完子程序后返回到调用前的程序。程序如下: , q* G3 J P7 J0 K* T7 x' n' zlist D=16c76 ?8 ~) G% [' ?start:ca11 setcpu / O) e4 L/ k, I- P! L6 U$ p3 ^; Ycall automatlsn、statel 0 @- B$ X. |5 q' ? b' i8 nL3 call readinsignal - R' v6 `- F* v" u' ~ vbtfsc cs2_v,ultrasonicdetectl % e7 b5 b7 K2 Z# ugoto L3 goto autonatlsmstate2 : 5 y2 [: a: K) N3 Y5 Gautomatlsmstate2: return % R- M6 [" |0 q7 a$ ^% JauatomaTIsmstatel、 automaTIsmstate2表示两种状态,uhrasonicdetectl表示一个输入超声检测信号。上面程序描写调用 automatistmstate1状态,执行完后进行下面的检测ultrasonicdetect],没有触发就一直循环检测,触发就进入 autornatismstate2状态,执行完也不再回到下面的程序。 + ~/ ?. v% a* ?) i/ c3 、状态标志位Z、C的不同使用情况 * |" C! s( F9 P+ B6 U在进行判断标志位时,Z(零标志)、C(借位标志)是不同的。Z为l时,表示上面的结果为0,Z为0时,则结果不为0。C为l时,借位,C为0时,没有借位。在使用定时器的时候,一般使用C标志位,这是由于当完成某一动作去检查定时器时,时间可能没到,或是正好,或是已经超过时间,只要到了或超过时间,都要按照要求关闭定时器,如下面程序所述。如果用Z标志位,等于0时可能没有检测到,无法判断停止的状态,而用z可以很好地控制时间定时。进行一般的计算时大多用Z,如前面的动作标志位中就是如此使用的。 list D=16c76 call opentimerO L4 movlw d’30’ subwf t0_v2,W btfss status,c goto L4 " `% \2 l" Q5 fcau closetimer0 程序检测时间是否到达1.5s,没有则循环等待,到了或检测时间过了就关闭定时器,执行下面的程序。 总之,在PIC单片机的编程中采用合适的方法,可以使整个程序运行稳定,而且程序空间的使用也将有所减小,避免了调试中的Bug。这是笔者在实际中的一点体会,还有许多不足或没有考虑到的问题,希望在和大家的探讨中不断学习PIC单片机的精髓。 |
该用户从未签到 |