欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6245|回復: 3
打印 上一主題 下一主題
收起左側

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

[復制鏈接]
跳轉到指定樓層
樓主
ID:579706 發表于 2019-7-30 11:08 | 只看該作者 回帖獎勵 |正序瀏覽 |閱讀模式
#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個A/D轉換臨時變量
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; //設定目標
double Proportion; //比例常數
double Integral; //積分常數
double Derivative; //微分常數
double LastError; //Error[-1]
double PrevError; //Error[-2]
double SumError;
}PID;
PID sPID;
/*短延時函數*/
void delay1()
{  
int i; //定義整型變量
   for(i=1000;i>0;i--); //延時
}
/*延時函數*/
void Delay_ms1(uint xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<71;j++);
}
}
/*A/D轉換初始化函數*/
void ad_init()
{
TRISA=0x0F;
TRISC=0x00; //設置C口全為輸出
TRISD=0x00; //設置D口全為輸出
ADCON1=0xC4; //轉換結果右對齊,其他做普通I/O
ADCS1=0;
ADCS0=1;
}
//輸出電壓采樣
void sccy()
{
resultsc=0;
  for(int i=5;i>0;i--)
{
  ad_init(); //調用初始化函數
  CHS2=0;
           CHS1=0;
  CHS0=0;//系統時鐘f/16,選擇RA0通道,允許ADC工作
  ADON=1;
  delay1(); //保證采樣延時
  ADGO=1; //開啟轉換過程
  while(ADGO); //等待轉換完成
  resultsc=resultsc+ADRESL+ADRESH*256; //累計轉換結果
}
resultsc=resultsc/5; //求5次結果的平均值
}
//PID基準電壓采樣
void jzcy()
{
resultjz=0;
  for(int i=5;i>0;i--)
{
  ad_init(); //調用初始化函數
  CHS2=0;
           CHS1=0;
  CHS0=1;//系統時鐘f/16,選擇RA1通道,允許ADC工作
  ADON=1;
  delay1(); //保證采樣延時
  ADGO=1; //開啟轉換過程
  while(ADGO); //等待轉換完成
  resultjz=resultjz+ADRESL+ADRESH*256; //累計轉換結果
}
resultjz=resultjz/5; //求5次結果的平均值
}
//輸入電壓采樣
void srcy()
{
resultsr=0;
  for(int i=5;i>0;i--)
{
  ad_init(); //調用初始化函數
  CHS2=0;
           CHS1=1;
  CHS0=1;//系統時鐘f/16,選擇RA3通道,允許ADC工作
  ADON=1;
  delay1(); //保證采樣延時
  ADGO=1; //開啟轉換過程
  while(ADGO); //等待轉換完成
  resultsr=resultsr+ADRESL+ADRESH*256; //累計轉換結果
}
resultsr=resultsr/5; //求5次結果的平均值
}
/*數值轉換函數*/
void conv()
{
scdy=(resultsc*5.0/1023); //A/D轉換的結果
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; //個位
adsc[2]=((int)(scxs*10)-adsc[0]*100-adsc[1]*10); //小數點第一位
adsc[3]=((int)(scxs*100)-adsc[0]*1000-adsc[1]*100-adsc[2]*10); //小數點第二位
adsc[4]=((int)((scxs-adsc[0]*10)*1000)-adsc[1]*1000-adsc[2]*100-adsc[3]*10);//小數點第三位
adjz[0]=((int)(jzxs/10)); //十位
adjz[1]=((int)(jzxs))%10; //個位
adjz[2]=((int)(jzxs*10)-adjz[0]*100-adjz[1]*10); //小數點第一位
adjz[3]=((int)(jzxs*100)-adjz[0]*1000-adjz[1]*100-adjz[2]*10); //小數點第二位
adjz[4]=((int)((jzxs-adjz[0]*10)*1000)-adjz[1]*1000-adjz[2]*100-adjz[3]*10); //小數點第二位
adsr[0]=((int)(srxs/10)); //十位
adsr[1]=((int)(srxs))%10; //個位
adsr[2]=((int)(srxs*10)-adsr[0]*100-adsr[1]*10); //小數點第一位
adsr[3]=((int)(srxs*100)-adsr[0]*1000-adsr[1]*100-adsr[2]*10); //小數點第二位
adsr[4]=((int)((srxs-adsr[0]*10)*1000)-adsr[1]*1000-adsr[2]*100-adsr[3]*10);//小數點第三位
}
//lcd顯示函數
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計算部分
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);
                                    //函數解釋:將s中當前位置后面的n個字節用ch替換并返回s 。
}
//PID輸入函數
double sensor(void) //傳感器
{
return scdy;
}
//PID輸出函數
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初始函數
void initCCP1()
{
int CCP1;
PR2=6; //頻率17.86kHz根據公式計算
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預分頻1:16,開始工作
}
/*主函數*/
void main()
{
PIDInit(&sPID);
while(1)
{
sccy();
jzcy();
srcy();
conv(); //調用轉換函數
delay1();
lcdrw=0; //lcd控制
lcdinit(); //lcd初始化
lcdxianshi();
PIDsc();
initCCP1(); //初始化CCP1
}
}

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

5#
ID:434676 發表于 2021-1-14 11:37 | 只看該作者
謝謝分享,支持支持
回復

使用道具 舉報

地板
ID:78426 發表于 2019-10-25 12:15 | 只看該作者
好程序,有沒有實驗通過?
回復

使用道具 舉報

無效樓層,該帖已經被刪除
沙發
ID:579706 發表于 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
//延時函數
void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
       for(y=220;y>0;y--);
}
//LCD寫命令子程序
void lcdcom(uchar write)
{
        lcdrs=0;
        PORTD=write;
        delay(1);
        lcden=1;
        delay(1);
        lcden=0;
}
//lcd寫數據子程序
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);        //開顯示,光標不閃爍
        lcdcom(0x06);        //光標設置
        lcdcom(0x01);
}
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表