📄 can.c
字号:
CANMBX2A=0x0000; /*邮箱2信息初始化*/
CANMBX2B=0x0000;
CANMBX2C=0x0000;
CANMBX2D=0x0000;
CANMCR=0x0103;
CANMSGID3H=0x6000; /*设置邮箱3的控制字及ID,IDE=0标准标示符,AME=0禁止屏蔽,标准方式为MSGID2H[12-2]*/
CANMSGID3L=0x0000;
CANMSGCTRL3=0x08; /*数据长度DCL=8,RTR=0数据帧*/
CANMBX3A=0x0201; /*邮箱3信息初始化*/
CANMBX3B=0x0403;
CANMBX3C=0x0605;
CANMBX3D=0x0807;
CANMCR=0x0480;/*DBO=1,ABO=1,STM=0*/
CANMDER=0x4C; /*使能邮箱2,3,邮箱2配置成接收,3发送*/
CANIMR=0xF7FF; /*中断MBX3不使能,*/
CANIFR=0xFFFF; /*清全部中断标志*/
}
void SYSINIT(void)
{
asm(" SETC INTM "); /*关总中断*/
asm(" CLRC SXM "); /*抑制符号扩展*/
asm(" CLRC OVM "); /*累加器中结果正常溢出*/
asm(" CLRC CNF "); /*B0区被配置为数据空间*/
SCSR1=0x83FE; /*时钟2倍频,CLKIN=15M,CLKOUT=30M*/
WDCR=0x00E8; /*不使能WDT*/
IMR=0x0000; /*屏蔽所有CPU中断*/
IFR=0xFFFF; /*清全部中断标志*/
MCRA=0xC5FB; /*p116配置IOPA2-SONAR,IOPB1-PWM4,IOPB3-PWM6,IOPB4-DIR1,IOPB5-DIR2*/
MCRB=0xFEC3; /*配置IOPC2,3-码盘,IOPC4,5-灯,IOPD0*/
MCRC=0xF383; /*配置IOPE2-PWM8,IOPE3-6:BRAKE1-4,IOPF2-DIR3,IOPF3-DIR4*/
/*MCRA=0xCFFF;配置IOPB4,IOPB5,XINT1*/
/*MCRB=0xFE03;配置IOPC2-IOPC7,IOPD0*/
/*MCRC=0xF387;配置IOPF2,IOPF3,IOPE3-6*/
PBDATDIR=0xFF00; /*设置IOPB输出低电平*/
PCDATDIR=0x3000; /*设置IOPC4,5输出低,其余输入*/
PDDATDIR=0xFFFF; /*设置IOPD0输出为高电平*/
PEDATDIR=0xFFFF; /*设置IOPE输出高电平*/
PFDATDIR=0xFF00; /*设置IOPF输出为低电平*/
/*PBDATDIR=0xFF00;设置IOPB4,5输出低电平*/
/*PCDATDIR=0x0000;设置IOPC2-7输入*/
/*PDDATDIR=0xFFFF;设置IOPD0输出为高电平*/
/*PEDATDIR=0x0000;设置IOPE3-6输入*/
/*PFDATDIR=0xFF00;设置IOPF2,3输出为低电平*/
ACTRA=0x0666; /*PWM6,4,2低有效,PWM5,3,1高有效*/
ACTRB=0x0666; /*PWM8低有效,PWM7高有效*/
DBTCONA=0x02E7; /*使能死区定时器3,2,1,死区周期为3,9分频*/
DBTCONB=0x02E7; /*使能死区定时器6,5,4,死区周期为3,9分频*/
CMPR1=48;
CMPR2=48;
CMPR3=48;
CMPR4=48;
T1PR=TxPR;
T3PR=TxPR;
/*T1PR=95;
T3PR=95; */
T2PR=0xFFFF;
T4PR=0xFFFF;
T1CNT=0;
T2CNT=1000;
T3CNT=0;
T4CNT=1000;
GPTCONA=0x0006;
GPTCONB=0x0006; /*禁止定时器比较输出,T4低有效,T3高有效*/
EVAIMRA=0x0000; /*禁止定时器1的中断,禁止比较单元1-3的中断,禁止功率驱动保护中断*/
EVAIMRB=0x0000; /*禁止定时器2的中断*/
EVAIMRC=0x0004; /*使能CAP3中断,禁止CAP1,CAP2中断*/
EVBIMRA=0x0080; /*使能定时器3的周期中断,禁止比较单元4-6的中断,禁止功率驱动保护中断*/
EVBIMRB=0x0000; /*禁止定时器4的中断*/
EVBIMRC=0x0004; /*使能CAP6中断,禁止CAP4,CAP5中断*/
EVAIFRA=0xFFFF;
EVAIFRB=0xFFFF;
EVAIFRC=0xFFFF;
EVBIFRA=0xFFFF;
EVBIFRB=0xFFFF;
EVBIFRC=0xFFFF;
COMCONA=0xA600; /*使能比较操作,使能比较输出,下溢或周期匹配时重装载比较和方式控制寄存器*/
COMCONB=0xA600; /*禁止比较操作,禁止比较输出,下溢或周期匹配时重装载比较和方式控制寄存器*/
T1CON=0x1442; /*连续增计数模式,预分频为16,定时器计数使能,使用内部时钟*/
T3CON=0x1442;
T2CON=0x1872; /*定向增减计数模式,使能定时器操作,使用正交编码脉冲电路作为时钟输入*/
T4CON=0x1872;
CAPCONA=0x7404; /*使能QEP1,2,CAP3(T1,检测上升沿)*/
CAPCONB=0x7404; /*使能QEP3,4,CAP6(T3,检测上升沿),禁止CAP6*/
/*PBDATDIR=0xFF00;设置IOPB4,5输出高电平*/
/*PFDATDIR=0xFF04;设置IOPF2输出高电平,IOPF3输出低电平IOPF6输出低电平*/
/*PDDATDIR=0xFFFF;设置IOPD0输出为高电平*/
/********以下是串口初始化***********/
SCICCR=0x0007; /*空闲线多处理器模式,8位数据,1位停止位,无奇偶校验*/
SCICTL1=0x0013; /*接收使能,SLEEP=0,SW RESET=0*/
SCICTL2=0x0002; /*接收中断使能*/
/*SCIHBAUD=0x0001;
SCILBAUD=0x0086; 波特率为9600,systemclk=30M*/
SCIHBAUD=0x0001;
SCILBAUD=0x0038; /*波特率为9600systemclk=24M*/
SCICTL1=0x0033; /*串口初始化完成,SW RESET=1*/
SCIPRI=0x0060; /*一旦仿真挂起,在完成当前的接收/发送操作后停止*/
/**********************************/
IMR=0x001a; /*开CPU中断INT2,开INT4,开int5*/
/*IMR=0x000A;开CPU中断INT2,开INT4*/
asm(" CLRC INTM "); /*开总中断*/
}
void UpdatePosition(PID*pid) /*获取码盘数值*/
{
pid->count=T2CNT;
if((EVAIFRB&0x0001)==1)
{
EVAIFRB=0x0001;
(pid->overflow)++;
}
pid->mposition=(pid->count+65536*(pid->overflow)-1000);
}
void UpdateTrajectory(PID*pid)
{
if(pid->saturated==0)
{
if(pid->phase==1)
{
if(pid->v<pid->vlimit)
{pid->v+=accel;}
else
{(pid->even_cnt)++;}
pid->pdist-=pid->v;
pid->position+=pid->v;
if(pid->pdist<0)
{pid->phase=0;}
}
else
{
if(pid->even_cnt>0)
{(pid->even_cnt)--;}
else if(pid->v>0)
{pid->v-=accel;}
else
{pid->move=0;
PBDATDIR=0xFF00;
}
pid->position+=pid->v;
}
}
}
void calcPID(PID*pid,int k)
{
/*asm(" SETC SXM ");*/
unsigned int Kp=pid->Kp;
unsigned int Ki=pid->Ki;
unsigned int Kd=pid->Kd;
UpdatePosition(&control[k]);
UpdateTrajectory(&control[k]);
n++;
if((n%30)==0)
{ n=30;
if(t<150)
{
fb[t]=pid->mposition;
t++;
}
}
pid->e0=(pid->mposition-pid->position);
/*pid->PID_OUT=Kp*(pid->e0);
if(pid->saturated==0)
{
pid->e_sum+=pid->e0;
}
pid->PID_OUT+=(Ki*(pid->e_sum));*/
pid->de=(pid->e0-pid->e1);
/*pid->PID_OUT+=(Kd*(pid->de));
pid->PID_OUT=(pid->PID_OUT)/10;*/
j=(pid->e0)/6;
if(j>7)
{
j=7;
}
else if(j<-7)
{
j=-7;
}
m=fabs(j);
pid->PID_OUT=a[m]*(pid->e0)+(100-a[m])*(pid->de);
if(pid->PID_OUT>3375)
{
pid->PID_OUT=3375;
}
else if(pid->PID_OUT<-3375)
{
pid->PID_OUT=-3375;
}
pid->DUTYCYCLE=(pid->PID_OUT)/2/(pid->PID_MAX)+50;
pid->e1=pid->e0;
pid->saturated=0;
if(pid->DUTYCYCLE<6)
{
pid->DUTYCYCLE=6;
pid->saturated=1;
}
else if(pid->DUTYCYCLE>94)
{
pid->DUTYCYCLE=94;
pid->saturated=1;
}
CMPR1=(pid->DUTYCYCLE)*PERIOD/100;
/*CMPR2=(pid->DUTYCYCLE)*PERIOD/100;*/
}
void main(void)
{
int h=1;
varinit();
initPID();
SYSINIT();
caninit();
Tdata((char*)c_prompt);
if(h==0)
{
CANTCR=0x20;/*TRS3=1邮箱3请求发送*/
while(CANTCR&0x2000==0) continue; /*等待发送应答TA3=1则发送成功 */
CANTCR=0x2000; /*清TA3\MIF3标志位*/
while(CAN_FLAG==0) continue;
CAN_FLAG=0;
CANMDER=0x0000;
CANMCR=0x0100; /*cDr=1改变数据请求*/
cantemp=CANMBX2A;
Tfdata((float)cantemp,0);
cantemp=CANMBX2B;
Tfdata((float)cantemp,0);
cantemp=CANMBX2C;
Tfdata((float)cantemp,0);
cantemp=CANMBX2D;
Tfdata((float)cantemp,0);
CANMBX3A=CANMBX2A+1;
CANMBX3B=CANMBX2B+1;
CANMBX3C=CANMBX2C+1;
CANMBX3D=CANMBX2D+1;
CANMCR=0x0480;/*DBO=1,ABO=1,STM=1*/
CANMDER=0x04C; /*使能邮箱2,3,邮箱2配置成接收,3发送*/
}
while(1)
{
if(SAMPLE==1) /*采样周期1ms到*/
{
ledcount++;
if(ledcount>1000)
{PCDATDIR=0x3000;}
else
{ PCDATDIR=0x30FF;}
if(ledcount==2000) ledcount=0; /*灯闪烁*/
FLAG=0;
SAMPLE=0;
if(i==0)
{
calcPID(&control[i],i);
}
}
if(uartflag)
{
uartflag=0;
uartchuli(data_rx);
}
if(CAN_FLAG==1)
{
CAN_FLAG=0;
cantemp=CANMBX2A;
Tfdata((float)cantemp,1);
cantemp=CANMBX2B;
Tfdata((float)cantemp,1);
cantemp=CANMBX2C;
Tfdata((float)cantemp,1);
cantemp=CANMBX2D;
Tfdata((float)cantemp,1);
CANMCR=0x0480;/*DBO=1,ABO=1,STM=1*/
CANMDER=0x04C; /*使能邮箱2,3,邮箱2配置成接收,3发送*/
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -