#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 } }
上一篇:pic单片机做的万年历
下一篇:PIC单片机驱动TM1616源程序
推荐阅读最新更新时间:2024-11-12 16:23
设计资源 培训 开发板 精华推荐
- 使用 Analog Devices 的 ADUC845 的参考设计
- 电流采样电路_2023-07-26_18-31-41
- 基于C2800系列的DSP开发板
- LTC2181、16 位、40Msps 低功耗双通道 ADC 的典型应用
- XC6206
- LT3990IMSE-5 5V 同步降压转换器的典型应用
- DC2268A-F,用于 LTM4630EV 双路 18A/单路 36A 降压模块稳压器的演示板,4.5V=VIN=15V,Vout1 = 1V @ 18A,Vout2 = 1.5V @ 18A
- 基于Z16F2811AL20SG MCU的Z16F2800100ZCOG、ZNEO Z16F系列开发套件
- LT1148-3.3、94% 效率同步降压稳压器在 3.3V 时从 5V 逻辑电源泵出 2A
- 【征集令】EHome摄像头继电器模块V2.0