|
#include<string.h>
#include<stdio.h>
#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
#include"cd1602.h"
uint adsc[5],adjz[5],adsr[5]; //定義3個(gè)A/D轉(zhuǎn)換臨時(shí)變量
uint resultjz,resultsr,resultsc; //PWM為jz2,PID為jz1
double scdy,jzdy,srdy,pidsc,tjkz,jzxs,scxs,srxs,PWMsr,jzzkb;
__CONFIG(HS&WDTDIS);
typedef struct PID{
double SetPoint; //設(shè)定目標(biāo)
double Proportion; //比例常數(shù)
double Integral; //積分常數(shù)
double Derivative; //微分常數(shù)
double LastError; //Error[-1]
double PrevError; //Error[-2]
double SumError;
}PID;
PID sPID;
/*短延時(shí)函數(shù)*/
void delay1()
{
int i; //定義整型變量
for(i=1000;i>0;i--); //延時(shí)
}
/*延時(shí)函數(shù)*/
void Delay_ms1(uint xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<71;j++);
}
}
/*A/D轉(zhuǎn)換初始化函數(shù)*/
void ad_init()
{
TRISA=0x0F;
TRISC=0x00; //設(shè)置C口全為輸出
TRISD=0x00; //設(shè)置D口全為輸出
ADCON1=0xC4; //轉(zhuǎn)換結(jié)果右對(duì)齊,其他做普通I/O
ADCS1=0;
ADCS0=1;
}
//輸出電壓采樣
void sccy()
{
resultsc=0;
for(int i=5;i>0;i--)
{
ad_init(); //調(diào)用初始化函數(shù)
CHS2=0;
CHS1=0;
CHS0=0;//系統(tǒng)時(shí)鐘f/16,選擇RA0通道,允許ADC工作
ADON=1;
delay1(); //保證采樣延時(shí)
ADGO=1; //開(kāi)啟轉(zhuǎn)換過(guò)程
while(ADGO); //等待轉(zhuǎn)換完成
resultsc=resultsc+ADRESL+ADRESH*256; //累計(jì)轉(zhuǎn)換結(jié)果
}
resultsc=resultsc/5; //求5次結(jié)果的平均值
}
//PID基準(zhǔn)電壓采樣
void jzcy()
{
resultjz=0;
for(int i=5;i>0;i--)
{
ad_init(); //調(diào)用初始化函數(shù)
CHS2=0;
CHS1=0;
CHS0=1;//系統(tǒng)時(shí)鐘f/16,選擇RA1通道,允許ADC工作
ADON=1;
delay1(); //保證采樣延時(shí)
ADGO=1; //開(kāi)啟轉(zhuǎn)換過(guò)程
while(ADGO); //等待轉(zhuǎn)換完成
resultjz=resultjz+ADRESL+ADRESH*256; //累計(jì)轉(zhuǎn)換結(jié)果
}
resultjz=resultjz/5; //求5次結(jié)果的平均值
}
//輸入電壓采樣
void srcy()
{
resultsr=0;
for(int i=5;i>0;i--)
{
ad_init(); //調(diào)用初始化函數(shù)
CHS2=0;
CHS1=1;
CHS0=1;//系統(tǒng)時(shí)鐘f/16,選擇RA3通道,允許ADC工作
ADON=1;
delay1(); //保證采樣延時(shí)
ADGO=1; //開(kāi)啟轉(zhuǎn)換過(guò)程
while(ADGO); //等待轉(zhuǎn)換完成
resultsr=resultsr+ADRESL+ADRESH*256; //累計(jì)轉(zhuǎn)換結(jié)果
}
resultsr=resultsr/5; //求5次結(jié)果的平均值
}
/*數(shù)值轉(zhuǎn)換函數(shù)*/
void conv()
{
scdy=(resultsc*5.0/1023); //A/D轉(zhuǎn)換的結(jié)果
jzdy=(resultjz*5.0/1023);
srdy=(resultsr*5.0/1023);
scxs=scdy*4;
jzxs=jzdy*4;
srxs=srdy*4;
adsc[0]=((int)(scxs/10)); //十位
adsc[1]=((int)(scxs))%10; //個(gè)位
adsc[2]=((int)(scxs*10)-adsc[0]*100-adsc[1]*10); //小數(shù)點(diǎn)第一位
adsc[3]=((int)(scxs*100)-adsc[0]*1000-adsc[1]*100-adsc[2]*10); //小數(shù)點(diǎn)第二位
adsc[4]=((int)((scxs-adsc[0]*10)*1000)-adsc[1]*1000-adsc[2]*100-adsc[3]*10);//小數(shù)點(diǎn)第三位
adjz[0]=((int)(jzxs/10)); //十位
adjz[1]=((int)(jzxs))%10; //個(gè)位
adjz[2]=((int)(jzxs*10)-adjz[0]*100-adjz[1]*10); //小數(shù)點(diǎn)第一位
adjz[3]=((int)(jzxs*100)-adjz[0]*1000-adjz[1]*100-adjz[2]*10); //小數(shù)點(diǎn)第二位
adjz[4]=((int)((jzxs-adjz[0]*10)*1000)-adjz[1]*1000-adjz[2]*100-adjz[3]*10); //小數(shù)點(diǎn)第二位
adsr[0]=((int)(srxs/10)); //十位
adsr[1]=((int)(srxs))%10; //個(gè)位
adsr[2]=((int)(srxs*10)-adsr[0]*100-adsr[1]*10); //小數(shù)點(diǎn)第一位
adsr[3]=((int)(srxs*100)-adsr[0]*1000-adsr[1]*100-adsr[2]*10); //小數(shù)點(diǎn)第二位
adsr[4]=((int)((srxs-adsr[0]*10)*1000)-adsr[1]*1000-adsr[2]*100-adsr[3]*10);//小數(shù)點(diǎn)第三位
}
//lcd顯示函數(shù)
void lcdxianshi()
{
uchar i;
lcdcom(0x80);
for(i=0;i<10;i++)
{
if(i==0)
lcddat(0x6A);
else if(i==1)
lcddat(0x7A);
else if(i==2)
lcddat(0x3A);
else if(i==3)
lcddat(adjz[i-3]+0x30);
else if(i==4)
lcddat(adjz[i-3]+0x30);
else if(i==5)
lcddat(0x2E);
else if(i==9)
lcddat(0x56);
else
lcddat(adjz[i-4]+0x30);
}
lcdcom(0x8B);
for(i=0;i<5;i++)
{
if(i==0)
lcddat(0x73);
else if(i==1)
lcddat(0x72);
else if(i==2)
lcddat(0x3A);
else if(i==3)
lcddat(adsr[i-3]+0x30);
else if(i==4)
lcddat(adsr[i-3]+0x30);
}
lcdcom(0xC0);
for(i=0;i<10;i++)
{
if(i==0)
lcddat(0x73);
else if(i==1)
lcddat(0x63);
else if(i==2)
lcddat(0x3A);
else if(i==3)
lcddat(adsc[i-3]+0x30);
else if(i==4)
lcddat(adsc[i-3]+0x30);
else if(i==5)
lcddat(0x2E);
else if(i==9)
lcddat(0x56);
else
lcddat(adsc[i-4]+0x30);
}
lcdcom(0xCB);
for(i=0;i<5;i++)
{
if(i==0)
lcddat(0x2E);
else if(i==4)
lcddat(0x56);
else
lcddat(adsr[i+1]+0x30);
}
}
//PID計(jì)算部分
double PIDCalc(PID *pp,double NextPoint)
{
double dError,Error;
Error=pp->SetPoint-NextPoint;
pp->SumError+=Error;
dError=pp->LastError-pp->PrevError;
pp->PrevError=pp->LastError;
pp->LastError=Error;
return(pp->Proportion * Error+pp->Integral * pp->SumError+
pp->Derivative * dError);
}
//PID初始化
void PIDInit(PID *pp)
{
memset(pp,0,sizeof(PID)); //memset(void *s, int ch, size_t n);
//函數(shù)解釋:將s中當(dāng)前位置后面的n個(gè)字節(jié)用ch替換并返回s 。
}
//PID輸入函數(shù)
double sensor(void) //傳感器
{
return scdy;
}
//PID輸出函數(shù)
void PIDsc(void)
{
double rOut;
double rIn;
sPID.Proportion=0.1;
sPID.Integral=0.0;
sPID.Derivative=0.0;
sPID.SetPoint=jzdy;
rIn=sensor();
rOut=PIDCalc(&sPID,rIn);
pidsc=rOut;
}
//CCP1初始函數(shù)
void initCCP1()
{
int CCP1;
PR2=6; //頻率17.86kHz根據(jù)公式計(jì)算
CCP1CON=0b00001100; //PWM模式
PWMsr=jzdy-pidsc;
if(srdy<=0)
srdy=0.005;
if(PWMsr<=0)
{
PWMsr=0.2;
}
jzzkb=(1-srdy/jzdy)*5;
tjkz=jzdy*jzzkb/PWMsr;
if(tjkz>=2.25)
{
tjkz=2.25;
}
CCP1=(int)((PR2+1)*4*tjkz/5);
CCP1Y=CCP1%2;
CCP1X=((CCP1-CCP1Y)/2)%2;
CCPR1L=(CCP1-CCP1X*2-CCP1Y)/4;
T2CON=0b00000110; //TMR2預(yù)分頻1:16,開(kāi)始工作
}
/*主函數(shù)*/
void main()
{
PIDInit(&sPID);
while(1)
{
sccy();
jzcy();
srcy();
conv(); //調(diào)用轉(zhuǎn)換函數(shù)
delay1();
lcdrw=0; //lcd控制
lcdinit(); //lcd初始化
lcdxianshi();
PIDsc();
initCCP1(); //初始化CCP1
}
}
|
評(píng)分
-
查看全部評(píng)分
|