📄 tempdisplay.c
字号:
/*-----------------------------------------------------------------------
;MAX1169
-------------------------------------------------------------------------*/
// I2C通用驱动AD程序
SomeNOP(void)
{ //uchar ij=255;
// while(ij--){
_nop_();_nop_();_nop_();_nop_();}
//}
/*--------------------------------------------------------------------------------
调用方式:void I2CStart(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStart(void)
{
//EA=0;
SDA=1; //SomeNOP();//SCL保持高,SDA从高到低一次跳变,I2C通信开始
SCL=1; SomeNOP();
SDA=0; SomeNOP();
SCL=0; SomeNOP();
}
/*--------------------------------------------------------------------------------
调用方式:void I2CStop(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStop(void)
{
//SCL=0;
SDA=0; //SomeNOP(); //SCL保持高,SDA从低到高一次跳变,I2C通信停止
SCL=1; SomeNOP();
SDA=1; SomeNOP();
SCL=0; SomeNOP();
//EA=1;
}
/*--------------------------------------------------------------------------------
调用方式:I2CAck(void) 2005/12/10
函数说明:私有函数,I2C专用,等待从器件接收方的应答
ACK BY
---------------------------------------------------------------------------------*/
WaitAck(void)
{
unsigned char errtime=255;//因故障接收方无ACK(ACK对应SDA=0),超时值为255。
SDA=1;
//SDA=0;
SCL=1;
SystemError=0x10;
while(SDA)
{ errtime--;
if(!errtime)
{ I2CStop();
SystemError=0x11; //出错后给全局变量赋值
return;
}
};
SCL=0;
_nop_();
}
/*--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2005/12/10
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
---------------------------------------------------------------------------------*/
void SendAck(void)
{
SDA=0; SomeNOP(); //数据线保持低,时钟线发生一次从高低的跳变 发送一个应答信号
SCL=1; SomeNOP();
SCL=0;
}
/*--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2005/12/10
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
--------------------------------------------------------------------------------*/
void SendNotAck(void)
{
SDA=1; SomeNOP(); //数据线保持高,时钟线发生一次从高低的跳变 没有应答
SCL=1; SomeNOP();
SCL=0;
}
/*--------------------------------------------------------------------------------
调用方式:void I2CSend(uchar ch) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CSendByte(uchar ch) //write device
{
unsigned char i=8;
while (i--)
{
SCL=0;_nop_();
SDA=(bit)(ch&0x80); ch<<=1; SomeNOP(); //SCK下降沿发送数据
SCL=1; SomeNOP();
}
SCL=0;
}
/*--------------------------------------------------------------------------------
调用方式:uchar I2CReceive(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
uchar I2CReceiveByte(void) //read device
{
unsigned char i=8,datatmp=0;
SDA=1; //释放总线
while(i--)
{
datatmp<<=1;
SCL=0;SomeNOP();
SCL=1;SomeNOP(); //SCL做一次从低到高的跳变 可以接收数据
datatmp|=SDA;
};
SCL=0;
return datatmp;
}
/*--------------------------------------------------------------------------------
调用方式:uint ADC(void) 2005/12/10
函数说明:用于max1169AD转换测试(转换前是否一定要进行“HS MODE”设置?N,上电即默认为FS)
---------------------------------------------------------------------------------*/
uint ADC(uchar addr)
{
uint adc_data;
uchar nt1;
I2CStart();
nt1=(addr<<1)|0x61;
I2CSendByte(nt1); //写入器件地址,并设置器件为R模式
WaitAck(); //写入地址后,器件向主机发送ACK。
// SCL=0; //用延时的方式等待SCK变高(转换时SCK被max1169置低)
// SomeNOP();
// while(!SCL); //由于转换过程很短,转换过程中SCL保持低,转换结束后slave释放对SCL控制权,但SCL仍然为0
adc_data=I2CReceiveByte(); //read d15~d8
SendAck();
adc_data<<=8;
adc_data=adc_data|I2CReceiveByte(); //read d7~d0
SendNotAck();
I2CStop();
return(adc_data);
}
void delay(uchar x)
{ uchar j;
for(j=0;j<x;j++)
_nop_();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------------------------------------------------------------------------------------------
;中位值平均滤波程序
函数说明: 相当于“中位值滤波法”+“算术平均滤波法”连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个
数据的算术平均值
-----------------------------------------------------------------------------------------------------------*/
float filter()
{
uchar count,i,j,k;
uint ch_adc[N];
uint temp;
float sum=0.0;
for (count=0;count<N;count++)
{
ch_adc[count]=ADC(0x6);
delay(80);
}
_nop_();
for (i=0;i<N-1;i++)
{
k = i;
for (j=i+1;j<N;j++)
if (ch_adc[j]<ch_adc[k]) k=j;
temp = ch_adc[k]; ch_adc[k] = ch_adc[i]; ch_adc[i] = temp; //选择法进行排序
}
for(count=1;count<N-1;count++)
sum += (float)ch_adc[count];
return (float)(sum/(N-2));
}
/*-----------------------------------------------------------------------------------------------------------
;温度转化程序
函数说明:30~40度的温度曲线
-----------------------------------------------------------------------------------------------------------*/
double temptrans(float x)
{
double y;
y=a1*x*x*x+a2*x*x+a3*x+a4;
return y;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------------------------------------------------------------------------------------------
;MAX5541控制程序
-----------------------------------------------------------------------------------------------------------*/
/*void delayms(uchar x)
{
uchar i;
for(i=0;i<x;i++);
}*/
void ad5541_ck(void){
SCLK=0;_nop_();_nop_();
SCLK=1;_nop_();_nop_();
}
void ad5541(uint da1){
uchar r=16;
uint ch;
ch=da1;
DA_CS=1;
//dacs2=1;
ad5541_ck();
DA_CS=0;
while (r--){
DIN=ch&0x8000;
ad5541_ck();
ch<<=1;
}
DA_CS=1;
_nop_();_nop_();_nop_();
}
/*----------------------------------------------------------------------------------------------------
常规PID控制炉温程序(只用到了PI部分)
-----------------------------------------------------------------------------------------------------*/
signed int pid(struct PIDpara *sp)
{
signed int ek = 0,duk = 0,uk = 0; //ek为当次采样比较误差,duk为pid运算结果
uint yk;
yk = (uint)filter() + 9600;
ek = sp->rk - yk;
duk = (sp->kp + sp->ki) * ek - sp->kp * sp->ek1;
uk = sp->uk1 + duk;
sp->ek1 = ek; //e(k)数据更新,给下一次PID运算使用
sp->uk1 = uk; //u(k)数据更新
return(uk); //输出给函数返回值
}
// -----------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------------------------------------
;温控系统主程序
-----------------------------------------------------------------------------------------------------------*/
main()
{
uint DA_i=0;
uint ukout=0;
uint counter = 0;
//uint rk = 19316; //40度
//uint rk = 20000; //50度
uint rk = 28600; //60度
//uint rk = 34727; //70度
//uint rk = 38674; //80度
uint yk;
auto struct PIDpara *p1,data1={3.14,0.065,28600,0,0};
auto struct PIDpara *p2,data2={3.14,0,28600,0,0};
TMOD = 0x01; //采用定时器0方式1
TH0 = -100000/256; //定时器预置计数初值
TL0 = -100000%256;
EA = 1; //CPU开中断
ET0 = 1; //开C/T中断
TR0 = 1; //启动C/T
while(1)
{
// _nop_();
if(!(counter++ % 10))
{
disp();
}
if(!(counter++ % 30)) //每隔3s做一次运算
{
if(rk - yk < 0x1420) //积分分离PID,当温度大于10度仅为P控制器,当温度小于10度加入积分
{
p1 = &data1; //PID参数赋初值
ukout = Umax - pid(p1);
}
else
{
p2 = &data2;
ukout = Umax - pid(p2);
}
ad5541(ukout);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -