找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6165|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

PIC16F877A編程PID+PWM+1602液晶顯示

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
#
ID:579706 發(fā)表于 2019-7-30 11:08 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
#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)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

板凳
ID:434676 發(fā)表于 2021-1-14 11:37 | 只看該作者
謝謝分享,支持支持
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:78426 發(fā)表于 2019-10-25 12:15 | 只看該作者
好程序,有沒(méi)有實(shí)驗(yàn)通過(guò)?
回復(fù)

使用道具 舉報(bào)

樓主
ID:579706 發(fā)表于 2019-7-30 11:10 | 只看該作者
#include<pic.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define lcdrs RC0 //lcd控制口
#define lcdrw RC1
#define lcden RC3
//延時(shí)函數(shù)
void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
       for(y=220;y>0;y--);
}
//LCD寫(xiě)命令子程序
void lcdcom(uchar write)
{
        lcdrs=0;
        PORTD=write;
        delay(1);
        lcden=1;
        delay(1);
        lcden=0;
}
//lcd寫(xiě)數(shù)據(jù)子程序
void lcddat(uchar shuju)
{
        lcdrs=1;
        PORTD=shuju;
        delay(1);
        lcden=1;
        delay(1);
        lcden=0;
}
//lcd初始化子程序
void lcdinit()
{
        lcden=0;
        lcdcom(0x38);        //顯示模式
        lcdcom(0x0c);        //開(kāi)顯示,光標(biāo)不閃爍
        lcdcom(0x06);        //光標(biāo)設(shè)置
        lcdcom(0x01);
}
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表