通用数字PID调节器设计.docx
《通用数字PID调节器设计.docx》由会员分享,可在线阅读,更多相关《通用数字PID调节器设计.docx(28页珍藏版)》请在冰豆网上搜索。
通用数字PID调节器设计
通用数字PID调节器设计
主要技术数据和设计要求
主要技术数据:
8路模拟量输入:
适配1~5V输入,量程自由设定;
8路输出控制信号:
1~5V标准电压输出;
输入模拟量转换精度:
0.1%;
RS232串行通讯通口;
控制模型:
数字PID控制算法
PID参数范围:
比例带Kp:
1-999.9%
积分时间Ti:
1-9999秒(Ti=9999时积分切除)
微分时间Td:
:
0-9999秒(Td=0时微分切除)
调节控制器使用51内核的单片机内核的单片机,完成对8路模拟信号的切换、信号变换、A/D转换;单片机对数据处理后(含数字滤波、数值变换),送到显示和通讯部分,并经PID运算处理后通过D/A转换器输出。
经信号变换和信号分配后输出8路控制信号。
设计中应充分考虑干扰问题。
设计步骤
一、总体方案设计
二、控制系统的建模和数字控制器设计
三、硬件的设计和实现
1.选择计算机机型(采用51内核的单片机);
2.设计支持计算机工作的外围电路(EPROM、RAM、I/O端口等);
3.设计键盘、显示接口电路;
4.设计8路模拟量输入输出通道;
5.设计RS232串行通讯通口;
*6.其它相关电路的设计或方案(电源、通信等)。
四、软件设计
1.分配系统资源,编写系统初始化和主程序模块;
2.编写数字PID调节器软件模块;
3.编写数字滤波程序;
*4.编写A/D、D/A转换器处理程序模块;
*5.其它程序模块(显示与键盘等处理程序)。
五、编写课程设计说明书,绘制完整的系统电路图。
PID调节器主控部分包括以下几个部分:
单片机部分、A/D转换部分、D/A转换部分、稳压部分、数字输入输出部分以及串口通信部分。
D1:
内部设定点信号灯
S1:
内部设定点和外部设定点转换开关
D2:
手动信号灯
S2:
手动自动转换开关
D3:
实际值X显示信号灯
D4:
设定值W显示信号灯
S3:
参数修改以及实际值和设定值显示转换开关
D5:
超过限定值信号灯
D6:
低于限定值信号灯
S4:
设定值增加按钮
S5:
设定值减少按钮
S6:
修改手动变量按钮
S7:
修改手动变量按钮
附录[1]主程序—MAIN.C
#include"adconver.h"
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
#include"subkey1.h"
#include"subkey2.h"
#include"subkey3.h"
#include"subkey4.h"
#include"subkey5.h"
#include"subkey6.h"
bitinsertsetframe=1;//内部设定标志位
bithandframe=1;//手动设定标志位
bitimprovedisframe=0;//实际值标志位
bitshineframe=0;//判断是不是第一次开机停止4LED的闪烁
bitcanshuframe=0x00;//参数标志位
unsignedcharcircleframe=0x00;//参数循环变量
unsignedcharchannelframe=0x00;//通道标志位
unsignedcharledframe=0xfc;//LED灯管状态
unsignedchartimes=0x00;//记数位
unsignedcharreadkey;
unsignedintsetvalue=0x00;//设定值
unsignedcharoutputvalue=0x00;//输出值
unsignedintlimup=0x270f;//实际值上限
unsignedintlimdown=0x00;//实际值下限
unsignedinta1=0x270f;//上限报警值
unsignedinta2=0x00;//下限报警值
unsignedintcp=0x00;//P参数
unsignedintci=0x00;//I参数
unsignedintcd=0x00;//D参数
unsignedcharled[6];//LED值公共
main()
{
unsignedinttmr;
unsignedcharkeynumber;
for(tmr=0;tmr<0xffff;tmr++);
write7281(0x12,0x80);
write7281(0x10,0xf0);
write7281(0x00,0xc8);
write7281(0x14,0x1b);
write7281(0x14,0x2e);
write7281(0x15,0x30);
write7281(0x15,0x40);
write7281(0x15,0x50);
write7281(0x06,0xfc);
while
(1)
{
while(!
key)
{
keynumber=read7281(0x13);
switch(keynumber)
{
case0x00:
subkey0();break;
case0x01:
subkey1();break;
case0x02:
subkey2();break;
case0x03:
subkey3();break;
case0x04:
subkey4();break;
case0x05:
subkey5();break;
case0x06:
subkey6();break;
default:
break;
}
}
}
}
附录[2]S1模块的程序—SUBKEY0.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
voidsubkey0()
{
if(insertsetframe==1)
{
insertsetframe=0;
ledframe|=0x01;
write7281(0x06,ledframe);
}
else
{
insertsetframe=1;
ledframe&=0xfe;
write7281(0x06,ledframe);
}
}//更改内部设定和外部设定的状态,并将相应的状态位进行更改,并更改状态灯
附录[3]S2模块的程序—SUBKEY1.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey1.h"
voidsubkey1()
{
if(handframe==1)
{
handframe=0;
ledframe|=0x02;
write7281(0x06,ledframe);
}
else
{
handframe=1;
ledframe&=0xfd;
write7281(0x06,ledframe);
}
}//更改手动自动状态,改变相应的状态位,更改相应的状态灯
附录[4]S3模块的程序—SUBKEY2.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey2.h"
#include"adconver.h"
#include"subkey0.h"
#include"subkey1.h"
#include"hdconver.h"
#include"subkey3.h"
#include"subkey4.h"
#include"pid.h"
#include"daconver.h"
voidsubkey2()
{
if(shineframe==0)
{
write7281(0x10,0xff);
shineframe=1;
}
else
{
skey2();
}
}
voidskey2(void)
{//canshuframe=1;
write7281(0x18,0x17);
switch(circleframe)
{
case0x00:
ledframe|=0x0c;
write7281(0x06,ledframe);
circleframe+=1;
hdconver(limup);//4LED显示上限值
dis4led();
write7281(0x14,0x41);
write7281(0x14,0x5C);//写入2LEDHI
break;
case0x01:
circleframe+=1;
hdconver(limdown);//4LED显示下限值
dis4led();
write7281(0x14,0x40);
write7281(0x14,0x5d);//写入2LEDLO
break;
case0x02:
circleframe+=1;
hdconver(a1);//4LED显示上限报警
dis4led();
write7281(0x14,0x41);
write7281(0x15,0x5a);//写入2LEDA1
break;
case0x03:
circleframe+=1;
hdconver(a2);//4LED显示下限报警
dis4led();
write7281(0x14,0x42);
write7281(0x15,0x5a);//写入2LEDA2
break;
case0x04:
circleframe+=1;
hdconver(cp);//4LED显示P参数
dis4led();
write7281(0x14,0x4e);
write7281(0x14,0x5f);//写入2LEDP
break;
case0x05:
circleframe+=1;
hdconver(ci);//4LED显示I参数
dis4led();
write7281(0x14,0x41);
write7281(0x14,0x5f);//写入2LEDI
break;
case0x06:
circleframe+=1;
hdconver(cd);//4LED显示D参数
dis4led();
write7281(0x15,0x4d);
write7281(0x14,0x5f);//写入2LEDI
break;
case0x07:
improvedisframe=0;
ledframe=(ledframe|0x08)&0xfb;
circleframe+=1;
adconver();
write7281(0x14,0x40);
write7281(0x14,channelframe);
write7281(0x06,ledframe);
break;
case0x08:
improvedisframe=1;
ledframe=(ledframe|0x04)&0xf7;
circleframe=0;
pidcf();
daconver();
hdconver(setvalue);
dis4led();
write7281(0x06,ledframe);
break;
default:
break;
}
}//按相应的S3改变不同的参数
附录[5]S4模块的程序—SUBKEY3.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey3.h"
#include"subkey2.h"
#include"hdconver.h"
voidsubkey3()
{
switch(circleframe)
{
case0x01:
limup=add1(limup);
break;
case0x02:
limdown=add1(limdown);
break;
case0x03:
a1=add1(a1);
break;
case0x04:
a2=add1(a2);
break;
case0x05:
cp=add1(cp);
break;
case0x06:
ci=add1(ci);
break;
case0x07:
cd=add1(cd);
break;
case0x00:
setvalue=add1(setvalue);
break;
default:
break;
}
}
unsignedintadd1(unsignedintvalue)
{
ledframe|=0x20;//关掉下限报警
write7281(0x06,ledframe);
if(value==9999)
{
ledframe&=0xef;//打开上限报警灯
write7281(0x06,ledframe);
write7281(0x06,ledframe);
}
else
{
value+=1;
}
hdconver(value);
dis4led();
return(value);
}
附录[6]S5模块的程序—SUBKEY4.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey4.h"
#include"subkey2.h"
#include"hdconver.h"
voidsubkey4()
{
switch(circleframe)
{
case0x01:
limup=sub1(limup);
break;
case0x02:
limdown=sub1(limdown);
break;
case0x03:
a1=sub1(a1);
break;
case0x04:
a2=sub1(a2);
break;
case0x05:
cp=sub1(cp);
break;
case0x06:
ci=sub1(ci);
break;
case0x07:
cd=sub1(cd);
break;
case0x00:
setvalue=sub1(setvalue);
break;
default:
break;
}
}
unsignedintsub1(unsignedintvalue)
{
ledframe|=0x10;//关掉上限报?
write7281(0x06,ledframe);
if(value==0)
{
ledframe&=0xdf;//打开上限报警灯
write7281(0x06,ledframe);
}
else
{
value-=1;
}
hdconver(value);
dis4led();
return(value);
}
附录[7]S6模块的程序—SUBKEY5.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey5.h"
#include"hdconver.h"
voidsubkey5()
{
if(improvedisframe==0)
{
channelframe=0x00;
write7281(0x15,0x40);
write7281(0x15,0x50);//若现在状态为实际值,则改变通道状态并显示现在状态为00
}
else
{
if(handframe==1)
{
ledframe|=0x10;//关掉上限报警灯
write7281(0x06,ledframe);
if(outputvalue==0x00)
{
ledframe&=0xdf;//打开下限报警灯
write7281(0x06,ledframe);
}
else
{
outputvalue-=1;
hdconver2(outputvalue);
}
dis2led();
}
}
}
附录[7]S7模块的程序—SUBKEY6.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey6.h"
#include"hdconver.h"
voidsubkey6()
{
if(improvedisframe==0)
{
channelframe=0x01;
write7281(0x15,0x41);
write7281(0x15,0x50);//若现状态为实际值,则2LED显示为01
}
else
{
if(handframe==1)
{
ledframe|=0x20;//关掉下限报警灯
write7281(0x06,ledframe);
if(outputvalue==99)
{
ledframe&=0xef;//打开上限报警档?
write7281(0x06,ledframe);
}
else
{
outputvalue+=1;
hdconver2(outputvalue);
}
}
dis2led();
}
}
附录[8]A/D转换模块的程序—ADCONVER.C
#include"STC12C5410AD.H"
#include"adconver.H"
#include"delay.h"
#include"main.h"
#include"dis7281.h"
#include"hdconver.h"
voidadconver()
{unsignedcharadchanne=0xe0;//设置P1的0.1位为AD输入通道
ADC_CONTR=(0x80|ADC_CONTR)+channelframe;//开启AD模拟电源
delay(1000);
P1M0=0x03;
P1M1=0x03;//设置通道为开漏模式
ADC_CONTR=adchanne+channelframe;//设置AD转换通道
delay(22);
ADC_DATA=0x00;
ADC_LOW2=0x00;//清除数据口
ADC_CONTR|=0x08;//开启AD端口
while(!
(ADC_CONTR&0x10)){};//等待AD转换完成
ADC_CONTR&=0xe7;//停止AD转换
P1M0&=0xfd;
P1M1&=0xfd;//设置P1口为普通IO模式
addis();
}
voidaddis()
{
unsignedintaddata;
doubleliangch;
liangch=(limup-limdown)/100;
addata=ADC_DATA+(ADC_LOW2&0x03)*1024;
liangch=liangch/1023*addata;
addata=(unsignedint)liangch;
if(addata>a1)
{
ledframe&=0xef;//打开上限报警灯
write7281(0x06,ledframe);
}
if(addata{
ledframe&=0xdf;//打开上限报警灯
write7281(0x06,ledframe);
}
hdconver(addata);
dis4led();
}
附录[8]D/A转换模块的程序—DACONVER.C
#include"delay.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"daconver.h"
sbitTLV5618_SCLK=P1^7;
sbitTLV5618_DIN=P1^5;
sbitTLV5618_CS=P1^4;
voidmDelay(unsignedinta)
{unsignedintf;
for(f=0;f}
voidTLV5618(unsignedintda)
{
unsignedinti;
unsignedintdat;
dat=da|0xc000;
TLV5618_CS=0;
TLV5618_SCLK=0;
for(i=0;i<16;i++)
{
TLV5618_DIN=(bit)(dat&0x8000);
dat=dat<<1;
TLV5618_SCLK=1;
mDelay(50);
TLV5618_SCLK=0;
mDelay(50);
}
TLV5618_CS=1;
}
voiddaconver(void)
{floati=100;
unsignedintda;
i=outputvalue/100*4096;
da=(unsignedint)i;
TLV5618(da);
}
附录[9]显示及键盘模块的程序—DIS7281.C
#include"delay.H"
#include"STC12C5410AD.H"
#include"dis7281.H"
#include"main.h"
voidwrite7281(unsignedcharregadd,unsignedcharwritedata)
{
sendbyte(regadd);
sendbyte(writedata);
}
voidsendbyte(unsignedcharsendbyte)
{
unsignedcharbitcounter;
clk=0;
clk=1;
do{
clk=0;
clk=1;
}while(dat);
clk=0;
clk=1;
while(!
dat);
for(bitcounter=0;bitcounter<8;bitcounter++)
{
i