#include<reg52.h>
#include<intrins.h>
#include<math.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcdrs=P0^6;
sbit lcden=P0^7; //LCD引脚定义
sbit AD7705_DRDY=P1^0; // AD7705 data ready
sbit AD7705_DATA=P1^1; // AD7705 input data & output data
sbit AD7705_RESET=P1^2; // AD7705 RESET
sbit AD7705_CS=P1^3; // AD7705 CS
sbit AD7705_CLK=P1^4; // AD7705 CLK
sbit MAX541_DIN=P1^5;
sbit MAX541_SCLK=P1^6;
sbit MAX541_CS=P1^7; //MAX541引脚定义
void delay(uint k);
void MAX541_init(); //MAX541初始化
void MAX541_SPIWrite(int temp); //单片机向MAX541写16bits数据
int VoltToData(float out_volt); //将电压值转换为对应的16bits数字量
void SetMAX541(float temp); //设置MAX541输出电压
float T_Voltage;
uchar H_Data,L_Data;
void AD7705_init();
AD7705_Read (); //读取采样数值
void AD7705_Write_Reg(uchar Data_byte);
uchar AD7705_Read_Reg(); //读寄存器,包括2个字节
void lcd_init();
void lcd_write_data(char dat);
void lcd_write_com(char com);
void lcd_disp(uchar a);
uchar tab_key[6];
uchar code tab[]="0123456789";
uchar n,key;
uchar x1,x2,x3,x4,x5,x6;
long temp;
void i_set();
typedef struct
{
double dState; // Last position input
double iState; // Integrator state
double iMax, iMin; // Maximum and minimum allowable integrator state
double iGain; // integral gain
double pGain; // proportional gain
double dGain; // derivative gain
} SPid;
double UpdatePID(SPid * pid, double error, double position)
{
double pTerm, dTerm, iTerm; // calculate the proportional term
pTerm = pid->pGain * error; // calculate the integral state with appropriate limiting
pid->iState += error;
if (pid->iState > pid->iMax) pid->iState = pid->iMax;
else if (pid->iState < pid->iMin) pid->iState = pid->iMin;
iTerm = pid->iGain * pid->iState; // calculate the integral term
dTerm = pid->dGain * (position - pid->dState);
pid->dState = position;
return pTerm + iTerm - dTerm;
}
//MAX541初始化
void MAX541_init()
{
MAX541_DIN=0;
MAX541_CS=0;
MAX541_SCLK=0;
}
//单片机向MAX541写16bits数据
void MAX541_SPIWrite(int temp)
{
uint i;
for(i=0;i<16;i++)
{
MAX541_DIN=(bit)(temp&0x8000);
MAX541_SCLK=0;
temp<<=1;
_nop_();
MAX541_SCLK=1;
_nop_();
}
}
//将电压值转换为对应的16bits数字量
int VoltToData(float out_volt)
{
int temp;
temp=(int)(out_volt*65536/2.497);
return(temp&0xffff);
}
//设置MAX541输出函数
void SetMAX541(float volt)
{
int Data;
Data = VoltToData(volt);
MAX541_CS=0;
MAX541_SPIWrite(Data);
_nop_();
_nop_();
MAX541_CS=1;
_nop_();
_nop_();
}
//AD7705初始化
void AD7705_init()
{
AD7705_Write_Reg(0x20); //0,010,0,0,00 默认写0,时钟寄存器,写操作,正常工作模式,通道AIN1
AD7705_Write_Reg(0x0a); //000,0,0,000 默认写0,主时钟不禁止,2.4576时钟不分频,20Hz输出更新率、5.24Hz滤波器-3dB截止频率
AD7705_Write_Reg(0x10); //0,001,0,0,00 默认写0,设置寄存器,写操作,正常工作模式,通道AIN1
AD7705_Write_Reg(0x44); //01,000,1,0,0 自校准模式,1倍增益,单极性工作,片内缓冲器短路、调制器和滤波器开始处理数据
}
//AD7705读16bits数据
AD7705_Read()
{
AD7705_Write_Reg(0x38);
H_Data=AD7705_Read_Reg();
L_Data=AD7705_Read_Reg();
T_Voltage=(float)H_Data;
T_Voltage=T_Voltage*256;
T_Voltage=T_Voltage+(float)L_Data;
return(T_Voltage);
}
//AD7705写寄存器
void AD7705_Write_Reg(uchar Data_byte)
{
uchar i;
AD7705_CS=0;
AD7705_CLK=1;
_nop_();
_nop_();
for(i=0;i<8;i++)
{
AD7705_DATA=(bit)(Data_byte&0x80);
AD7705_CLK=0;
_nop_();
_nop_();
_nop_();
AD7705_CLK=1;
Data_byte<<=1;
}
_nop_();
AD7705_CS = 1;
}
//AD7705读寄存器
uchar AD7705_Read_Reg()
{
uchar i,Data_read;
AD7705_CS=0;
AD7705_CLK=1;
_nop_();
for(i=0;i<8;i++)
{
AD7705_CLK=0;
_nop_();
_nop_();
Data_read<<= 1;
Data_read|=(uchar)AD7705_DATA;
_nop_();
_nop_();
AD7705_CLK=1;
_nop_();
_nop_();
}
_nop_();
AD7705_CS=1;
AD7705_DRDY=1;
return(Data_read);
}
//延时
void delay(uint k)
{
uint i,j;
for(i=k;i>0;i--)
for(j=110;j>0;j--);
}
//LCD初始化
void lcd_init()
{
lcden=0;
lcd_write_com(0x38); //设置显示模式:16X2,5X7,8位数据接口
lcd_write_com(0x0c); //开显示,显示光标,光标闪烁
lcd_write_com(0x06); //读写一个字符后,地址指针及光标加一,且光标加一整屏显示不移动
lcd_write_com(0x01); //清屏
lcd_write_com(0x80); //设置光标指针
}
//写命令
void lcd_write_com(uchar com)
{
lcdrs=0; //低电平写命令
P2=com; //写入命令
delay(3); //延时约3ms
lcden=1; //LCD使能端置高电平
delay(3); //延时约3ms
lcden=0; //LCD使能端拉低电平
}
//写数据
void lcd_write_data(uchar dat)
{
lcdrs=1; //低电平写数据
P2=dat; //写入命令
delay(3); //延时约3ms
lcden=1; //LCD使能端置高电平
delay(3); //延时约5ms
lcden=0; //LCD使能端拉低电平
}
//LCD显示
void lcd_disp(uchar a)
{
lcd_write_data(tab[a]);
}
//电流、电压设置
void i_set(float dianliu)
{
float dianya;
dianya=10*dianliu;
SetMAX541(dianya);
}
void main()
{
uint a,c,d,i;
long b;
float dianya;
lcd_init();
MAX541_init();
AD7705_init();
for(i=0;i<11;i++)
{
i_set(10+i);
delay(500);
}
while(1)
{
i_set(50);
for(i=0;i<10;i++)
{
while(AD7705_DRDY);
a=AD7705_Read();
d=a*2.497/65535;
if(d==dianya) {dianya=dianya;}
else {UpdatePID;}
}
while(AD7705_DRDY);
a=AD7705_Read();
b=a*2.497*100000/65535; //结果与a、2.497、100000三个乘数的顺序相关,原因待查
x1= b/100000;
x2=(b-x1*100000)/10000;
x3=(b-x1*100000-x2*10000)/1000;
x4=(b-x1*100000-x2*10000-x3*1000)/100;
x5=(b-x1*100000-x2*10000-x3*1000-x4*100)/10; //6位数组时,b-x1*100000-x2*10000-x3*1000-x4*100-x5*10显示乱码,原因待查
x6=(b-x1*100000-x2*10000-x3*1000-x4*100-x5*10)%10; //6位数组时,SetMAX541(1.865),显示18xxyz,xx乱码,原因待查
tab_key[0]=x1;
tab_key[1]=x2;
tab_key[2]=x3;
tab_key[3]=x4;
tab_key[4]=x5;
tab_key[5]=x6;
lcd_write_com(0x80);
for(i=0;i<6;i++)
{
c=tab_key[i];
lcd_disp(c);
}
delay(500);
}
}
评论2