下边是我的完整程序
试验的问题有如下:
三段的速度比较明显的显现出来
当运行遇到阻力的时候就出现闷机的现象,没有增加电压(电压保持闷机前的状态);
我用PID程序和我现在的类似PID程序都出现一样的问题
请大侠门指导一下,谢谢,下边是程序
#include <pic.h>
__CONFIG(HS&WDTEN&PWRTEN&CP&CPD&BORDIS&IESODIS&FCMDIS);//外部高速晶振、看门狗使能、上电延时打开、代码与数据保护、低电压检测禁止、内外时钟切换禁止、故障保护时钟禁止
//脉冲数110
#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long
#define Kdoor RA2 //
#define Gdoor RA3 //
#define suobi RA4 //
#define jinji RA5 //
#define geli RE0 //
#define fuwu RE1 //
#define dw RE2 //
#define Adr1 RC0 //
#define Adr2 RC1 //
#define Adr3 RC2 //
#define zj1 RC3 //
#define zj2 RC4 //
#define ENA RD7 //A使能信号
#define ENB RD6 //B使能信号
#define INA RD5 //正转控制信号
#define INB RD4 //反转控制信号
//#define Speed RD2 //PWM速度信号
#define relay1 RB2 //
#define relay2 RB1 //
#define relay3 RC4 //
#define relay4 RD3 //
#define relay5 RD1 //
#define speed1 20 //
#define speed2 40 //
#define speed3 20 //
uint loop1in[2];
bank3 uint microS; //Timer0定时时,用作4096us的时基变量。
bit S20;
bank3 uchar mS50; //
bank3 uchar mS_50; //
bank3 uchar SS;
bank3 uchar gggg,qqqq; //1秒标志。。
bank3 uchar pppp; //0.5秒标志。。,产生1HZ频率用
int aaaa,bbbb;
int jspeed;
ulint COUNT;
bit FLAG1,FLAG2,FLAG3,FLAG4,FLAG5,FLAG6,FLAG7;
bank2 uchar pwm2_h;//PID输出的占空比
void delay(uint time) //1就是1ms,误差是偏大1.5us。但2000(即2秒时)偏小18ms
{
uint i;
uchar j;
for(i=0;i<time;i++)
{asm("clrwdt");
for(j=0;j<179;j++);
}
}
void Noop()
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void ccpint()
{
CCP1CON=0X04; //首先设置CCP1捕捉每个脉冲的上升沿
T1CON=0X00; //关闭TMR1震荡器
//PEIE=1; //外围中断允许(此时总中断关闭)
CCP1IE=1; //允许CCP1中断
TRISC5=1; //设置RC5为输入
}
void sspeed() //速度计算函数
{
int tttt;
tttt=aaaa;
if( pppp==2) //0.2秒的定时时间
{
pppp=0;
jspeed=5*(aaaa-tttt); // 0.2秒的定时时间,aaaa是即时脉冲数,tttt是0.2秒钱的脉冲数(不知这样写对不对),扩大1000倍的 个/毫秒
}
}
void guanji() //关电机
{
ENA=0;
ENB=0;
}
void kmpwm() //满行程是65个脉冲
{
int xx;
sspeed(); //计算实时速度
if((0<=aaaa)&&(aaaa<10)) //前半段
{
xx=40;
if(jspeed=speed1) //比较
{
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
else if(jspeed<speed1) //比较
{
xx+=5;
if(xx>200)
xx=200;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
else //比较
{
xx-=5;
if(xx<0)
xx=0;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
}
else if((10<=aaaa)&&(aaaa<55)) //中间半段
{
xx=80;
if(jspeed=speed2) //比较
{
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
else if(jspeed<speed2) //比较
{
xx+=5;
if(xx>200)
xx=200;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
else //比较
{
xx-=5;
if(xx<0)
xx=0;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
}
else if((55<=aaaa)&&(aaaa<65)) //后半段
{
xx=40;
if(jspeed=speed3) //比较
{
pwm2_h=xx;
CCPR2L=pwm2_h;
}
else if(jspeed<speed3) //比较
{
xx+=5;
if(xx>200)
xx=200;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
else //比较
{
xx-=5;
if(xx<0)
xx=0;
pwm2_h=xx;
CCPR2L=pwm2_h; //输出占空比
}
}
else if(65<=aaaa) //开门到位
{
FLAG5=0;
ENA=0; //电机停止输出
ENB=0;
pwm2_h=0;
CCPR2L=pwm2_h;
}
}
void guanmen()
{
FLAG3=1;
ENA=1;
ENB=1;
INA=0;
INB=1;
kmpwm();
}
//中断服务程序
void interrupt cp1int(void)
{
if(CCP1IF)
{
CCP1IF=0; //清除中断标志
CCPR1L=0;
CCPR1H=0;
bbbb++;
if(FLAG3==1) //后退脉冲递增
{
aaaa++;
COUNT++;
}
if(FLAG3==0) //前进脉冲递减
{
aaaa--;
if(aaaa<0)
aaaa=0;
COUNT--;
if(COUNT<0)
COUNT=0;
}
if(!COUNT)
{
// FLAG2=0;
}
}
if(T0IE&&T0IF) //若是Timer0中断
{
T0IF=0; //清空中断标志
microS+=4096;
if(microS>10000)
{
microS=0;
mS50+=1;
mS_50+=1;
if(mS50=10) //0.1秒
{
mS50=0;
pppp++;
}
if(mS_50==20) //2秒
{
mS_50=0;
gggg++;
qqqq++;
}
}
}
}
void main(void)
{
int i;
uchar pwm2_h;
TRISA|=0x3f; //RA口,除了RA0--RA5做输入,其中RA0做模拟输入,其他做识字数字量输入
TRISA&=0x3f;
CMCON0|=0x07; //关闭比较器,
ANSEL=0x01; //RA0为模拟输入
ADCON1|=0x50; //设置AD转换时钟,在8M晶振下,一个转换周期是2us。
VCFG1=0; //设置AD的参考电压为单片机电源电压。
VCFG0=0;
ADFM=1; //AD结果右对齐
ADON=1; //启动AD采样
TRISB|=0xf9; //RB口中RA1--RA2为继电器输出口
TRISB&=0xf9;
WPUB=0xff; //使能RB所有口的内部弱上拉功能。
TRISC|=0xaf; //RC口中RC0-RC3,RC5,RC7为输入端,其余输出
TRISC&=0xaf;
LCDCON=0; //禁止PORTC几个脚的VLCD功能
TRISD|=0x01; //RD口,除了RD0做输入,其余都做输出
TRISD&=0x01; //其中RD2用作PWM输出(自身带有)。
TRISE|=0x07; //RD口,除了RE0--RE2做输入
TRISE&=0x07;
PR2=0xc7; //Timer2作为PWM的频率控制器,当PR2为0xc8、Timer2为16预分频(是在对晶振的4分频后),晶振是8M时,PWM的频率是612HZ(见917手册的P219)
CCP2CON=0x0c; //将CCP2设置为PWM模式,其中的占空比数值在后面设置
T2CKPS1=1; //将Timer预分频值设为16
T2CKPS0=0;
TMR2IF=0; //清空Timer2的中断标志
TMR2ON=1; //启动Timer2
T0CS=0; //给Timer0选择内部指令周期计数,即将它设置为定时器功能。此时Timer0也开始工作了。
PSA=0; //将预分频器分配给Timer0.
PS2=1; //分频比设置为32.则在8M晶振下,Timer0一个中断周期为4096us。
PS1=0;
PS0=0;
T0IE=1; //允许Timer0中断
//CCP1IE=1; //允许CCP1中断
PEIE=1; //允许外围中断
GIE=1; //允许总中断
pppp=0;
gggg=0;
qqqq=0;
aaaa=0;
FLAG1=0;
FLAG2=0;
WDTPS3=0; //设置看门狗分频是2048,则其周期为66ms
WDTPS2=1;
WDTPS1=1;
WDTPS0=0;
ENA=0;
ENB=0;
INA=0;
INB=0;
relay1=1;
relay2=1;
relay3=1;
relay4=1;
relay5=1;
TMR1H=0;
TMR1L=0; //定时器1清0
CCP1IF=0; //清除CCP1的中断标志,以免中断一打开就进入
//中断
ei( ); //中断允许
TMR1ON=1; //定时器1开
FLAG1=0;
FLAG2=0;
FLAG5=0;
FLAG3=0;
FLAG4=0;
FLAG6=0;
FLAG7=0;
COUNT=0;
aaaa=0;
jspeed=0;
while(1)
{
asm("clrwdt"); //喂狗
if(Gdoor==0&&Kdoor==1&&jinji==1&&geli==1&&FLAG1==0) //启动后退,防抖
{
delay(300);
if(Gdoor==0)
{
delay(200);
if(Gdoor==0)
{
pppp=0;
FLAG5=1;
}
}
}
if(FLAG5==1)
{
//qqqq=0;
ccpint(); //后退
guanmen();
}
else
{
relay3=1; //
guanji();
}
}
} |