📄 pid.c51
字号:
#include <reg51.h>
#include<math.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/*MAX7219寄存器功能说明**********************************/
#define shutdown 0x0c //0 关闭 1 开启
#define decodemode 0x09 //0 ndecode all
//1 decode 0
//0f decode 0-3
//ff decode all
#define intensity 0x0a //亮度控制寄存器 0-f
/*显示位控制寄存器***************************************/
/*0-第一位 1-第一、二位 ......7-全显示*****************/
#define scanlimit 0x0b
#define testreg 0x0f //测试模式 0 普通模式 1显示测试模式
#define dataaddr 0x01 //显示基址
/********************************************************/
#define set_0(X) X=0
#define set_1(X) X=1
/***************************PID参数**********************/
#define Kp 32 //定义PID三个参数 放大16倍
#define Ki 8
#define Kd 6
sbit clk=P2^1;
sbit load_cs=P2^2;
sbit din=P2^0;
sbit ready=P3^2;
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P2_6=P2^6;
#define power_on P2_6=1
#define power_off P2_6=0
#define set_tem 10
#define ok 11
#define no_key 12
unsigned char xdata start _at_ 0xfff8;
unsigned char xdata read_h _at_ 0xfffc;
unsigned char xdata read_l _at_ 0xfffe;
/***********************全局变量*************************/
signed int tem_data=0; //炉子温度测量值
signed int tem_data_set=0; //温度设定值
signed int E_n,E_nSUB1,E_nSUB2;
signed char U_n=0; //PID调节输出
/************************AD转换子程序********************/
long AD574(void)
{ uchar data_h=0,data_l=0;
int result_12=0;
XBYTE[0xfff8]=0;
while(ready==1); //等待转换结束
data_h=XBYTE[0xfffc];
data_l=read_l;
data_l=data_l>>4;
result_12=data_h<<4;
result_12=result_12+(data_l&0x0F);
return (result_12); //返回12位A/D转换结果
}
/***********************线性化处理子程序*****************/
int LinearProcessing(long result) //线性化处理子程序
{int tem_data;
tem_data=(long)result*10000/4095;
return(tem_data);
}
/***********************数字滤波处理子程序*****************/
int filtering(int tem_data_8[])
{unsigned char i,j,k;
int con_data=0;
int temp;
i=0;
j=0;
temp=tem_data_8[0]; //找最小值
for(k=1;k<8;k++)
{if(temp>tem_data_8[k])
{temp=tem_data_8[k];
i=k;
}
}
temp=tem_data_8[0]; //找最小值
for(k=1;k<8;k++)
{if(temp<tem_data_8[k])
{temp=tem_data_8[k];
j=k;
}
}
tem_data_8[i]=0; //求平均值
tem_data_8[j]=0;
for(k=0;k<8;k++)
{con_data+=tem_data_8[k];
}
con_data=con_data/6;
return(con_data);
}
/************************温度显示刷新子程序**************/
void tem_refresh(int TEM_data) //温度显示刷新子程序
{void max7219_data_send(uchar ,uchar );
uchar i;
TEM_data=TEM_data/10;
i=TEM_data%10;
max7219_data_send(dataaddr+3,i); //刷新个位
TEM_data=TEM_data/10;
i=TEM_data%10;
max7219_data_send(dataaddr+2,i); //刷新十位
TEM_data=TEM_data/10;
i=TEM_data%10;
max7219_data_send(dataaddr+1,i); //刷新百位
TEM_data=TEM_data/10;
i=TEM_data%10;
max7219_data_send(dataaddr+0,i); //刷新千位
}
/*******************PID调节子程序************************/
void PID(void)
{signed int U_add=0;
U_add=Kp*(E_n-E_nSUB1)+Ki*E_n+Kd*(E_n-2*E_nSUB1+E_nSUB2);
U_add=U_add/10; //缩小10倍
U_add=U_add>>4; //缩小16倍
U_n=U_n+U_add;
if(U_n<0) //错误处理
U_n=0;
else if(U_n>100)
U_n=100;
else ;
return;
}
/********************对MAX7219通信总线初始化*******************/
void initial()
{
set_0(clk);
set_0(load_cs);
set_0(din);
}
/*****************向MAX7219发送一个16位数据*******************/
void max7219_data_send(uchar addr,uchar data_send) //向MAX7219发送一个16位数据
{
uchar i,a;
set_0(load_cs);
for(i=0;i<4;i++)
{
set_0(clk);
set_1(clk);
}
addr=addr<<4;
for(i=0;i<4;i++)
{
set_0(clk);
a=addr&0x80;
if(a) set_1(din);
else set_0(din);
addr=addr<<1;
set_1(clk);
}
for(i=0;i<8;i++)
{
set_0(clk);
a=data_send&0x80;
if(a) set_1(din);
else set_0(din);
data_send=data_send<<1;
set_1(clk);
}
set_1(load_cs);
}
/*******************主函数******************************/
void main()
{
initial(); //MAX7219初始化设置
max7219_data_send(decodemode,0x0ff);
max7219_data_send(intensity,0x01);
max7219_data_send(scanlimit,0x03);
max7219_data_send(shutdown,0x01);
max7219_data_send(testreg,0x00);
E_n=0;
E_nSUB1=0;
E_nSUB2=0;
TMOD=0x56;
TH0=256-100;
TL0=256-100;
TH1=0;
TL1=0;
IT1=1;
EX1=1;
ET0=1;
ET1=1;
EA=1;
TR0=1;
TR1=1;
P1=0xF0;
while(1);
}
/****************************外部中断1中断服务程序****************************/
void key() interrupt 2
{unsigned char KeyScan();
unsigned char key_value;
char i,j,k;
unsigned char key_value_3[3]={0,0,0};
TR0=0;
TR1=0;
EA=0;
key_value=KeyScan();
if(key_value==set_tem)
{ for(i=0;i<4;i++)
{max7219_data_send(dataaddr+i,0);
}
i=0;
while(i<3)
{ while(1)
{key_value=KeyScan();
if(key_value==no_key)
continue;
else
{key_value_3[i]=key_value;
j=i;
k=0;
for(;j>=0;j--)
{max7219_data_send(dataaddr+3-j,key_value_3[k]);
k++;
}
i++;
break;
}
}
}
while(1)
{key_value=KeyScan();
if(key_value!=ok)continue;
else
{tem_data_set=1000*key_value_3[0]+100*key_value_3[1]+10*key_value_3[2];
TR0=1;
TR1=1;
EA=1;
break;
}
}
}
else
{TR0=1;
TR1=1;
EA=1;
return;
}
}
/****************************计数器0中断服务程序****************************/
void count0() interrupt 1
{int con_data_8[8];
int con_data=0;
uchar i;
TR0=0;
TR1=0;
for(i=0;i<8;i++)con_data_8[i]=AD574();
con_data=filtering(con_data_8);
tem_data=LinearProcessing(con_data);
E_nSUB1=E_n;
E_nSUB2=E_nSUB1;
E_n=tem_data_set-tem_data;
if(E_n>=500)
{power_on;
TR0=1;
tem_refresh(tem_data);
return;
}
else
{PID();
if(U_n==0)
{power_off;
TR0=1;
tem_refresh(tem_data);
return;
}
else
{TH1=0xFF;
TL1=256-U_n;
TR0=1;
TR1=1;
power_on;
tem_refresh(tem_data);
}
}
return;
}
/****************************计数器1中断服务程序****************************/
void count1() interrupt 3
{TR1=0;
power_off;
}
/***************************按键扫描子程序*********************************/
unsigned char KeyScan(void)
{void delay10ms(unsigned char time);
unsigned char key;
P1=0xff;
P1_0=0;
if(P1_4==0)
{delay10ms(10);
if(P1_4==0)
{key=0;
while(P1_4==0);
return(key);
}
}
else if(P1_5==0)
{delay10ms(10);
if(P1_5==0)
{key=1;
while(P1_5==0);
return(key);
}
}
else if(P1_6==0)
{delay10ms(10);
if(P1_6==0)
{key=2;
while(P1_6==0);
return(key);
}
}
else ;
P1_0=1;
P1_1=0;
if(P1_4==0)
{delay10ms(10);
if(P1_4==0)
{key=3;
while(P1_4==0);
return(key);
}
}
else if(P1_5==0)
{delay10ms(10);
if(P1_5==0)
{key=4;
while(P1_5==0);
return(key);
}
}
else if(P1_6==0)
{delay10ms(10);
if(P1_6==0)
{key=5;
while(P1_6==0);
return(key);
}
}
else ;
P1_1=1;
P1_2=0;
if(P1_4==0)
{delay10ms(10);
if(P1_4==0)
{key=6;
while(P1_4==0);
return(key);
}
}
else if(P1_5==0)
{delay10ms(10);
if(P1_5==0)
{key=7;
while(P1_5==0);
return(key);
}
}
else if(P1_6==0)
{delay10ms(10);
if(P1_6==0)
{key=8;
while(P1_6==0);
return(key);
}
}
else ;
P1_2=1;
P1_3=0;
if(P1_4==0)
{delay10ms(10);
if(P1_4==0)
{key=9;
while(P1_4==0);
return(key);
}
}
else if(P1_5==0)
{delay10ms(10);
if(P1_5==0)
{key=set_tem;
while(P1_5==0);
return(key);
}
}
else if(P1_6==0)
{delay10ms(10);
if(P1_6==0)
{key=ok;
while(P1_6==0);
return(key);
}
}
else return(no_key);
}
/***********************延时程序*************************************/
void delay10ms(unsigned char time)
{
unsigned char i;
while(time--)
{
for(i=0;i<120;i++) ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -