// ============= 电机 PWM ======================
PDC1 = 0; PDC2 = 0; PDC3 = 0; PDC4 = 0;
// 中心对齐 PWM。
// 注:PWM周期设定为 dLoopInTcy/2,但由于先采用递增计数随后为递减计数, // =>在计数到零时中断标志置 1 =>因此实际中断周期为 dLoopInTcy //
PTPER = dLoopInTcy/2; // 将 PWM周期设定为循环时间,该参数在 parms.h中定义
PWMCON1 = 0x0077; // 使能 PWM 1,2,3对工作在互补模式 DTCON1 = dDeadTime; // 死区时间 DTCON2 = 0;
FLTACON = 0; // 未使用 PWM故障引脚 FLTBCON = 0;
PTCON = 0x8002; // 使能 PWM中心对齐
// SEVTCMP: 特殊事件比较计数寄存器
// 相对于 PWM周期的 ADC捕获设定相位: 0偏移量和递增计数 SEVTCMP = 2; // 不能为 0,否则关断触发器(文档中未列明)
SEVTCMPbits.SEVTDIR = 0;
// ============= 编码器 ===============
MAXCNT = MotorParm.iCntsPerRev; POSCNT = 0; QEICON = 0;
QEICONbits.QEIM = 7; // 通过 MAXCNT脉冲复位 x4 QEICONbits.POSRES = 0; // 不要让索引脉冲复位计数器 QEICONbits.SWPAB = 0; // 方向
DFLTCON = 0; // 数字滤波器设定为关闭
// ============= ADC - 测量电流和电位器给定值 ====================== // ADC设定为对以下通道同时进行采样: // CH0=AN7, CH1=AN0, CH2=AN1, CH3=AN2
// 采样由 PWM触发,且采样结果以有符号小数形式存放。
ADCON1 = 0;
// 有符号小数格式( DOUT = sddd dddd dd00 0000) ADCON1bits.FORM = 3;
// 电机控制 PWM间隔终止采样并启动转换 ADCON1bits.SSRC = 3;
// 同时采样选择位(仅当 CHPS =01或 1x时应用)
// 同时采样 CH0、 CH1、 CH2和 CH3(当 CHPS = 1x时) // 同时采样 CH0和 CH1(当 CHPS=01时) ADCON1bits.SIMSAM = 1;
//在上一次转换结束后立即开始采样。 // SAMP位自动置位。 ADCON1bits.ASAM = 1;
ADCON2 = 0;
// 同时采样 CH0、 CH1、 CH2、 CH3(当 CHPS = 1x时) ADCON2bits.CHPS = 2;
ADCON3 = 0;
// A/D转换时钟选择位 = 8 * Tcy ADCON3bits.ADCS = 15;
/* ADCHS:ADC输入通道选择寄存器 */ ADCHS = 0; // CH0 为 AN7
ADCHSbits.CH0SA = 7;
// CH1正极性输入为 AN0, CH2正极性输入为 AN1, CH3正极性输入为 AN2 ADCHSbits.CH123SA = 0;
/* ADPCFG:ADC端口配置寄存器 */ // 将所有端口设置为数字端口 ADPCFG = 0xFFFF;
ADPCFGbits.PCFG0 = 0; // AN0 模拟 ADPCFGbits.PCFG1 = 0; // AN1 模拟 ADPCFGbits.PCFG2 = 0; // AN2 模拟
ADPCFGbits.PCFG7 = 0; // AN7 模拟
/* ADCSSL:ADC输入扫描选择寄存器 */ ADCSSL = 0;
// 开启 A/D模块
ADCON1bits.ADON = 1;
#ifdefDIAGNOSTICS
// 对用于诊断模式的输出比较通道 7和 8进行初始化。
// PWM模式中使用比较 // Timer2用作时基 PR2 = 0x1FFF;
OC7CON = 0x0006; OC8CON = 0x0006; T2CONbits.TON = 1; #endif
return False; }
#ifdefDIAGNOSTICS
void DiagnosticsOutput(void) {
int Data;
if(IFS0bits.T2IF) {
IFS0bits.T2IF = 0;
Data = (ParkParm.qIq >> 4) + 0xfff; if(Data > 0x1ff0) Data = 0x1ff0; if(Data < 0x000f) Data = 0x000f; OC7RS = Data;
Data = (EncoderParm.qVelMech) + 0x0fff;
if(Data > 0x1ff0) Data = 0x1ff0; if(Data < 0x000f) Data = 0x000f; OC8RS = Data; } }
#endif
Encoder.c
// 编码器子程序的定标
#include \ #include \ #include \
/********************************************************** InitEncoderScaling
对编码器子程序的定标常量进行初始化。
函数参数:
CntsPerRev:来自正交编码器的每转编码器计数值 ScalingSpeedInRPS:用于基本转速定标的每秒转数 IrpPerCalc:每次转速计算的 CalcVelIrp中断数 VelIrpPeriod:VelCalcIrp中断间的周期(单位为秒)
对于
CalcAng: 运行时方程:
qMechAng = qKang * (POSCNT*4) / 2^Nang
定标方程:
qKang = (2^15)*(2^Nang)/CntsPerRev.