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

发布者:爱笑的猫咪最新更新时间:2019-10-24 来源: 51hei关键字:PIC16F877A  编程PID  PWM  1602液晶显示 手机看文章 扫描二维码
随时随地手机看文章

#include

#include

#include

#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{

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 

}

}


关键字:PIC16F877A  编程PID  PWM  1602液晶显示 引用地址:PIC16F877A编程PID+PWM+1602液晶显示

上一篇:pic单片机做的万年历
下一篇:PIC单片机驱动TM1616源程序

推荐阅读最新更新时间:2024-11-12 16:23

单片机红外遥控解码HS0038B用1602液晶显示
一个红外遥控接收头解码的列子 试验成功,51单片机+1602液晶显示,完整的源码下载地址是:http://www.51hei.com/bbs/dpj-19538-1.html 下面给出主要程序的预览: /************************************************** *程序名称: HS0038B红外遥控键值显示 *晶 振: 11.0592MHZ *作 者: Kevin.Xie *时 间: 200944 *地 址: 51hei ***************************************************/ /* HS0038
[单片机]
stm32的PWM输入捕获模式
一、概念理解 PWM输入捕获模式是输入捕获模式的特例,自己理解如下 1. 每个定时器有四个输入捕获通道IC1、IC2、IC3、IC4。且IC1 IC2一组,IC3 IC4一组。并且可是设置管脚和寄存器的对应关系。 2. 同一个TIx输入映射了两个ICx信号。 3. 这两个ICx信号分别在相反的极性边沿有效。 4. 两个边沿信号中的一个被选为触发信号,并且从模式控制器被设置成复位模式。 5. 当触发信号来临时,被设置成触发输入信号的捕获寄存器,捕获 一个PWM周期(即连续的两个上升沿或下降沿) ,它等于包含TIM时钟周期的个数(即捕获寄存器中捕获的为TIM的计数个数n)。 6. 同样另一个捕获通道捕获触发信号和下一个相反极
[单片机]
实现半桥DC/DC变换器软开关的PWM控制解决方案
经常被用于中小功率电路设计的DC-DC转换器一直是工程师们在进行电源设计时候的首选。半桥电路由两个功率开关器件总成,并向外提供方波信号。大家都知道,常见的半桥控制器通常有两种控制方法,一种是对称控制,而另一种则是不对称互补控制,本文主要分析实现半桥DC/DC变换器软开关的PWM控制策略。 在本文中缓冲型软开关对称PWM控制策略是指对称控制半桥变换器磁心双向磁化,利用率高,且不存在偏磁。控制方便,控制特性线性。功率管上电压应力低,适用于高输入电压场合,但此种半桥变换器较难实现软开关,变换器效率难以得到提高。 对称PWM 控制ZVS半桥变换器 对称式PWM 控制ZVS半桥变换器,其与传统半桥电路相比,对称PWM控制的ZVS
[电源管理]
PIC16F877A单片机 (IIC总线+AT24C02芯片)
1 基本原理 1.1 IIC总线 需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。 1.2 AT24C02芯片 2 源代码 /*---------------------函数功能: IIC总线 AT24C02 -----------------------------------------*/ #include pic.h // 调用PIC16f87XA单片机的头文件 #include delay.h //调用延时子函数的头文件 __CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关
[单片机]
<font color='red'>PIC16F877A</font>单片机 (IIC总线+AT24C02芯片)
AVR单片机定时/计数器的PWM的应用设计
一、定时/计数器PWM设计要点 根据PWM的特点,在使用ATmega128的定时/计数器设计输出PWM时应注意以下几点: 1.首先应根据实际的情况,确定需要输出的PWM频率范围,这个频率与控制的对象有关。如输出PWM波用于控制灯的亮度,由于人眼不能分辨42Hz以上的频率,所以PWM的频率应高于42Hz,否则人眼会察觉到灯的闪烁。 2.然后根据需要PWM的频率范围确定ATmega128定时/计数器的PWM工作方式。AVR定时/计数器的PWM模式可以分成快速PWM和频率(相位)调整PWM两大类。 3.快速PWM可以的到比较高频率的PWM输出,但占空比的调节精度稍微差一些。此时计数器仅工作在单程正向计数方式,计数器的上限值决定PW
[单片机]
AVR单片机定时器、PWM、ICP范例
/*********************************************** **** AVR 定时器使用范例 *** **** *** **** 编译器:WINAVR20050214 *** ***********************************************/ /* 本程序简单的示范了如何使用ATMEGA16的定时器 AVR定时器的要点介绍 T0工作于CTC模式,输出1KHz/2KHz 50%占空比的方波 T1工作于快速PWM模式兼输入捕捉 T2工作于相位修正
[单片机]
为什么万用表电压档测量传感器看到的是 PWM 信号?
有一个测量位置变化的位置传感器,用万用表电压档测量传感器的输出信号,结果显示的是模拟量信号,即位置和信号输出大小呈线性关系。但是,用示波器(Picoscope 4227)测量传感器的输出信号,显示的却是 PWM 信号(脉宽调制),即位置不同,输出 PWM 信号的占空比不同。 PWM 信号的参数是:200 Hz, 低电平为 0V,高电平为 18V。 现在可以确定,我的传感器输出信号是 PWM 信号。PWM 信号需要输入到控制器 I/O中,但是控制器 I/O 口不具备直接采集 PWM 信号的功能。 解决方案 设计个电路,将 PWM 信号转化为模拟量信号,然后将转换后的模拟量信号输入到控制器模拟量 I/O 口。 转换电路
[测试测量]
为什么万用表电压档测量传感器看到的是 <font color='red'>PWM</font> 信号?
【51单片机快速入门指南】3.2.1:PWM、呼吸灯与舵机
普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 PWM(脉冲宽度调制) 摘自百度百科。 基本原理 控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等但宽度不一致的脉冲,用这些脉冲来代替正弦波或所需要的波形。按一定的规则对各脉冲的宽度进行调制,既可改变逆变电路输出电压的大小,也可改变输出频率。 (SPWM)例如,把正弦半波波形分成N等份,就可把正弦半波看成由N个彼此相连的脉冲所组成的波形。这些脉冲宽度相等,都等于 π/n ,但幅值不等,且脉冲顶部不是水平直线
[单片机]
【51单片机快速入门指南】3.2.1:<font color='red'>PWM</font>、呼吸灯与舵机
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved