1.首先教你怎么做

首先查看 两个文件

DSP2833x_EQep.h  文件

DSP2833x_EQep.c 文件


2.代码:  (没有想到吧 !  没有注释 !! 因为我也不知道,咋做出来的!!, 头脑混乱)

/** main.c* TFTLCD字符显示实验* 作者 : she001* 时间: 2022/10/24* 程序功能:外部中断 开始方向 , key1 num全局变量  +1   key2  num全局变量  -1    key3 num全局变量  +10   key 全局变量 -10 (别按 中断2  有 bug)*//* 头文件汇总 */
#include <bsp_includes.h>
#include <math.h>
#include "IQmathLib.h"typedef struct
{volatile struct EPWM_REGS *EPwmRegHandle;Uint16 EPwm_CMPA_Direction;Uint16 EPwm_CMPB_Direction;Uint16 EPwmTimerIntCount;Uint16 EPwmMaxCMPA;Uint16 EPwmMinCMPA;Uint16 EPwmMaxCMPB;Uint16 EPwmMinCMPB;
}EPWM_INFO;typedef struct {float ElecTheta;    //OutPut: Motor Electrical Anglefloat MechTheta;    //Output: Motor Mechanical Anglefloat MechTheta_Beyond;  //存储超过一圈后的位置信息的变量int DirectionQep; //output: Motor rotation directionint PolePairs;     //Parameter: 同步电机极对数int LineEncoder;   //Parameter: 码盘一周脉冲数(增量式)int Encoder_N;     //Parameter: 码盘一周脉冲数的4倍(根据倍频的倍数而定,这里用4倍频)int CalibrateAngle;//Parameter:电机A相绕组和码盘Index信号之间的夹角,与安装精度有关float Mech_Scaler;   //Parameter:1/Encoder_Nfloat RawTheta;      //Variable: 初始定位后,电机转子d轴和定子A相绕组之间所相差的码盘计数值int Index_sync_flag;//Output: Index sync statusfloat BaseRpm;        //Parameter:额定转速float Speed_Mr_Rpm_Scaler;//Parameter:60000/(Encoder_N * T),其中T为M法测速时的时间间隔,单位ms//60/512线/(4倍频*0.001s)float Speed_Mr_Rpm;   //Output: speed int r.p.mfloat Speed_Mr;       //Output: speed in per-uintfloat Position_k_1;   //Input: Current positionfloat Position_k;     //Input: Last positionfloat Speed_Tr_Rpm_Scaler;//Parameter: (UPPS * 150e6 * 60)/(Encoder_N * CCPS)//150e6*60/512float Speed_Tr_Rpm;   //Output: spedd int r.p.mfloat Speed_Tr;       //Output: speed int per-uintfloat t1;float t2;float t3;float Ts; // 采样时间float K2; //滤波系数float Speed_Temp;float Speed;             // Output :  speed in per-unitUint32 K;int cnt_old; //eQEP位置计数器寄存器中上一个时刻的计数值int cycles; // 电机转过的圈数float position;void (*init)();         // Pointer to the init funcionvoid (*calc)();} EQEP_POS_SPEED_GET;//-----------------------------------------------------------------------------
// Define a POSSPEED_handle
//-----------------------------------------------------------------------------
typedef EQEP_POS_SPEED_GET  *EQEP_POS_SPEED_GET_handle;//-----------------------------------------------------------------------------
// Default initializer for the POSSPEED Object.
//-----------------------------------------------------------------------------
#if (CPU_FRQ_150MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\9.76,0,0,0,0,\17578125,0,0,\0,0,0,0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}//注意9.76是0.003s为周期//#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\
//                                     2,500,2000,0,1.0/2000,0,0,\
//                                     6000.0,\
//                                     29.29,0,0,0,0,\
//                                     17578125,0,0,\
//                                     0,0,0,0,0,0,0,0,0,0,0,\
//                                     (void (*)(long))eQEP_pos_speed_get_Init,\
//                                     (void (*)(long))eQEP_pos_speed_get_Calc}#endif#if (CPU_FRQ_100MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\3.0,0,0,0,0,\1125000,0,0,\0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}
#endif#define Key_Read *((Uint16 *)0x4700)
#define KeyValue ((Key_Read)&0x0f)
#define keyon1 GpioDataRegs.GPADAT.bit.GPIO29// Configure the period for each timer
#define EPWM1_TIMER_TBPRD  2000  // Period register
#define EPWM1_MAX_CMPA     1950
#define EPWM1_MIN_CMPA       50
#define EPWM1_MAX_CMPB     1950
#define EPWM1_MIN_CMPB       50// To keep track of which way the compare value is moving
#define EPWM_CMP_UP   1
#define EPWM_CMP_DOWN 0// 中断服务子程序在主程序下面时,需要在主程序之前要先申明才能使用.
interrupt void xint1_isr(void);
void delay_loop_2(void);
void delay_loop_1(void);//超短时间的延时
void InitEPwm1Example(void);
void update_compare(EPWM_INFO*);
void Init_Port(void);//电机初始化函数
// Global variables used in this example
EPWM_INFO epwm1_info;int num=200;//PWM的数值
int speed=0;//测量的速度
int fangxiang=0;//当fangxiang=0  电机转动的方向为  正向   , fangxiang==1  电机转动的方向为 反向
/********************************************************************************************* 在做TFTLCD时,找到对用的头文件,改变宏定义即可,* */
#if (TFTLCD_TEST == 1)
uchar class[]= {"班级 "};
uchar Name[]= {"名字 "};
uchar student_ID[]={"学号: "};
uchar Str1[] = {"PWM :   "};//方向的提示语句
uchar Str2[] = {"速度: "};//速度的提示语句
#endif///EQEP模块
int DirectionQep=0;
int LineEncoder=500;
int Encoder_N=2000;
unsigned int motor_speed=100;
float Speed_Mr_RPM=0;
float Position_k_1=0;
float Position_k=0;
unsigned int delay_show=0;struct EQEP_POS_SPEED_GET
{float ElecTheta;    //OutPut: Motor Electrical Anglefloat MechTheta;    //Output: Motor Mechanical Anglefloat MechTheta_Beyond;  //存储超过一圈后的位置信息的变量int DirectionQep; //output: Motor rotation directionint PolePairs;     //Parameter: 同步电机极对数int LineEncoder;   //Parameter: 码盘一周脉冲数(增量式)int Encoder_N;     //Parameter: 码盘一周脉冲数的4倍(根据倍频的倍数而定,这里用4倍频)int CalibrateAngle;//Parameter:电机A相绕组和码盘Index信号之间的夹角,与安装精度有关float Mech_Scaler;   //Parameter:1/Encoder_Nfloat RawTheta;      //Variable: 初始定位后,电机转子d轴和定子A相绕组之间所相差的码盘计数值int Index_sync_flag;//Output: Index sync statusfloat BaseRpm;        //Parameter:额定转速float Speed_Mr_Rpm_Scaler;//Parameter:60000/(Encoder_N * T),其中T为M法测速时的时间间隔,单位ms//60/512线/(4倍频*0.001s)float Speed_Mr_Rpm;   //Output: speed int r.p.mfloat Speed_Mr;       //Output: speed in per-uintfloat Position_k_1;   //Input: Current positionfloat Position_k;     //Input: Last positionfloat Speed_Tr_Rpm_Scaler;//Parameter: (UPPS * 150e6 * 60)/(Encoder_N * CCPS)//150e6*60/512float Speed_Tr_Rpm;   //Output: spedd int r.p.mfloat Speed_Tr;       //Output: speed int per-uintfloat t1;float t2;float t3;float Ts; // 采样时间float K2; //滤波系数float Speed_Temp;float Speed;             // Output :  speed in per-unitUint32 K;int cnt_old; //eQEP位置计数器寄存器中上一个时刻的计数值int cycles; // 电机转过的圈数float position;void (*init)();         // Pointer to the init funcionvoid (*calc)();};//-----------------------------------------------------------------------------
// Define a POSSPEED_handle
//-----------------------------------------------------------------------------
typedef EQEP_POS_SPEED_GET  *EQEP_POS_SPEED_GET_handle;//-----------------------------------------------------------------------------
// Default initializer for the POSSPEED Object.
//-----------------------------------------------------------------------------
#if (CPU_FRQ_150MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\9.76,0,0,0,0,\17578125,0,0,\0,0,0,0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}//注意9.76是0.003s为周期//#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\
//                                     2,500,2000,0,1.0/2000,0,0,\
//                                     6000.0,\
//                                     29.29,0,0,0,0,\
//                                     17578125,0,0,\
//                                     0,0,0,0,0,0,0,0,0,0,0,\
//                                     (void (*)(long))eQEP_pos_speed_get_Init,\
//                                     (void (*)(long))eQEP_pos_speed_get_Calc}#endif#if (CPU_FRQ_100MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\3.0,0,0,0,0,\1125000,0,0,\0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}
#endifvoid eQEP_pos_speed_get_Init(EQEP_POS_SPEED_GET *p)
{#if (CPU_FRQ_150MHZ)
//  EQep1Regs.QUPRD=1500000;            // Unit Timer for 100Hz at 150 MHz SYSCLKOUT
//案例给的程序错误的地方 这个是单位事件使能 也就是说M法EQep1Regs.QUPRD=150000*3;            // Unit Timer for 100Hz at 150 MHz SYSCLKOUT
#endif#if (CPU_FRQ_100MHZ)EQep1Regs.QUPRD=1000000;            // Unit Timer for 100Hz at 100 MHz SYSCLKOUT
#endifp->Encoder_N=4*p->LineEncoder;p->Mech_Scaler=1.0/p->Encoder_N;EQep1Regs.QDECCTL.bit.QSRC=0x00;        // QEP quadrature count modeEQep1Regs.QEPCTL.bit.FREE_SOFT=2;EQep1Regs.QEPCTL.bit.PCRM=0x01;         // PCRM=00 mode - QPOSCNT reset on index eventEQep1Regs.QEPCTL.bit.UTE=1;         // Unit Timeout EnableEQep1Regs.QEPCTL.bit.QCLM=1;        // Latch on unit time outEQep1Regs.QPOSMAX=p->Encoder_N;     // Encoder_NEQep1Regs.QEPCTL.bit.QPEN=1;        // QEP enableEQep1Regs.QCAPCTL.bit.UPPS=1;       // 1/2 for unit positionEQep1Regs.QCAPCTL.bit.CCPS=3;       // 1/8 for CAP clockEQep1Regs.QCAPCTL.bit.CEN=1;        // QEP Capture Enable
//  EQep1Regs.QPOSMAX=0xffffffff;p->cycles=0;p->Speed_Tr_Rpm_Scaler=60.0*150*1000000/4/p->Encoder_N;p->Speed_Tr_Rpm=0;//EQep1Regs.QEPCTL.bit.SWI=1;// software generate index pulse}//**********************************void eQEP_pos_speed_get_Calc(EQEP_POS_SPEED_GET *p)
{int cnt_inc , cnt_cur;float tmp1;unsigned int t2_t1;unsigned long M1,M2,fclk;//Check the rotational directionp->DirectionQep = EQep1Regs.QEPSTS.bit.QDF;cnt_cur = EQep1Regs.QPOSCNT;//Check the position counter for EQep1p->RawTheta = cnt_cur + p->CalibrateAngle;if(p->RawTheta < 0){p->RawTheta = p->RawTheta + EQep1Regs.QPOSMAX;}else if(p->RawTheta > EQep1Regs.QPOSMAX){p->RawTheta = p->RawTheta - EQep1Regs.QPOSMAX;}//Compute the mechanical anglep->MechTheta = p->Mech_Scaler * p->RawTheta;/*****************超过一圈后的角度计算*************/// Check the counter for QEPcnt_inc = cnt_cur - p->cnt_old;if (abs(cnt_inc) > 200)     //6000 RPM, 1ms能读到的最大差值就是200,  除非转角超过1圈.{if (cnt_inc < 0)p->cycles +=1;elsep->cycles -=1;}p->cnt_old = cnt_cur;//Compute the mechanical angletmp1=p->MechTheta_Beyond;   // old positionp->MechTheta_Beyond = p->MechTheta+p->cycles;p->Speed = 60*(p->MechTheta_Beyond-tmp1)/p->Ts;   // speed in RPM values// Check an index occurrenceif (EQep1Regs.QFLG.bit.IEL == 1){p->Index_sync_flag = 0x00F0;EQep1Regs.QCLR.bit.IEL=1;                   // Clear interrupt flag}//// High Speed Calculation using QEP Position counter// Check unit Time out-event for speed calculation:// Unit Timer is configured for 100Hz in INIT function//if(EQep1Regs.QFLG.bit.UTO==1)// If unit timeout (one 100Hz period){p->Position_k =1.0 * EQep1Regs.QPOSLAT;if(p->DirectionQep==0) // POSCNT is counting down{if(p->Position_k > p->Position_k_1){ tmp1 = -(p->Encoder_N - (p->Position_k - p->Position_k_1)); }else{ tmp1 = p->Position_k - p->Position_k_1;}// x2-x1 should be negative}else if(p->DirectionQep==1)    // POSCNT is counting up{if(p->Position_k < p->Position_k_1){ tmp1 = p->Encoder_N - (p->Position_k_1 - p->Position_k); }else{ tmp1 = p->Position_k - p->Position_k_1;}// x2-x1 should be positive}if(tmp1 > p->Encoder_N){ p->Speed_Mr_Rpm = p->BaseRpm;  }else if(tmp1 < -p->Encoder_N){ p->Speed_Mr_Rpm = -p->BaseRpm; }else{ p->Speed_Mr_Rpm = tmp1 * p->Speed_Mr_Rpm_Scaler; }p->Speed_Mr = p->Speed_Mr_Rpm / p->BaseRpm;p->Position_k_1 = p->Position_k;EQep1Regs.QCLR.bit.UTO=1; // Clear interrupt flag}//    // Low-speed computation using QEP capture counter // T法if(EQep1Regs.QEPSTS.bit.UPEVNT==1)                          // Unit position event{if(EQep1Regs.QEPSTS.bit.COEF==0)                        // No Capture overflowt2_t1 =  EQep1Regs.QCPRD;else                                                    // Capture overflow, saturate the resultt2_t1 = 0xFFFF;//// Convert p->Speed_pr to RPM//if(p->DirectionQep==0)p->Speed_Tr_Rpm = - p->Speed_Tr_Rpm_Scaler / t2_t1; //negativeelsep->Speed_Tr_Rpm =  p->Speed_Tr_Rpm_Scaler / t2_t1;//       if(p->Speed_Tr_Rpm > p->BaseRpm)//         p->Speed_Tr_Rpm = p->BaseRpm;//       else if(p->Speed_Tr_Rpm < -p->BaseRpm)//         p->Speed_Tr_Rpm = -p->BaseRpm;//EQep1Regs.QEPSTS.all=0x88;          // Clear Unit position event flag// Clear overflow error flag}GpioDataRegs.GPATOGGLE.bit.GPIO6= 1;// GPIO06翻转  开始的时候为1  led 灯关闭GpioDataRegs.GPATOGGLE.bit.GPIO7= 1;// GPIO07翻转  开始的时候为1  led 灯关闭delay_loop_2();GpioDataRegs.GPATOGGLE.bit.GPIO6= 1;// GPIO06翻转  开始的时候为1  led 灯关闭GpioDataRegs.GPATOGGLE.bit.GPIO7= 1;// GPIO07翻转  开始的时候为1  led 灯关闭}EQEP_POS_SPEED_GET Pos_speed = EQEP_POS_SPEED_GET_DEFAULTS;void interrupt_init()
{EALLOW;  // 修改被保护的寄存器,修改前应添加EALLOW语句PieVectTable.XINT1 = &xint1_isr;EDIS;   // EDIS的意思是不允许修改被保护的寄存器// 在外设中断扩展模块中断使能寄存器中允许XINT1和XINT2: (组1中断4 & 5)// 使能CPU中断1(INT1):PieCtrlRegs.PIECTRL.bit.ENPIE = 1;          // 使能外设中断扩展PIE模块PieCtrlRegs.PIEIER1.bit.INTx4 = 1;          // 使能PIE组1的INT4IER |= M_INT1;                              // 使能CPU中断1(INT1)EINT;                                       // 开全局中断// GPIO29配置为输入引脚通用I/O口,接按键TZ1,TZ2EALLOW;GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 0;         // 选择为通用I/O口GpioCtrlRegs.GPADIR.bit.GPIO29 = 0;          // 方向定义为输入GpioCtrlRegs.GPAPUD.bit.GPIO29=0;GpioCtrlRegs.GPAQSEL2.bit.GPIO29 = 0;        // 外部中断1(XINT1)与系统时钟SYSCLKOUT同步GpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0x80;   // 每个采样窗口的周期EDIS;// 通过GPIO外部中断选择寄存器,选择GPIO12为外部中断1,选择GPIO13为外部中断2EALLOW;GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 0x1D;   // XINT1是GPIO29EDIS;// 配置外部中断1和2的中断控制寄存器XIntruptRegs.XINT1CR.bit.POLARITY = 0;      // 下降沿触发中断// 使能外部中断1和外部中断2XIntruptRegs.XINT1CR.bit.ENABLE = 1;        // 使能XINT1
}void TFTLCD(uchar str3,uchar str4)
{//TFTLCD实验#if (TFTLCD_TEST == 1)ILI9325_Init();         //TFT初始化//显示字符LCD_PutString(37, 20,class, WHITE,RED);//显示班级LCD_PutString(37, 50,Name,  WHITE,RED);//显示名字LCD_PutString(37, 80,student_ID, RED,WHITE);//显示学号LCD_PutString(37, 110,Str1, WHITE,RED);//PWMLCD_PutString(120,110,str4, WHITE,RED);//PWM 的值LCD_PutString(37,140,Str2, WHITE,RED);//速度LCD_PutString(110,140,str3, WHITE,RED);//速度的数值#endif
}void update_compare(EPWM_INFO *epwm_info)//电机调速函数
{epwm_info->EPwmRegHandle->CMPB=EPWM1_TIMER_TBPRD/2 - num;epwm_info->EPwmRegHandle->CMPA.half.CMPA=EPWM1_TIMER_TBPRD/2 + num;
}void bianhua()//改变显示器的 显示数据
{int n1;int n2;int n3;int n4;uchar str4[4];if(motor_speed<300){str4[0]=(motor_speed/100)+48;str4[1]=(motor_speed%100/10)+48;str4[2]=(motor_speed%10)+48;}if(num>(EPWM1_TIMER_TBPRD/2+1)){return;}update_compare(&epwm1_info);if(num<10){n1=num;}else if(num<100){uchar str3[2];n1=num/10;str3[0]=n1+48;n2=num%10;str3[1]=n2+48;TFTLCD(str4,str3);//输出数据}else if(num<1000){uchar str3[4];n1=num/100;str3[0]=n1+48;n2=num%100/10;str3[1]=n2+48;n3=num%10;str3[2]=n3+48;TFTLCD(str4,str3);//输出数据}else if(num<10000){uchar str3[5];n1=num/1000;str3[0]=n1+48;n2=num%1000/100;str3[1]=n2+48;n3=num%100/10;str3[2]=n3+48;n4=num%10;str3[3]=n4+48;TFTLCD(str4,str3);//输出数据}
}void kkkk()
{int n1;int n2;int n3;int n4;if(num>(EPWM1_TIMER_TBPRD/2+1)){return;}update_compare(&epwm1_info);if(num<10){n1=num;}else if(num<100){uchar str3[3];n1=num/10;str3[0]=n1+48;n2=num%10;str3[1]=n2+48;str3[2]=32;LCD_PutString(120,110,str3, WHITE,RED);//PWM 的值}else if(num<1000){uchar str3[4];n1=num/100;str3[0]=n1+48;n2=num%100/10;str3[1]=n2+48;n3=num%10;str3[2]=n3+48;LCD_PutString(120,110,str3, WHITE,RED);//PWM 的值}else if(num<10000){uchar str3[5];n1=num/1000;str3[0]=n1+48;n2=num%1000/100;str3[1]=n2+48;n3=num%100/10;str3[2]=n3+48;n4=num%10;str3[3]=n4+48;LCD_PutString(120,110,str3, WHITE,RED);//PWM 的值}}//函数入口
void main(void)
{//TFTLCD 初始化InitSysCtrl();DINT;InitPieCtrl();IER = 0x0000;IFR = 0x0000;InitPieVectTable();InitEPwm1Gpio();//PWM 控制电机的引脚初始化InitEPwm1Example();//PWM  控制电机的初始化 函数InitEQepGpio();//EQEP 模块引脚初始化Pos_speed.init(&Pos_speed);//EQEP 模块初始化InitXintf();InitSpiaGpio();interrupt_init();//中断初始化bianhua();//开始的显示EALLOW;GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 00;      // GPIO57为GPIO功能GpioCtrlRegs.GPBDIR.bit.GPIO57 = 1;      // GPIO57为输出功能EDIS;GpioDataRegs.GPBTOGGLE.bit.GPIO57= 1;// GPIO057翻转  开始的时候为1  led 灯关闭EALLOW;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;EDIS;InitEPwm1Example();EALLOW;SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;EDIS;IER |= M_INT3;EINT;ERTM;update_compare(&epwm1_info);Pos_speed.calc(&Pos_speed);///小灯模块EALLOW;GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 00;      // GPIO6为GPIO功能GpioCtrlRegs.GPADIR.bit.GPIO6 = 1;      // GPIO6为输出功能GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 00;      // GPIO7为GPIO功能GpioCtrlRegs.GPADIR.bit.GPIO7 = 1;      // GPIO7为输出功能EDIS;GpioDataRegs.GPATOGGLE.bit.GPIO6= 1;// GPIO06翻转  开始的时候为1  led 灯关闭GpioDataRegs.GPATOGGLE.bit.GPIO7= 1;// GPIO07翻转  开始的时候为1  led 灯关闭int mmm=0;int nnn=0;int hhh=0;int hhh1=0;while (1){if(nnn==10){motor_speed=mmm/10;nnn=0;mmm=0;uchar str4[5];str4[0]=(motor_speed%1000/100)+48;str4[1]=(motor_speed%100/10)+48;str4[2]=(motor_speed%10)+48;str4[3]=0;//空白 怕乱码LCD_PutString(110,140,str4,WHITE,RED);//速度的数值}else{hhh=(int)abs(Pos_speed.Speed_Tr_Rpm);if(hhh>240 || hhh<0){mmm+=hhh1;nnn++;}else{hhh1=hhh;mmm+=hhh;nnn++;}}Pos_speed.calc(&Pos_speed);if(KeyValue==0x0e)//1110  e{if(num<EPWM1_TIMER_TBPRD/2-10){num+=100;}kkkk();}delay_loop_1();//这里加一个延时是为了保证 key   按键按下去的时候能够识别的到if(KeyValue==0x0d) //1101  13->d{if(num>=110){num-=100;}kkkk();}delay_loop_1();//这里加一个延时是为了保证 key   按键按下去的时候能够识别的到if(KeyValue==0x0b)//1011  11->b{if(num<EPWM1_TIMER_TBPRD/2-10){num+=10;}kkkk();}delay_loop_1();//这里加一个延时是为了保证 key   按键按下去的时候能够识别的到if(KeyValue==0x07)//0111  7{if(num>=20){num=num-10;}kkkk();}}
}interrupt void xint1_isr(void)
{Uint32 i;for(i=0;i<1000000;i++);    //键盘消抖动while(keyon1==0);if(fangxiang==0){fangxiang=1;}else if(fangxiang==1){fangxiang=0;}bianhua();// 应答寄存器的位1清0,以响应同组内其他中断;PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}void delay_loop_2()
{Uint32      i;Uint32      j;for(i=0;i<40;i++){for (j = 0; j < 100000; j++);}}void delay_loop_1()//超短时间的延时
{Uint32      i;Uint32      j;for(i=0;i<20;i++){for (j = 0; j < 10000; j++);}
}void InitEPwm1Example()//PWM 控制电机的 初始化
{// Setup TBCLKEPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;           // Set timer period 801 TBCLKsEPwm1Regs.TBPHS.half.TBPHS = 0x0000;           // Phase is 0EPwm1Regs.TBCTR = 0x0000;                      // Clear counter// Set Compare valuesEPwm1Regs.CMPA.half.CMPA = EPWM1_MIN_CMPA;     // Set compare A valueEPwm1Regs.CMPB = EPWM1_MAX_CMPB;               // Set Compare B value// Setup counter modeEPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count upEPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loadingEPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUTEPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;// Setup shadowingEPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;  // Load on ZeroEPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// Set actionsEPwm1Regs.AQCTLA.bit.CAU = AQ_SET;             // Set PWM1A on event A, up countEPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;           // Clear PWM1A on event A, down countEPwm1Regs.AQCTLB.bit.CBU = AQ_SET;             // Set PWM1B on event B, up countEPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR;           // Clear PWM1B on event B, down count// Interrupt where we will change the Compare ValuesEPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;      // Select INT on Zero eventEPwm1Regs.ETSEL.bit.INTEN = 1;                 // Enable INTEPwm1Regs.ETPS.bit.INTPRD = ET_3RD;            // Generate INT on 3rd event// Information this example uses to keep track// of the direction the CMPA/CMPB values are// moving, the min and max allowed values and// a pointer to the correct ePWM registersepwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP;   // Start by increasing CMPA &epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN; // decreasing CMPBepwm1_info.EPwmTimerIntCount = 0;               // Zero the interrupt counterepwm1_info.EPwmRegHandle = &EPwm1Regs;          // Set the pointer to the ePWM moduleepwm1_info.EPwmMaxCMPA = EPWM1_MAX_CMPA;        // Setup min/max CMPA/CMPB valuesepwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;}

实验结果:


书上的知识,可以看看!!!

增量式编码器以转动时输出脉冲, 通过计数设备来知道其相对参考点的位置, 当编码器不动或停电时, 依靠计数设备的内部记忆来记住位置。 这样当停电后, 编码器不能有任何的移动, 当来电工作是, 编码器输出脉冲过程中, 也不能有干扰而丢失脉冲, 不然计数设备记忆的零点就会偏移, 而且这种偏移量是无法知道的, 只有错误的生产结果出现后才能知道。 解决的方法是增加参考点, 编码器每经过参考点, 将参考点位置修正进行计数设备的记忆位置。 在参考点以前,是不能保证位置的准确性。 因此, 在工控中就有每次操作前先找参考点, 即开机找零等方法。

F28335 有两路 eQEP 模块, 每个模块有 4 个管脚, 分别是: QEPA/XCLK、QEPB/XDIR、 eQEPI 和 QPES。 其中前两个引脚被使用在正交时钟模式或者直接计数模式。
(1) 正交时钟模式
正交编码器提供两路相位差为 90 度的脉冲, 相位关系决定了电机旋转方向信息, 脉冲的个数可以决定电机的绝对位置信息。 超前或者顺时钟旋转时, A 路信号超前 B 路信号, 滞后或者逆时针旋转时, B 路信号超前 A 路信号。 正交编码器使用这两路输入引脚可以产生正交时钟和方向信号。
(2) 直接计数模式
在直接计数模式中, 方向和时钟信号直接来自外部, 此时 QEPA 引脚提供时钟输入, QEPB 引脚提供方向输入。后两个引脚 eQEPI 是索引或者起始标记脚, 正交编码器使用索引信号来确定一个绝对的起始位置, 此引脚直接与正交编码器的索引输出端相连, 当此信号到来时, 可以将位置计数器复位清零, 也可以初始化或者锁存位置计数器的值。QEPS 是锁存输入引脚, 锁存引脚输入的主要作用是当规定时间信号到来时,初始或者锁存位置计数器的值, 该引脚通常和传感器或者限制开关连接, 用于通知电机是否达到预定位置。
eQEP 主要包含以下几个功能单元:
–通过 GPIO MUX 寄存器编程锁定 QEPA 或者 QEPB 功能。
–正交解码单元(QDU) 。
–位置计数器和位置计算控制单元(PCCU) 。
–正交边沿捕获单元, 用于低速测量(QCAP) 。
–用于速度/频率测量的时基单元(UTIME) 。
–用于检测的看门狗模块。

图片:


EQEP  模块  测速  头文件:


#ifndef EQEP_POS_SPEED_GET_H
#define EQEP_POS_SPEED_GET_H#include "IQmathLib.h"         // Include header for IQmath library//-----------------------------------------------------------------------------
//  Define the structure of the POSSPEED Object
//-----------------------------------------------------------------------------typedef struct {float ElecTheta;    //OutPut: Motor Electrical Anglefloat MechTheta;    //Output: Motor Mechanical Anglefloat MechTheta_Beyond;  //存储超过一圈后的位置信息的变量int DirectionQep; //output: Motor rotation directionint PolePairs;     //Parameter: 同步电机极对数int LineEncoder;   //Parameter: 码盘一周脉冲数(增量式)int Encoder_N;     //Parameter: 码盘一周脉冲数的4倍(根据倍频的倍数而定,这里用4倍频)int CalibrateAngle;//Parameter:电机A相绕组和码盘Index信号之间的夹角,与安装精度有关float Mech_Scaler;   //Parameter:1/Encoder_Nfloat RawTheta;      //Variable: 初始定位后,电机转子d轴和定子A相绕组之间所相差的码盘计数值int Index_sync_flag;//Output: Index sync statusfloat BaseRpm;        //Parameter:额定转速float Speed_Mr_Rpm_Scaler;//Parameter:60000/(Encoder_N * T),其中T为M法测速时的时间间隔,单位ms//60/512线/(4倍频*0.001s)float Speed_Mr_Rpm;   //Output: speed int r.p.mfloat Speed_Mr;       //Output: speed in per-uint              float Position_k_1;   //Input: Current position float Position_k;     //Input: Last positionfloat Speed_Tr_Rpm_Scaler;//Parameter: (UPPS * 150e6 * 60)/(Encoder_N * CCPS)//150e6*60/512float Speed_Tr_Rpm;   //Output: spedd int r.p.mfloat Speed_Tr;       //Output: speed int per-uintfloat t1;float t2;float t3;float Ts; // 采样时间float K2; //滤波系数  float Speed_Temp;float Speed;             // Output :  speed in per-unitUint32 K;int cnt_old; //eQEP位置计数器寄存器中上一个时刻的计数值int cycles; // 电机转过的圈数float position;void (*init)();        // Pointer to the init funcion          void (*calc)();} EQEP_POS_SPEED_GET;//-----------------------------------------------------------------------------
// Define a POSSPEED_handle
//-----------------------------------------------------------------------------
typedef EQEP_POS_SPEED_GET  *EQEP_POS_SPEED_GET_handle;//-----------------------------------------------------------------------------
// Default initializer for the POSSPEED Object.
//-----------------------------------------------------------------------------
#if (CPU_FRQ_150MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\9.76,0,0,0,0,\17578125,0,0,\0,0,0,0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}//注意9.76是0.003s为周期//#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,0,\
//                                     2,500,2000,0,1.0/2000,0,0,\
//                                     6000.0,\
//                                     29.29,0,0,0,0,\
//                                     17578125,0,0,\
//                                     0,0,0,0,0,0,0,0,0,0,0,\
//                                     (void (*)(long))eQEP_pos_speed_get_Init,\
//                                     (void (*)(long))eQEP_pos_speed_get_Calc}#endif#if (CPU_FRQ_100MHZ)
#define EQEP_POS_SPEED_GET_DEFAULTS {0,0,0,\2,500,2000,0,1.0/2000,0,0,\6000.0,\3.0,0,0,0,0,\1125000,0,0,\0,0,0,0,0,0,0,0,\(void (*)(long))eQEP_pos_speed_get_Init,\(void (*)(long))eQEP_pos_speed_get_Calc}
#endif//-----------------------------------------------------------------------------
//  Prototypes for the functions in posspeed.c
//-----------------------------------------------------------------------------
void eQEP_pos_speed_get_Init(EQEP_POS_SPEED_GET_handle);
void eQEP_pos_speed_get_Calc(EQEP_POS_SPEED_GET_handle);#endif
//==============================================================
//End of file.
//==============================================================

EQEP  模块  测速    主文件:

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File #include "Example_posspeed.h" #include "Example_posspeed.h"
#include <math.h>//======== Definations for functions ===========================void eQEP_pos_speed_get_Init(EQEP_POS_SPEED_GET *p)
{#if (CPU_FRQ_150MHZ)
//  EQep1Regs.QUPRD=1500000;           // Unit Timer for 100Hz at 150 MHz SYSCLKOUT
//案例给的程序错误的地方 这个是单位事件使能 也就是说M法EQep1Regs.QUPRD=150000*3;            // Unit Timer for 100Hz at 150 MHz SYSCLKOUT
#endif
#if (CPU_FRQ_100MHZ)EQep1Regs.QUPRD=1000000;           // Unit Timer for 100Hz at 100 MHz SYSCLKOUT
#endifp->Encoder_N=4*p->LineEncoder;p->Mech_Scaler=1.0/p->Encoder_N;EQep1Regs.QDECCTL.bit.QSRC=0x00;     // QEP quadrature count modeEQep1Regs.QEPCTL.bit.FREE_SOFT=2;EQep1Regs.QEPCTL.bit.PCRM=0x01;          // PCRM=00 mode - QPOSCNT reset on index eventEQep1Regs.QEPCTL.bit.UTE=1;         // Unit Timeout Enable EQep1Regs.QEPCTL.bit.QCLM=1;        // Latch on unit time outEQep1Regs.QPOSMAX=p->Encoder_N;     // Encoder_NEQep1Regs.QEPCTL.bit.QPEN=1;      // QEP enableEQep1Regs.QCAPCTL.bit.UPPS=1;     // 1/2 for unit positionEQep1Regs.QCAPCTL.bit.CCPS=3;      // 1/8 for CAP clockEQep1Regs.QCAPCTL.bit.CEN=1;       // QEP Capture Enable
//  EQep1Regs.QPOSMAX=0xffffffff;p->cycles=0;p->Speed_Tr_Rpm_Scaler=60.0*150*1000000/4/p->Encoder_N;p->Speed_Tr_Rpm=0;//EQep1Regs.QEPCTL.bit.SWI=1;// software generate index pulse}//**********************************void eQEP_pos_speed_get_Calc(EQEP_POS_SPEED_GET *p)
{int cnt_inc , cnt_cur;float tmp1;unsigned int t2_t1;unsigned long M1,M2,fclk;//Check the rotational directionp->DirectionQep = EQep1Regs.QEPSTS.bit.QDF;cnt_cur = EQep1Regs.QPOSCNT;//Check the position counter for EQep1p->RawTheta = cnt_cur + p->CalibrateAngle;if(p->RawTheta < 0){p->RawTheta = p->RawTheta + EQep1Regs.QPOSMAX;}else if(p->RawTheta > EQep1Regs.QPOSMAX){p->RawTheta = p->RawTheta - EQep1Regs.QPOSMAX;}//Compute the mechanical anglep->MechTheta = p->Mech_Scaler * p->RawTheta;/*****************超过一圈后的角度计算*************/// Check the counter for QEP cnt_inc = cnt_cur - p->cnt_old;if (abs(cnt_inc) > 200)    //6000 RPM, 1ms能读到的最大差值就是200,  除非转角超过1圈.{if (cnt_inc < 0)p->cycles +=1;elsep->cycles -=1;}  p->cnt_old = cnt_cur;//Compute the mechanical angletmp1=p->MechTheta_Beyond;   // old positionp->MechTheta_Beyond = p->MechTheta+p->cycles;p->Speed = 60*(p->MechTheta_Beyond-tmp1)/p->Ts;   // speed in RPM values// Check an index occurrenceif (EQep1Regs.QFLG.bit.IEL == 1){p->Index_sync_flag = 0x00F0;EQep1Regs.QCLR.bit.IEL=1;                   // Clear interrupt flag}//// High Speed Calculation using QEP Position counter// Check unit Time out-event for speed calculation:// Unit Timer is configured for 100Hz in INIT function//if(EQep1Regs.QFLG.bit.UTO==1)// If unit timeout (one 100Hz period){p->Position_k =1.0 * EQep1Regs.QPOSLAT;if(p->DirectionQep==0) // POSCNT is counting down{if(p->Position_k > p->Position_k_1){ tmp1 = -(p->Encoder_N - (p->Position_k - p->Position_k_1)); }else{ tmp1 = p->Position_k - p->Position_k_1;}// x2-x1 should be negative}else if(p->DirectionQep==1)    // POSCNT is counting up{if(p->Position_k < p->Position_k_1){ tmp1 = p->Encoder_N - (p->Position_k_1 - p->Position_k); }else{ tmp1 = p->Position_k - p->Position_k_1;}// x2-x1 should be positive}if(tmp1 > p->Encoder_N){ p->Speed_Mr_Rpm = p->BaseRpm;  }else if(tmp1 < -p->Encoder_N){ p->Speed_Mr_Rpm = -p->BaseRpm; }else{ p->Speed_Mr_Rpm = tmp1 * p->Speed_Mr_Rpm_Scaler; }p->Speed_Mr = p->Speed_Mr_Rpm / p->BaseRpm;p->Position_k_1 = p->Position_k;EQep1Regs.QCLR.bit.UTO=1; // Clear interrupt flag}#ifndef  Larrange_qep
//    // Low-speed computation using QEP capture counter // T法if(EQep1Regs.QEPSTS.bit.UPEVNT==1)                          // Unit position event{if(EQep1Regs.QEPSTS.bit.COEF==0)                        // No Capture overflowt2_t1 =  EQep1Regs.QCPRD;else                                                    // Capture overflow, saturate the resultt2_t1 = 0xFFFF;//// Convert p->Speed_pr to RPM//if(p->DirectionQep==0)p->Speed_Tr_Rpm = - p->Speed_Tr_Rpm_Scaler / t2_t1; //negativeelsep->Speed_Tr_Rpm =  p->Speed_Tr_Rpm_Scaler / t2_t1;//         if(p->Speed_Tr_Rpm > p->BaseRpm)//           p->Speed_Tr_Rpm = p->BaseRpm;//        else if(p->Speed_Tr_Rpm < -p->BaseRpm)//         p->Speed_Tr_Rpm = -p->BaseRpm;//EQep1Regs.QEPSTS.all=0x88;          // Clear Unit position event flag// Clear overflow error flag}#else//Lagrangeif(EQep1Regs.QEPSTS.bit.UPEVNT==1){p->t1=p->t2;p->t2=(unsigned int)EQep1Regs.QCPRD;EQep1Regs.QEPSTS.bit.UPEVNT=1;}p->t3=EQep1Regs.QCTMR;p->Speed_Tr_Rpm=(p->Speed_Tr_Rpm_Scaler)*((2*p->t3+2*p->t2+p->t1)*2/(p->t1+p->t2)/p->t2-(2*p->t3+p->t2+p->t1)/p->t2/p->t1);if(p->DirectionQep==0)p->Speed_Tr_Rpm=-p->Speed_Tr_Rpm;
#endif}//==============================================================
//End of file.
//==============================================================


遇到的问题 :

.text    的     内存小了, 报错

改内存:


注意 模块  L298N  那么多的资料,我查了  一天才知道    ,   靠,实践才是道理

我来画图了   (L298N  驱动模块    驱动    AB 直流编码器电机)


A通道输入  或者B通道输入  直接使用  PWM 信号一样的   接在IN1  和 IN2  或者 IN3  和 IN4  上面。


推荐去看的链接:

https://www.cnblogs.com/Congratulation-hyl/p/15185333.html
L298N  开发板 功能图

https://blog.csdn.net/m0_73734297/article/details/126864324
基于MATLAB的simulink 基于dsp28335的直流电机的驱动模型(

https://blog.csdn.net/weixin_46556696/article/details/116380524
DSP28335基础教程——EQEP实验(直流电机转速检测)

https://blog.csdn.net/weixin_43475628/article/details/115920212
DSP28335实现PID闭环 +  模型

https://blog.csdn.net/qq_51963216/article/details/122804439
直流电机与PID——编码器电机使用(一)

https://blog.csdn.net/qq_30759585/article/details/121607868
DSP28335的EQEP模块的使用与电机测速

DSP CCS12.00 芯片:TMS320F28335 结课设计 : 电机模块 + 按键模块 + EQEP 模块 设计 + TFTLCD 的设计 第一次尝试相关推荐

  1. DSP CCS12.00 芯片:TMS320F28335 PWM 的设计

    先学习怎么 发出 PWM 的波形  (知识点看后面) 1.PWM输出配置步骤 EPWM相关文件 在DSP2833x_EPwm.c和DSP2833x_EPwm.h文件中. ​ EALLOW;SysCtr ...

  2. DSP CCS12.00 芯片:TMS320F28335 ADC 的运用

    1.AD 转换的四个步骤 实现ad转换需要经过取样.保持.量化.编码四个步骤. 2.AD 的含义 AD 转换 就是把模拟信号转换成数字信号.主要包括积分型.逐次逼近型.并行比较型/串并行型.Σ-Δ调制 ...

  3. DSP CCS12.00 芯片:TMS320F28335 结课设计 综合设计 TFTLCD + 按键 + 蜂鸣器 + 流水灯

    (永辉电子DSP 板子) 代码功能 : 1.外部中断 控制 流水灯的方向 2. key 1 开启 蜂鸣器 3.key 2 关闭 蜂鸣器 4.key 3 开启 LED灯  (可能按键不对  但是就是这几 ...

  4. DSP CCS12.00 芯片:TMS320F28335 结课设计 数字电压表 TFTLCD 模块 + ADC 模块

    (永辉电子DSP 的板子  ) 扭动滑动变阻器 改变电压 代码: #include "DSP2833x_Device.h" // DSP2833x Headerfile Inclu ...

  5. DSP CCS12.00 芯片:TMS320F28335 结课设计 频率测量系统设计

    (这篇文章我不负责 !!! , 我没搞懂) 永辉电子 DSP 板子 1.功能: PWM3B   PWM3A 输出 : ECAP 模块测量  : 线的连接 第一种方法 ECAP 1A 模块  J7  4 ...

  6. DSP CCS12.00 芯片:TMS320F28335 TFTLCD显示屏幕的应用

    1.我用的那个DSP 工具箱 是 永辉电子公司, 2.知识点 (无) 别人写好的代码,直接用!!! 3.具体操作 1.首先建立工程: 2.这次代码主要,需要添加一个 cmd 文件 关于寄存器的cmd文 ...

  7. DSP CCS12.00 芯片:TMS320F28335 直流电机部分 + TFTLCD 显示部分 + 按键模块

    1. 首先我的 PWM 模块直接连接 了  直流电机  所以 我的 直流电机 利用 PWM  模块控制 . 直流电机  转速=(电枢端电压-两个电刷上的电压降-电枢绕组电阻上的压降)/(电机常数乘以电 ...

  8. 《web结课作业的源码》中华传统文化题材网页设计主题——基于HTML+CSS+JavaScript精美自适应绿色茶叶公司(12页)

  9. 《web结课作业的源码》中华传统文化题材网页设计主题——基于HTML+CSS+JavaScript精美自适应绿色茶叶公司(12页)...

    ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主

最新文章

  1. python全栈 互联网协议
  2. HBase总结(十三)HBase Shell 常用命令及例子
  3. DS博客作业08--课程总结
  4. 汇编 div_Solidity汇编开发简明教程
  5. homebrew install php53
  6. Linux 内核态与用户态通信 netlink
  7. 通俗理解滑模变结构(2)
  8. 【shell】Shell编程的前篇以及通过编程实现,jdk的安装
  9. BSTR与CString之前的转换
  10. springmvc07 Json处理
  11. java 中文乱码的解决方法
  12. GB35114 A级过检
  13. 你的功夫真的夠了嗎?
  14. 证件照处理:一寸照片换底色
  15. 计算机网络实验:IP协议层分析
  16. 360无线wifi电脑怎样连接到服务器,360随身Wifi能连接上但是电脑无法上网怎么办...
  17. 利用N2N内网穿透,并实现直连
  18. KEPServerEX 6 之 高级标签插件 Advanced Tags 中文使用(完整版)
  19. 华为鸿蒙os操作系统有pc版,华为开源操作系统 鸿蒙OS 升级版曝光,打通PC等一大批硬件...
  20. 印象笔记的使用技巧总结

热门文章

  1. Python学习(十四)——常用模块1
  2. su命令无权限,如何解决
  3. 一篇入门级Scrapy框架(校花网)
  4. 航空发动机-网格技术篇1之叶栅流域正交画法
  5. 照片还是照骗?人工智能正在改变人类世界观
  6. Apache Kylin 的预计算是怎么回事?
  7. mysql数据库视图_MySQL数据库应用总结(九)—MySQL数据库视图的操作
  8. 塑胶模具基本知识以及技术应用
  9. Python非全日制培训
  10. 服务器内部转发以及客户端重定向