简易数字温度计制作(不用单片机)

2024-11-02 08:06:44
推荐回答(1个)
回答1:

#include
#include
#define uchar unsigned char
#define uint unsigned int

sbit CLK_164=P0^4;//数码管显示控制芯片74LS164时钟引脚
sbit DTAT_164=P0^5;//数码管显示控制芯片74LS164 AB

sbit CS=P1^5;//AD转换
sbit CLK=P1^2;//AD转换
sbit DIN=P1^3;//AD转换
sbit DOUT=P1^4;//AD转换

sbit FMQ=P3^6;//报警

sbit KEY_PIN=P3^4;//按键

sbit sda=P2^5; //DS1307
sbit sclk=P2^4;//DS1307

uchar LED_TAB[7]={0x0e,0x0d,0x0b,0x07,0x0f}; //0,1,2,3位依次显示,0x0f为全灭
uchar DISP_SAVE[7];
uchar BCD_TAB[11]={0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x19,0xff};//数码管显示的值:0,1,2,3,4,5,6,7,8,9;oxff为不显示值
//uchar CCBD_TAB[10]={0x31,0xFD,0x91,0x61,0xF5,0x11,0xC1,0x63,0xe3};
uchar D1307[7];
uchar cotot=0;
uchar temp5,count_1,temp6;
uchar JP1=0;
uint temper;

void delay(uint tt) //延迟函数
{
uchar i;
for(;tt>0;tt--)
{
for(i=0;i<2;i++);
}
}
/*********************************************************************************************/

/***************************************************************************
** 起始信号DS1307
*****************************************************************************/
void iicstart(void)
{
sclk=0; //总线放空,以便更改总线数据
sda=1; //发送I2C总线起始条件的数据信号1以便总线使能时产生下降沿
sclk=1; //发送I2C总线起始条件的时钟信号
delay(1);
sda=0; //产生下降沿 总线传输开始
delay(1);
sclk=0; //时钟线从高到低一次跳变,总线放空 准备传输数据
}
/***************************************************************************
** 结束信号DS1307
*******************************************************************************/
void iicstop(void)
{
sclk=0; //发送I2C总线时钟信号放空
sda=0; //发送I2C总线停止条件的数据信号0以便产生上升沿
delay(1);
sclk=1; //时钟线从低到高一次跳变 总线 使能
sda=1; //发送I2C总线数据信号产生上升沿 终止传送
delay(1);
sclk=0; //发送I2C总线时钟信号放空

}
/**********************************************************************************
** 检测应答信号DS1307
***********************************************************************************/
uchar upcheck(void)
{
uchar i;
sclk=0;
sda=1; //数据线升高,以便捕捉相应信号,(相应信号:拉低数据线)
sclk=1; // 主机放出一脉冲,等待捕捉相应信号
if(sda==1)
i=0;
else
{
i=1;
count_1++;
}
sclk=0;//无论传送是否正确,都需放空总线,以备后用
return(i);//i为应答信号标志位
}
/*******************************************************************************
** 发送应答信号和非应答信号DS1307
*********************************************************************************/
void sendcheck(void)//应答信号
{
sclk=0;
sda=0; //数据线保持拉低,时钟线发生一次从高低的跳变 发送一个应答信号
sclk=1;
delay(1);
sclk=0;
}
void senducheck(void)//非应答信号
{
sclk=0;
sda=1; //数据线保持高,时钟线发生一次从高低的跳变 没有应答
sclk=1;
delay(1);
sclk=0;
}
/*********************************************************************************
**写入一个字节
**字节内容:addr
*******************************************************************************/
void writeiic(uchar addr)
{
uchar temp1,i;
temp1=addr;
sclk=0; //总线放空
for(i=0;i<8;i++) //发送八位
{
if((temp1&0x80)==0)//提取高位的数据,由高位到低位逐步提出字节位,发送到总线上
sda=0;
else
sda=1;

sclk=1; //总线使能,发送总线数据
delay(2);
sclk=0; //总线1位传送完成,总线放空
temp1=temp1<<1;//左循环以便输出下一位
}
temp5=upcheck();//检测应答信号

}
/******************************************************************************************
**读取一个字节
**读取内容:addr
**********************************************************************************************/

uchar read(uchar addr)
{
uchar temp1,temp2,i;
temp1=addr;
sclk=0;
for(i=0;i<8;i++)
{
if((temp1&0x80)==0)//提取高位的数据,由高位到低位逐步提出字节位,发送到总线上
sda=0;
else
sda=1;

sclk=1;
delay(2);
sclk=0;
temp1=temp1<<1;
}
temp5=upcheck();//检测应答信号

sclk=0; //总线放空
sda=1;
for(i=0;i<8;i++) //读入八个位
{
temp2=temp2<<1; // 读入数据左循环
sclk=1; //时钟做一次从低到高的跳变 可以接收一位数据
delay(2);
if(sda==1)
temp2=temp2|0x01; // 将数据编入变量temp2

sclk=0; //总线放空
}
senducheck();//发送非应答信号
return(temp2); //反馈接收到的信息
}

void read1(uchar addr,uchar cc,uchar *chn)
{
uchar temp1,temp2,temp3,i;
temp1=addr;
temp3=cc;
/////////////////////////////////////////////
sclk=0; //写入
for(i=0;i<8;i++)
{
if((temp1&0x80)==0)
sda=0;
else
sda=1;
sclk=1;
delay(2);
sclk=0;
temp1=temp1<<1;
}
temp5=upcheck();
/////////////////////////////////////////////
for(temp1=0;temp1 {

sclk=0;
sda=1;
for(i=0;i<8;i++) //读入八个位
{
temp2=temp2<<1;
sclk=1;
delay(2);
if(sda==1)
temp2=temp2|0x01;
sclk=0;
}
chn[temp1]=temp2;
temp2=0x00;

if((temp3-temp1)==1)
senducheck();//发送非应答信号
else
sendcheck();//发送应答信号

}
}
/****************************************************************************************/
void QU_write(uchar lx,uchar ly,uchar lz)
{
iicstart();//开始信号
writeiic(lx);//呼叫芯片D1307,并定义为 写 动作(0XD0)
writeiic(ly);//发送地址
writeiic(lz);//发送数据
iicstop();//结束信号
}
void READ_1307_DISP(void)//读取DS1307的寄存器
{
uchar i;
uchar j;
j=D1307[0]; //J=0
delay(1);
iicstart();//启动传送
writeiic(0xd0);//呼叫芯片D1307,并定义为 写 动作
delay(1);
writeiic(0x00); //发送起始地址并检测响应
delay(1);
iicstart(); //启动总线
read1(0xd1,3,D1307); //呼叫芯片D1307并定义为写动作(0XD1);循环写入数据的次数(3);将写入的数据保存在数组D1S07中
iicstop(); //关闭总线
if(j!=D1307[0])//接受到数据
{
JP1=!JP1; //JP1=1
}
i=D1307[2]&0x0f;//BCD码转换
if(JP1==0)
{
DISP_SAVE[1]=BCD_TAB[i]&0xfe;//时间显示的十位并加点
}
else
{
DISP_SAVE[1]=BCD_TAB[i];
}

i=(D1307[2]&0x70)>>4;//BCD码转换
DISP_SAVE[0]=BCD_TAB[i];//时间显示的个位
i=D1307[1]&0x0f;//BCD码转换
DISP_SAVE[3]=BCD_TAB[i];//时间显示的千位
i=(D1307[1]&0x70)>>4;//BCD码转换
DISP_SAVE[2]=BCD_TAB[i];//时间显示的百位

}

/**********************************************************************************************/

uint MCP3204_READ(uchar lx)//AD转换
{
uchar i=0,j=0;
uchar temp1=0,temp2=0;
uint temp3=0;
CS=1;
CLK=0;
delay(5);
CS=0;
j=lx;
for(i=0;i<5;i++)
{
if((j&0x80)==0x80)
{
DOUT=1;
}
else
{
DOUT=0;
}
CLK=0;
delay(5);
CLK=1;
j=j<<1;
}
CLK=0;
delay(5);
CLK=1;
delay(5);
CLK=0;
for(i=0;i<4;i++)
{
temp1=temp1<<1;
CLK=1;
delay(5);
CLK=0;
if(DIN==1)
{
temp1=temp1|0x01;
}
}
for(i=0;i<8;i++)
{
temp2=temp2<<1;
CLK=1;
delay(5);
CLK=0;
if(DIN==1)
{
temp2=temp2|0x01;
}
}
CS=1;
temp3=temp1;
temp3=(temp3<<8)|temp2;
return temp3;
}
/********************************************************************************/
void get_key(void) //按键程序
{
if(KEY_PIN==0)
{
delay(30);//消抖
if(KEY_PIN==0)
{
while(KEY_PIN==0);//松手检测
cotot=!cotot;
}
}
}
/*************************************************************************************/
void write_164(uchar lx)//控制数码管的显示
{
uchar i,j;
j=lx;
for(i=0;i<8;i++)
{
CLK_164=0;
if((j&0x01)==0x01)//检测J的最后一位是否为1
{
DTAT_164=1;//
}
else
{
DTAT_164=0;//
}
delay(3);
CLK_164=1;
j=j>>1;
delay(2);

}

}
void disp_all(void)
{
uchar i,j;
for(i=0;i<20;i++)//大约1sec跳闪一次
{
for(j=0;j<5;j++)
{
P0=0X0F;//数码管关闭
write_164(DISP_SAVE[j]);//数码管显示的内容
P0=LED_TAB[j];//数码管动态显示
delay(100);
P0=0X0F;//数码管关闭
}
}
write_164(0xff);
}

void main(void)
{
uchar lop;
uint teo;
FMQ=0;//关闭报警
KEY_PIN=1;//按键未按下
QU_write(0xd0,0x00,0x00);//呼叫芯片D1307并定义为写动作;向秒寄存器写入;数据0
QU_write(0xd0,0x01,0x16);//呼叫芯片D1307并定义为写动作;向分寄存器写入;数据16
QU_write(0xd0,0x02,0x03);//呼叫芯片D1307并定义为写动作;向时寄存器写入;数据3

while(1)
{
get_key();//检测按键
if(cotot==0)//按键未被按下显示温度
{
temper=MCP3204_READ(0xc0);
if(temper>2700)//温度零上时
{
temper=temper-2600;
if(temper>teo)//teo此时为0
{
teo=temper;
}
if(teo>400)
{
teo=teo-100;
}
lop=teo/1000;//LOP取千位
DISP_SAVE[0]=BCD_TAB[lop];//数码管显示十位

lop=(teo%1000)/100;//LOP取百位
DISP_SAVE[1]=BCD_TAB[lop];//数码管显示个位

lop=(teo%100)/10;//LOP取十位
DISP_SAVE[2]=BCD_TAB[lop]&0xfe;//数码管显示百位并显示点

lop=teo%10;//LOP取个位
DISP_SAVE[3]=BCD_TAB[lop]; //数码管显示千位
}
else if(temper<2660)//温度零下时
{
temper=0;
teo=0;
lop=teo/1000;
DISP_SAVE[0]=BCD_TAB[lop];//数码管显示0
lop=(teo%1000)/100;
DISP_SAVE[1]=BCD_TAB[lop];//数码管显示0
lop=(teo%100)/10;
DISP_SAVE[2]=BCD_TAB[lop]&0xfe;//数码管显示0并加点
lop=teo%10;
DISP_SAVE[3]=BCD_TAB[lop];//数码管显示0
}
if(teo>300)//如果温度超过30°
{
FMQ=1;//报警
}
else
{
FMQ=0;//停止报警
}
}
else if(cotot==1)//按键被按下显示时间
{
READ_1307_DISP();//读取实时时间
}
disp_all();//显示时间或者温度
}
}