📄 pwm.c
字号:
#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 S_K 2341 //Q12
#define N_K 10
unsigned long int i=0;
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 nothing()
{
return; // 中断直接返回
}
// 给定 ,P ,I D,
PID n_pid = {0,20000,0,0,0,0,0,200,3500,1638400,-1638400},
p_pid = {4020,400,0,0,0,0,0,0,2500,14336000,-14336000};
int encincr,encoderold=0,speedtmp=0,direction=1;
int temp = 0;
int speedstep=10;
int n_in=0;
long int n_out = 0;
int change=0;
long int sum_plus = 0;
long int s_in = 0;
long int s_out = 0;
int flag2 = 10;
int positionstep = 10;
long int p_out = 0;
void main(void)
{
disable(); // 总中断禁止
initial(); // 系统初始化
T2PER = 0XFFFF; //最大周期
T2CNT = 0X0000;
T2CON = 0X9870; //定向增减,允许编码接口
T1PER = PWMT; //PWM设置,周期50微秒,2*500*(1/20)us
T1CNT = 0X0000;
ACTRA = 0x0099;//0X0096;//01101001 //PWM1,4高有效,2,3低有效
DBTCONA = 0X01F4; //死区1.6微秒,死区定时周期1个(X/32),0.05*32=1.56us
CMPR1 = PWMT*0.9; //占空比0.5,500*0.5,(还可以增加实现6个pwm)
CMPR2 = PWMT*0.5;
COMCONA = 0X8200; //允许比较,T1下溢重载
T1CON = 0X0840; //连续增减计数,内部时钟,不分频
MCRA = 0X03D8; //引脚设置为PWM1-4,QEP1-2
IMR = 0X0002; //允许INT6中断
IFR = 0X0000; //清标志
EVAIFRA = 0Xffff; //应写1清除
EVAIFRB = 0X0000;
EVAIFRC = 0X0000;
EVAIMRA = 0X0000;
EVAIMRB = 0X0000;
EVAIMRC = 0X0000;
EVAIMRA=EVAIMRA|0X0080; // 允许定时器1的周期中断
EVAIFRA=EVAIFRA&0X0080; // 清除定时器1周期中断标志
MCRA=MCRA&0Xdfff; //IOPB5,对SN74LVC4245输出使能
PBDATDIR=PBDATDIR|0X2000;
PBDATDIR=PBDATDIR&0Xffdf;
enable();
while(1)
{
;
}
}
void interrupt timer(void)
{
EVAIFRA = EVAIFRA;
if (--speedstep)
{
return;
}
else{
temp = T2CNT;
T2CNT = 0;
speedtmp += temp; //编码脉冲累计
speedstep = SPER;
}
n_in = temp;
n_out = PIDCalc ( &n_pid,n_in);
n_out = n_out>>12;
change = n_out;
change = change + 500;
if(change>960)
change = 960;
else if(change<=0)
change = 0;
CMPR2 = change; //更新占空比
CMPR1 = change;
//位置控制
if (--positionstep) return;
positionstep = 10;
p_out = PIDCalc ( &p_pid,speedtmp);
p_out = p_out>>12;
change = p_out;
if(change>400)
change = 400;
else if(change<-400)
change = -400;
n_pid.SetPoint = change;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -