单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 138|回复: 1
打印 上一主题 下一主题
收起左侧

PIC16F877A编程PID+PWM+1602液晶显示

[复制链接]
跳转到指定楼层
楼主
13731062108 发表于 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空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

沙发
 楼主| 13731062108 发表于 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);
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表