📄 pwm完整程序.txt
字号:
#include "LF2407REGS.h"
#include "pid.c"
#define PWMT 1000 //PWM周期,50us,50/(1/(4*10)*2)
#define NMAX 3000 //电机最高转速,r/min
#define SPER 100 //100个PWM周期速度调节一次
#define I_K 1000 //
#define N_K 1000
// 屏蔽中断程序
void inline disable()
{
asm(" setc INTM");
}
// 开总中断程序
void inline enable()
{
asm(" clrc INTM");
}
// 初始化子程序
void initial()
{
asm(" setc SXM"); // 符号位扩展有效
asm(" clrc OVM"); // 累加器中结果正常溢出
asm(" clrc CNF"); // B0被配置为数据存储空间
SCSR1=0x81FE; // CLKIN=10M,CLKOUT=4*CLKIN=40M
WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WD?の桓次缓蟮娜笔≈滴?,故可以用
// 软件禁止看门狗
IMR=0x0000; // 禁止所有中断
IFR=0x0FFFF; // 清除全部中断标志,"写1清0"
WSGR=0X00; // 禁止所有的等待状态
}
void interrupt timer3(void)
{
int abc=0;
}
// 该中断服务程序主要是为了防止干扰,不做任何其它操作
void interrupt nothing(void)
{
// return; // 中断直接返回
}
// 主程序
PID i_pid = {0,0.5,0.5,0,0,0,0,0,0,0},
n_pid = {1000,1,2,3,0,0,0,20,40,200,400};
unsigned int temp,i_in,i_out,n_out,n_in,n_ref, //p,i,d参数用Q12;kspeed用Q22
encincr,encoderold,speedtmp,speedstep,kspeed,direction;
void main(void) //不传入不返回
{
disable(); // 总中断禁止
initial(); // 系统初始化
T2PER = 0XFFFF; //最大周期
T2CNT = 0X0000;
T2CON = 0X9870; //定向增减,允许编码接口
T1PER = PWMT; //PWM设置,周期50微秒,2*500*(1/20)us
T1CNT = 0X0000;
ACTRA = 0X0096; //PWM1,4高有效,2,3低有效
DBTCONA = 0X01F4; //死区1.6微秒,死区定时周期1个(X/32),0.05*32=1.56us
CMPR1 = PWMT*0.2; //占空比0.5,500*0.5,(还可以增加实现6个pwm)
CMPR2 = PWMT*0.6;
COMCONA = 0X8200; //允许比较,T1下溢重载
T1CON = 0X0840; //连续增减计数,内部时钟,不分频
GPTCONA = 0X0100; //T1周期中断标志启动AD转换
MCRA = 0X03D8; //引脚设置为PWM1-4,QEP1-2
IMR = 0X0020; //允许INT6中断
IFR = 0Xffff; //清标志
EVAIFRA = 0X0000;
EVAIFRB = 0X0000;
EVAIFRC = 0X0000;
EVAIMRA = 0X0000;
EVAIMRB = 0X0000;
EVAIMRC = 0X0000;
//AD设置
ADCTRL2 = 0X0500; //允许EVA启动AD转换
ADCTRL1 = 0X0900; //10分频
MAXCONV = 0X0000; //一次最多一个转换通道
CHSELSEQ1 = 0x0000; //ADCIN00通道
MCRA=MCRA&0Xdfff; //IOPB5,对SN74LVC4245输出使能
PBDATDIR=PBDATDIR|0X2000;
PBDATDIR=PBDATDIR&0Xffdf;
EVBIMRA = 0X80;
EVBIFRA = 0X0FFFF;
GPTCONB = 0X0;
T3PER = 0X0EA6;
T3CNT = 0X0;
T3CON = 0X084C;
IMR = 0XFF;
IFR = 0X0FFF;
// enable();
asm(" CLRC INTM"); /// Enable all interrupt
while(1)
{
;
}
}
void interrupt adcint(void)
{
EVAIFRA = EVAIFRA; //清T1周期中断标志
ADCTRL2 = ADCTRL2 | 0x0202;
//电流PI调节
i_in = (RESULT0)>>6; //
if (direction)
{
i_pid.Pmax = PWMT/2;
i_pid.Pmin = 0;
temp = PWMT/2;
}
else
{
i_pid.Pmax = PWMT;
i_pid.Pmin = PWMT/2;
temp = PWMT;
}
i_out = PIDCalc ( &i_pid,i_in );
CMPR2 = ((i_out*I_K)>>12)+temp; //更新占空比
CMPR1 = ((i_out*I_K)>>12)+temp; //
//读编码器脉冲数,计算转角增量和转速
temp = T2CNT;
encincr = temp-encoderold; //编码增量
speedtmp+=encincr; //编码脉冲累计
encoderold = temp;
if (--speedstep)
{
return;
}
else //计算转速
{
n_in = speedtmp*kspeed; //kspeed,100*50us内发出的最大脉冲数,1/(3000/60*4*1024*5*10^(-3)),1024线编码器
n_in = NMAX*n_in; //转速反馈量
speedtmp = 0;
speedstep = SPER;
}
//速度PI调节
n_pid.SetPoint = n_ref;
n_pid.Pmax = i_pid.Pmax;
n_pid.Pmin = i_pid.Pmin;
n_out = PIDCalc ( &n_pid,(n_in>>22) );
temp = n_pid.Pmax;
i_pid.SetPoint = ((n_out*N_K)>>12)+temp;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -