都40+的人了,还在学单片机,很多问题的理解能力都不比年轻人,自己设计了一个3路测温程序,用的STC12C5A60S2单片机,10位AD转换值,思路是先校准100℃和0℃的值求出K值,再来算对应的温度,问题是现在只显示0.0℃。传感器是PT100。请大神帮看一下程序的问题在哪里,尽量解释的清楚些,谢谢!
************************************************************************************
#include <STC12C5A60S2.H>
#define uchar unsigned char
#define uint unsigned int
sbit AB_164=P0^6;
sbit CLK_164=P0^7;
sbit I2C_SDA=P3^7;
sbit I2C_SCL=P3^6;
uchar call_lop;
uint xdata MAX_T;
float xdata TE_A;
float xdata TE_B;
float xdata TE_C;
uint xdata A_0;
uint xdata A_100;
float xdata A_k=0;
uint xdata B_0;
uint xdata B_100;
float xdata B_k=0;
uint xdata C_0;
uint xdata C_100;
float xdata C_k=0;
sbit KEY=P4^5;
uchar code LED_TAB[7]={0x1f,0x2f,0x37,0x3b,0x3d,0x3e,0x3f};//数码管7个位
uchar code BCD_TAB[11]={0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x19,0xff};//0~9,0XFF是关闭
uchar code CCBD_TAB[10]={0x31,0xFD,0x91,0x61,0xF5,0x11,0xC1,0x63,0xe3};
// P - H E R A B C L
uchar xdata DISP_SAVE[6]={0X03,0X03,0X03,0X03,0X03,0Xff};//要送显的数据寄存器
/*****************************************************************************************************
****************短暂延时****************************************************************/
void delay1(uchar tt)
{
while(tt>0)
tt--;
}
/*********************************************************************************
**********74hc164操作************************************************************/
void write_164(uchar lx)
{
uchar i;
uchar j=0;
j=lx;
for(i=0;i<8;i++)
{
CLK_164=0;
if((j&0x01)==0x01)
{
AB_164=1;
}
else
{
AB_164=0;
}
delay1(10);
CLK_164=1;
j=j>>1;
delay1(5);
}
}
void disp_all(void)
{
uchar i;
uchar j;
for(j=0;j<10;j++)
{
for(i=0;i<6;i++)
{
P0=0X3F;
write_164(DISP_SAVE[i]);//将要显示的数据写入164中
P0=LED_TAB[i];//选择要显示的位
delay1(300);
P0=0X3F;
}
}
write_164(0xff);
}
/***************************************************************************
*******24C04***************************************************************/
void MI2C_START(void)//I2C开始信号
{
I2C_SDA=1;
delay1(4);
I2C_SCL=1;
delay1(4);
I2C_SDA=0;
delay1(4);
I2C_SCL=0;
}
void MI2C_STOP(void)//I2C停止信号
{
I2C_SDA=0;
delay1(4);
I2C_SCL=1;
delay1(4);
I2C_SDA=1;
delay1(4);
I2C_SCL=0;
}
void MI2C_R_ACK(void)//应答
{
uchar i;
I2C_SCL=1;
delay1(4);
while((I2C_SDA==1)&&(i<250))
i++;
I2C_SCL=0;
delay1(4);
}
void MI2C_UN_ACK(void)//主机不应答
{
I2C_SDA=1;
delay1(4);
I2C_SCL=1;
delay1(4);
I2C_SCL=0;
}
void MI2C_WRITE(uchar I2C_data)//写一个字节
{
uchar i,j;
j=I2C_data;//0xA0
for(i=0;i<8;i++)
{
I2C_SCL=0;
delay1(4);
if((j&0X80)==0X80)//从最高位开始写
{
I2C_SDA=1;//如果欲写入数据为1,就将数据线置1
}
else
{
I2C_SDA=0;//如果欲写入数据为0,就将数据线写0
}
delay1(4);
I2C_SCL=1;//时钟线做一个上升沿,将一位数据写入
delay1(4);
j=j<<1; //数据左移一位,将下次要写入的位数据移到最高位
}
I2C_SCL=0; //将SCL=0,以准备通过上升沿将数据写入
}
uchar MI2C_READ(void)
{
uchar k; //1个字节要分8次读出,需要定义一个寄存器用来计数
uchar t=0; //定义一个寄存器用保存读出数据
for(k=0;k<8;k++) //做一个8次的循环,每次读入1位,需要读8次
{
t=t<<1; //数据左移一位,空出最低位以准备保存读入的一位数据
I2C_SDA=1; //将SDA写1准备读
I2C_SCL=1; //将SCL=1,做个上升沿准备读一位数据
delay1(5); //略做延时
if(I2C_SDA==1) //读一位数据,并判断
{
t=t|0x01; //如果读入数据为1,就将接收缓冲区最低一位置1
}
else
{
t=t&0xfe; //如果读入数据为0,就将接收缓冲区最低一位写0
}
I2C_SCL=0; //SCL恢复为0,结束一位数据读操作
delay1(5); //略做延时
}
return t; //将读入的一个字节返回
}
uchar I2C_READ_ONE(uchar slv_addr,uchar data_addr)//I2C读数据
{
uchar i=0;
MI2C_START();//开始
MI2C_WRITE(slv_addr);//写I2C地址
delay1(20);
MI2C_R_ACK();//应答
MI2C_WRITE(data_addr);//写数据地址
MI2C_R_ACK();//应答
MI2C_START();//开始
MI2C_WRITE(slv_addr|0x01);
MI2C_R_ACK();//应答
i=MI2C_READ();//读取的数据给i
MI2C_UN_ACK();//主机不应答(结束读取)
MI2C_STOP();//停止
return i;
}
void I2C_WRITE_ONE(uchar slv_addr,uchar data_addr,uchar A_data)//I2C写数据
{
uchar i=0;
i=A_data;
MI2C_START();//开始
MI2C_WRITE(slv_addr);//写I2C地址
MI2C_R_ACK();//应答
MI2C_WRITE(data_addr);//写数据地址
MI2C_R_ACK();//应答
MI2C_WRITE(i);//写数据
MI2C_R_ACK();//应答
MI2C_STOP();//停止
delay1(200);
}
/**************************************************************************************
**********AD转换**********************************************************************/
void AD_init(void)
{
P1ASF=0xe0;//将P1.5,P1.6,P1.7做AD口使用
ADC_RES=0;
ADC_RESL=0;
ADC_CONTR=0x80;//将AD转换控制寄存器电源打开,360个时钟周期转换一次,准备转换
delay1(50);//必须要延时
}
uint ADC_GET(unsigned char channel)//channel是通道选择
{
uint temp=0;
ADC_CONTR=0x88|channel;//打开选通通道准备转换
delay1(50);
while(!(ADC_CONTR&0x10));//判断ADC_FLAG是否为1,如果是1,转换结束
ADC_CONTR&=0xe7;
temp=(ADC_RES*4)+ADC_RESL;
return temp;
}
/*****************************************************************************
****************************************************************************/
float AD_work(unsigned char channel)
{
uint AD_val;
float tmp;
AD_val=ADC_GET(channel);
if(channel==0x07)//A相温度地址
{
if(AD_val>=A_0)//
{
tmp=(AD_val-A_0)*A_k;
}
}
else if(channel==0x06)//B相温度
{
if(AD_val>=B_0)
{
tmp=(AD_val-B_0)*B_k;
}
else if(channel==0x05)//C相温度
{
if(AD_val>=C_0)
{
tmp=(AD_val-C_0)*C_k;
}
}
}
return tmp;
}
uchar GET_KEY(void)//按键扫描函数
{
uchar i=0;
uchar j=0;
uchar k=10;
for(i=0;i<6;i++)//循环6次,依次显示6个数码管位
{
P0=0X3F;//将P0口的164AB脚和CLK脚置0,数码管位全置1
P0=LED_TAB[i];//顺序打开数码管位
delay1(500);
if(KEY==0)//有键按下
{
delay1(250);//稍做延时
if(KEY==0)//再次判断有按键按下
{
disp_all();
P0=0X3F;
P0=LED_TAB[i];
delay1(500);
}
while(KEY==0);
k=i;
}
}
return k;
}
void Tiaoshichengxu(void)
{
uchar i=0;
uchar tt=0;
uchar call_lop=0;
uint tmp1=0;
uchar tmp2=0;
if(P20==0)
{
do
{
tt=GET_KEY();
switch(tt)
{
case 0:if(call_lop<5)
{
call_lop++;
}
else
{
call_lop=0;
}break;
case 1:if(call_lop==0)
{
tmp1=ADC_GET(0x07);//将A相0℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//截取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x02,tmp2);//AD转换值低8位存入24c04的0x02地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
delay1(20);
I2C_WRITE_ONE(0xa0,0x03,tmp2);//AD转换值高2位存入24c04的0x03地址中
delay1(200);
delay1(200);
}
else if(call_lop==1)
{
tmp1=ADC_GET(0x06);//将B相0℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x04,tmp2);//AD转换值低8位存入24c04的0x04地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x05,tmp2);//AD转换值高2位存入24c04的0x05地址中
delay1(200);
delay1(200);
}
else if(call_lop==2)
{
tmp1=ADC_GET(0x05);//将C相0℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x06,tmp2);//AD转换值低8位存入24c04的0x06地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x07,tmp2);//AD转换值高2位存入24c04的0x07地址中
delay1(200);
delay1(200);
}
else if(call_lop==3)
{
tmp1=ADC_GET(0x07);//将A相100℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x08,tmp2);//AD转换值低8位存入24c04的0x08地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
delay1(20);
I2C_WRITE_ONE(0xa0,0x09,tmp2);//AD转换值高2位存入24c04的0x09地址中
delay1(200);
delay1(200);
}
else if(call_lop==4)
{
tmp1=ADC_GET(0x06);//将B相100℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x0a,tmp2);//AD转换值低8位存入24c04的0x0a地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
delay1(20);
I2C_WRITE_ONE(0xa0,0x0b,tmp2);//AD转换值高2位存入24c04的0x0b地址中
delay1(200);
delay1(200);
}
else if(call_lop==5)
{
tmp1=ADC_GET(0x05);//将C相100℃的温度赋值给tmp1
delay1(20);
tmp2=tmp1&0x00ff;//取AD转换值低8位赋值给tmp2
I2C_WRITE_ONE(0xa0,0x0C,tmp2);//AD转换值低8位存入24c04的0x0c地址中
delay1(200);
delay1(200);
tmp2=(tmp1&0xff00)>>8;//取AD转换值高2位赋值给tmp2
delay1(20);
I2C_WRITE_ONE(0xa0,0x0D,tmp2);//AD转换值高2位存入24c04的0x0d地址中
delay1(200);
delay1(200);
}
break;
}
if(call_lop==0)
{
DISP_SAVE[0]=CCBD_TAB[8];//相位显示L
DISP_SAVE[1]=CCBD_TAB[5];//百位显示A
DISP_SAVE[2]=BCD_TAB[0];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
else if(call_lop==1)
{
DISP_SAVE[0]=CCBD_TAB[8];//相位显示L
DISP_SAVE[1]=CCBD_TAB[6];//百位显示B
DISP_SAVE[2]=BCD_TAB[0];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
else if(call_lop==2)
{
DISP_SAVE[0]=CCBD_TAB[8];//相位显示L
DISP_SAVE[1]=CCBD_TAB[7];//百位显示C
DISP_SAVE[2]=BCD_TAB[0];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
else if(call_lop==3)
{
DISP_SAVE[0]=CCBD_TAB[2];//相位显示H
DISP_SAVE[1]=CCBD_TAB[5];//百位显示A
DISP_SAVE[2]=BCD_TAB[1];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
else if(call_lop==4)
{
DISP_SAVE[0]=CCBD_TAB[2];//相位显示H
DISP_SAVE[1]=CCBD_TAB[6];//百位显示B
DISP_SAVE[2]=BCD_TAB[1];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
else if(call_lop==5)
{
DISP_SAVE[0]=CCBD_TAB[2];//相位显示H
DISP_SAVE[1]=CCBD_TAB[7];//百位显示C
DISP_SAVE[2]=BCD_TAB[1];//十位显示0
DISP_SAVE[3]=BCD_TAB[0];//个位显示0
DISP_SAVE[4]=BCD_TAB[0];//小数位显示0
}
disp_all();
}
while(P20==0);
}
}
void READ_JIAOZHUN(void)
{
uchar temp1;
uint temp2;
temp1=0;
temp2=0;
temp1=I2C_READ_ONE(0xa0,0x03);//读A相0℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x02);//读A相0℃转换值低8位给temp1
A_0=(temp2<<8)|temp1;//合并成10位数据给A_0
temp1=I2C_READ_ONE(0xa0,0x09);//读A相100℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x08);//读A相100℃转换值低8位给temp1
A_100=(temp2<<8)|temp1;//合并成10位数据给A_100
temp2=A_100-A_0;
A_k=100.0/temp2;//求出K值
temp1=0;//清零
temp2=0;//清零
temp1=I2C_READ_ONE(0xa0,0x05);//读B相0℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x04);//读B相0℃转换值低8位给temp1
B_0=(temp2<<8)|temp1;//合并成10位数据给B_0
temp1=I2C_READ_ONE(0xa0,0x0b);//读B相100℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x0a);//读B相100℃转换值低8位给temp1
B_100=(temp2<<8)|temp1;//合并成10位数据给B_100
temp2=B_100-B_0;
B_k=100.0/temp2;
temp1=0;//清零
temp2=0;//清零
temp1=I2C_READ_ONE(0xa0,0x07);//读C相0℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x06);//读C相0℃转换值低8位给temp1
C_0=(temp2<<8)|temp1;//合并成10位数据给C_0
temp1=I2C_READ_ONE(0xa0,0x0D);//读C相100℃转换值高2位给temp1
temp2=temp1;//赋值给temp2
temp1=I2C_READ_ONE(0xa0,0x0C);//读C相100℃转换值低8位给temp1
C_100=(temp2<<8)|temp1;//合并成10位数据给C_100
temp2=C_100-C_0;
C_k=100.0/temp2;
}
void FDshu_disp(float ut)
{
uchar temp1=0;
uchar temp2=0;
uchar temp3=0;
uchar temp4=0;
uint lt;
lt=ut;
temp1=lt/100;
if(temp1==0)
{
temp1=10;
}
temp2=(lt%100)/10;
if(temp1==10&&temp2==0)
{
temp2=10;
}
temp3=lt%10;
lt=ut*10;
temp4=lt%10;
DISP_SAVE[1]=BCD_TAB[temp1];
DISP_SAVE[2]=BCD_TAB[temp2];
DISP_SAVE[3]=BCD_TAB[temp3]&0xFE;//0xfe显示小数点
DISP_SAVE[4]=BCD_TAB[temp4];
disp_all();
}
void timer0() interrupt 1
{
MAX_T++;
if(MAX_T>6000)
{
MAX_T=0;
}
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
}
void main(void)
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA =1; //开总中断
ET0 =1; //开定时器0中断
AD_init();
write_164(0XFF);//74hc164初始化
while(1)
{
Tiaoshichengxu();
READ_JIAOZHUN();
TE_A=AD_work(0x07);//A相温度
TE_B=AD_work(0x06);//B相温度
TE_C=AD_work(0x05);//C相温度
if(MAX_T<2000)
{
DISP_SAVE[0]=CCBD_TAB[5];//相位显示A
FDshu_disp(TE_A);
disp_all();
}
else if((MAX_T>=2000)&&(MAX_T<4000))
{
DISP_SAVE[0]=CCBD_TAB[6];
FDshu_disp(TE_B);
disp_all();
}
else if(MAX_T>=4000)
{
DISP_SAVE[0]=CCBD_TAB[7];
FDshu_disp(TE_C);
disp_all();
}
}
}
|