//7.6 程序清单
#include <p30F6010.h>
#include <qei.h>
#include <timer.h>
#include <math.h>
#include <stdio.h>
//速度计算的两个变量
int AngPos[2] = {0,0};
int POSCNTcopy = 0;
#define MAX_CNT_PER_REV (500 * 4 - 1)
#define MAXSPEED (unsigned int)(((unsigned long)MAX_CNT_PER_REV*2048)/125)
#define HALFMAXSPEED (MAXSPEED>>1)
int Speed;
//初始化QEI模块
void InitQEI(void)
{
ADPCFG |= 0x0038; // 配置QEI的引脚为数字输入
QEICONbits.QEIM = 0; // 禁止QEI模块
QEICONbits.CNTERR = 0; // 清除任何一个计算错误
QEICONbits.QEISIDL = 0;// 休眠模式继续操作
QEICONbits.SWPAB = 0; // QEA和QEB不交换
QEICONbits.PCDOUT = 0; // 正常I/O引脚操作
QEICONbits.POSRES = 1; // 索引脉冲复位位置计数器
DFLTCONbits.CEID = 1; // 记数错误中断禁止
DFLTCONbits.QEOUT = 1; // 数字滤波输出使能QEn引脚
DFLTCONbits.QECK = 5; // QEn引脚1:64时钟分频数字滤波
DFLTCONbits.INDOUT = 1;// Index引脚数字滤波输出使能
DFLTCONbits.INDCK = 5; // Index引脚1:64时钟分频数字滤波
POSCNT = 0; // 复位位置计数器
QEICONbits.QEIM = 6; // X4模式,Index引脚位置计算器复位
return;
}
//计算QEI角位置:POSCNT由配置的Index引脚脉冲自动复位
void PositionCalculation(void)
{
POSCNTcopy = (int)POSCNT;
if (POSCNTcopy < 0)
POSCNTcopy = -POSCNTcopy;
AngPos[1] = AngPos[0];
AngPos[0] = (unsigned int)(((unsigned long)POSCNTcopy * 2048)/125);
// 0 <= POSCNT <= 1999,所以 0 <= AngPos <= 32752
return;
}
//初始化TIMER1 ,每0.0075 SEC产生一次中断
void InitTMR1(void)
{
TMR1 = 0; // 复位时间计数器
T1CONbits.TON = 0; //关闭Timer1
T1CONbits.TSIDL = 0; //处于休眠模式时继续操作
T1CONbits.TGATE = 0; //禁止门时间累加
T1CONbits.TCS = 0; //使用Tcy作为时钟源
T1CONbits.TCKPS = 2; //输入时钟Tcy / 64
PR1 = 1728; //预分频为1:64,中断周期为 = 0.0075 sec
IFS0bits.T1IF = 0; //清Timer 1中断标志
IEC0bits.T1IE = 1; //使能Timer1中断
T1CONbits.TON = 1; //打开Timer1
return;
}
//角速度计算中断子程序
void __attribute__((__interrupt__)) _T1Interrupt (void)
{
IFS0bits.T1IF = 0; //清Timer1中断标志位
PositionCalculation();
Speed = AngPos[0] - AngPos[1];
if (Speed >= 0)
{
if (Speed >= (HALFMAXSPEED))
Speed = Speed - MAXSPEED;
}
else
{
if (Speed < -(HALFMAXSPEED))
Speed = Speed + MAXSPEED;
}
Speed *= 2;
return;
}
int main( void )
{
Int v_temp;
InitQEI(); //初始化QEI模块
InitTMR1();//初始化Timer1
While(1){
PositionCalculation(); //计算QEI角位置
v_temp = Speed; //获取速度值
}
}