在16位的工作模式下,要先载入TMR1H内容,在再载入TMR1L内容。具体的初始化结果如下:
T0CONbits.TMR0ON=0;//TMR0停止工作
T0CONbits.T08BIT=0;//选择16位的定时/计数器 T0CONbits.T0CS=0;//选择内部CLKO时钟源作为定时 T0CONbits.PSA=0;//选择预分频器 T0CONbits.T0PS2=1;//预分频比为1:256 T0CONbits.T0PS1=1; T0CONbits.T0PS0=1;
TMR0H=(65536-31250)/256;//先写高字节 TMR0L=(65536-31250)%6;//再写低字节 T0CONbits.TMR0ON=1;//开始定时工作 4.3.1.4 TMR1定时/计数器初始化
由光栅盘产生的脉冲信号送到RC0/T13CK引脚,由TMR1对其进行脉冲计数,因此TMR1必须初始化在外部计数模式下,对T1CON寄存器进行设置,TMR1L和TMR1H初始化为0。具体的设置如下:
T1CONbits.RD16=1;//允许一次性读写16位
T1CONbits.TMR1CS=1;//选择外部时钟源,TMR1用作外部计数 TMR1H=0;//TMR1数据寄存器清0 TMR1L=0;
T1CONbits.TMR1 ON=1;//允许TMR1开始工作 4.3.1.5 TMR3定时/计化数器初始
在用M/T法测量电机的速度时,需要有一个标准时钟产生标准的计数过程,此处用TMR3工作在16位的定时模式下,以1?s的速度进行标准脉冲计数。初始化的结果如下: T3CONbits.T3CKPS1=1; T3CONbits.T3CKPS0=1;
T3CONbits.RD16=1;//允许一次性读写16位
T3CONbits.TMR3CS=0;//选择内部时钟源,TMR3用作内部计数 TMR3H=0;//TMR3数据寄存器清0
26
TMR3L=0;
T3CONbits.TMR3ON=1;//允许TMR3开始工作 4.3.1.5 ECCP模块初始化
在原理图中,P1A和P1B分别接在L298的IN3和IN4引脚上来控制电机正反转并实现对电机的调速。此时,必须将ECCP模块初始化在PWM模式下,并且采用周期相同。PIC18F458的有四个PWM输出口,在PWM模式下,由TMR2来产生PWM信号周期,实际上要对TMR2进行初始化,并且设置PWM的周期和占空比。具体的初始化过程如下:
CCP1CON=0x0F;//CCP1设置为PWM模式 CCP2CON=0x0F;//CCP2设置为PWM模式 T2CON=0x03;//TMR2的预分频为1:16 T2CONbits.TMR2ON=1;//TMR2开始工作 PR2=249;//PWM周期为2000Hz,FOSC=32MHz CCPR1L=0;//PWM1的占空比为0 CCPR2L=0;//PWM2的占空比为0 4.3.1.5 CPU中断系统初始化
硬件中共用到4个中断源,分别是TMR0定时1s溢出中断、TMR1计数溢出中断源、TMR3定时溢出中断源和INT0外部中断。在这4个中断源中,将INT0和TMR0作为高优先中断放在高优先级中断服务程序中执行,TMR1和TMR3放在低优先中断服务程序中执行,因此就有中断优先级初始化。具体的初始化过程如下:
INTCONbits.TMR0IF=0;//TMR0溢出标志位清0 INTCONbits.TMR0IE=1;//TMR0溢出中断允许 PIR1bits.TMR1IF=0;//TMR1溢出标志位清0 PIE1bits.TMR1IE=1;//TMR1溢出中断允许 IPR1bits.TMR1IP=0;//低优先级
PIR2bits.TMR3IF=0;//TMR1溢出标志位清0 PIE2bits.TMR3IE=1;//TMR1溢出中断允许 IPR2bits.TMR3IP=0;//低优先级
INTCONbits.INT0IF=0;//清INT0中断标志位 //INTCONbits.INT0IE=1;//INT0中断允许 INTCON2bits.RBPU=0;//允许内部弱上拉
27
INTCON2bits.INTEDG0=1;//上边沿触发中断 RCONbits.IPEN=1;//允许中断优先级位 INTCONbits.GIE=1;//CPU全局中断使能允许 INTCONbits.PEIE=1;//CPU第二梯队中断使能允许 4.3.2 电机运行控制模块
电机运行控制模块包括电机的方向控制和电机的速度控制,他们由MotorDirection和MotorPWMData两量变来控制PIC单片机的ECCP模块产生不同的PWM信号送到L298 电机驱动器。当MotorDirection=0时,表示正转;当MotorDirection=1时表示电机反转。MotorPWMData是PWM模块占空比的具体内容,由于PWM的周期是250,所以MotorPWMData的变量变化是0—250之间。改变MotorPWMData的值就可以改变电机的速度。具体函数过程如下:
void Motor_Control(unsigned char Direction, unsigned char Speed) {
If(0==Direction) {
CCPR1L=0; CCPR2L=0; CCPR1L=Speed; }
else {
CCPR2L=0;
CCPR1L=0; CCPR2L=Speed; } }
4.3.3 按键识别模块
主程序中要实现对电机启动、停止键识别、电机方向切换键识别和电机速度调节键识别。该模块中没有采用常规的按键识别过程。 4.3.3.1按键识别方法。
28
? 判断是否有键按下。 ? 延时去除按键抖动。 ? 再判断是否真的按下。
? 是真的按下,则执行按键处理程序。 ? 等待按键释放。
在第2步中一般在软件上调用一个延时子程序来完成,实际也是一个For循环语句;在第5步中一般在软件上是用一个While循环语句判断等待按键发生变化而退出该循环。这两步在主程序中执行要消耗CPU很多时间,使得CPU的利用率不高。对于实时性要求比较高的情况不建议使用这种方法解决按键问题。为了提高CPU利用率,可以采用硬件扩展键盘识别专用芯片来完成,但这样会造成成本的上升以及CPU或专用芯片的资源浪费。
为了考虑提高CPU的效率和充分利用CPU的资源等因素,可将第2步和第5步的延时和等待过程用其他方式来代替。具体实现方法如下:
(1)
定义一个按键是否成功按下标志变量KeyCounter;等于1表示按下成功,等于0表示不成功。
(2) (3)
定义一个软计数器加1的整型变量KeyCounter。
所有直接采用While循环语句或For循环语句的部分采用If语句代替。
按键识别过程的方法步骤如下: (1) 判断按键是否按下。
(2) 若按下,则判断KeyFlag标志是否为0。
(3) 若KeyFlag标志为0,则KeyCounter软计数器加1。
(4) 判断KeyCounter软计数是否到一定的数值(这一过程实际上是按键去抖动处
理)。
(5) 若KeyCounter计到一定数值上,则判断按键是否真的按下。 (6) 若按键真的按下,则置KeyFlag为1,表示按键按下成功。 (7) 开始进行按键对应功能的处理过程。 (8) 判断按键是否释放。
(9) 若按键释放,则清KeyFlag为0,同时清KeyCounter软计数器为0。 4.3.4 按键方法程序框图
该按键识别过程的新方法程序框图如图4.3.4所示。在整个过程中没有出现循环语句,从而使得主程序运行模块的效率得提高,保证了CPU的实时性。
29
图4.3.4按键识别方法程序框图
本实例中,CPU对电机启动、停止控制键(RUNSTOPKEY)、电机方向切换键(DIRKEY)和电机速度调节键(PWMKEY)的识别方法与4.3.4相同,只是在框图中的“按键功能处理”不同而已。
4.3.5 电机启动、停止控制键(RUNSTOPKEY)功能处理
如果系统上电时电机处于停止状态即(MotorRunStatus=1);如果电机处于运行状态,按下RUNSTOPKEY后,电机就会停下来,电机的的运行与停止状态在这个按键的作用下进行就可以控制电机的启动与停止操作。此部分的按键功能处理程序框图如图4.3.5.1所示。
30