#include <reg51.h>
/**********测温*************************/
#define uchar unsigned char
#define uint unsigned int
sbit DS=P1^7;
sbit E=P2^4;
sbit RS=P2^6;
sbit RW=P2^5;
const uchar NoDisp=0;
const uchar NoCur=1;
const uchar CurNoFlash=2;
const uchar CurFlash=3;
/**********测温*************************/
void long_delay(void);
void short_delay(void);
void delay10ms(unsigned char);
void write7279(unsigned char, unsigned char); // 写入HD7279
void send_byte(unsigned char); //发送1个字节
unsigned char read7279(unsigned char); // 读HD7279
unsigned char receive_byte(void); //接受1个字节
unsigned char digit[5]; //变量即I/O口定义
unsigned char key_number, j, k;
unsigned int tmr;
unsigned long wait_cnter;
sbit cs=P2^0; //
sbit clk=P2^1; //
sbit dat=P2^2; //
sbit key=P2^3; //
//****** HD7279A ******
#define CMD_RESET 0xa4 //复位指令
#define CMD_TEST 0xbf //测试指令
#define DECODE0 0x80 //方式0译码
#define DECODE1 0xc8 //方式1译码
#define CMD_READ 0x15 //读键盘指令
#define UNDECODE 0x90 //不译码指令
#define RTL_CYCLE 0xa3 //循环左移
#define RTR_CYCLE 0xa2 //循环右移
#define RTL_UNCYL 0xa1 //左移
#define RTR_UNCYL 0xa0 //右移
#define ACTCTL 0x98 //消隐
#define SEGON 0xe0 //段电亮
#define SEGOFF 0xc0 //闪烁控制
#define BLINKCTL 0x88
/*****************测温**********************************/
void mdelay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void WaitIdle()
{
RS=0;
RW=1;
//_nop_();也可以不要
E=1;
mdelay(5);
while((P0&0x80)==0x80)
{
E=0; //这两句protues仿真必须加;仿真器仿真也通过。
E=1;
};
E=0;
}
void LcdWcn(uchar c)
{
RS=0;
RW=0;
P0=c;
mdelay(5);
E=1;
mdelay(5);
E=0;
}
void LcdWc(uchar c)
{
WaitIdle();
LcdWcn(c);
}
void LcdWd(uchar c)
{
WaitIdle();
RS=1;
RW=0;
P0=c;
mdelay(5);
E=1;
mdelay(5);
mdelay(5);
E=0;
}
void ClrLcd()
{
LcdWc(0x01);
}
void RstLcd()
{
// dula=0;//关闭数码管锁存端,避免电流不够
// wela=0;
E=0;
LcdWc(0x38);
LcdWc(0x0f);
LcdWc(0x06);
LcdWc(0x01);
}
void SetCur(uchar Para)
{
mdelay(2);
switch(Para)
{
case 0:LcdWc(0x08);break;
case 1:LcdWc(0x0c);break;
case 2:LcdWc(0x0e);break;
case 3:LcdWc(0x0f);break;
default:break;
}
}
void LcdPos(uchar xPos,uchar yPos)
{
uchar tmp;
xPos&=0x0f;
yPos&=0x01;
if(yPos==0)
tmp=xPos;
else
tmp=xPos+0x40;
tmp|=0x80;
LcdWc(tmp);
}
void WriteChar(uchar c,uchar xPos,uchar yPos)
{
LcdPos(xPos,yPos);
LcdWd(c);
}
void WriteString(uchar *s,uchar xPos,uchar yPos)
{
uchar i;
if(*s==0)
return;
for(i=0;;i++)
{
if(*(s+i)==0)
break;
WriteChar(*(s+i),xPos,yPos);
xPos++;
if(xPos>=15)
break;
}
}
void dsreset(void) // DS18B20初始化
{
uint i;
DS=0; // 首先拉低,要求480us
i=103;
while(i>0)i--;
DS=1; // 上升沿,要求15~60us
i=4;
while(i>0)i--;
}
void rxwait()//等待应答脉冲
{
uint i;
while(DS);
while(~DS);
i=8;while(i>0)i--;
}
bit tmpreadbit(void) //读一位
{
uint i;
bit dat;
DS=0;
i++; //1us延时
DS=1;//15us内,主机必须停止将DS引脚置低
i++;i++; //15us延时
dat=DS;
i=8;while(i>0)i--;//读时隙不低于60us延时
return (dat);
}
uchar tmpread(void) // 读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void tmpwritebyte(uchar dat) //写一个字节到DS18B20里
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写1部分
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //写0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //发送温度转换命令
{
dsreset();//初始化DS18B20
rxwait(); //等待应答脉冲
mdelay(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}
uint tmp() //获得温度
{
float tt;
uchar a,b;
uint temp;
dsreset();
rxwait();//等待应答脉冲
mdelay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp<<=8; //出厂默认设置为12位分辨率
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
/*****************测温**********************************/
void main()
{
/*****************测温**********************************/
uchar xPos0,yPos0,xPos1,yPos1,i;
uchar * s0;
uint temp;
uchar A1,A2,A3;
/*****************测温**********************************/
while (1)
{
for (tmr=0;tmr<0x2000;tmr++); //上电延时
send_byte(CMD_RESET); // HD7279A
//******************************************
// 闪烁及键盘借口测试
//******************************************
/*****************测温**********************************/
send_byte(CMD_RESET);
RstLcd();
ClrLcd();
SetCur(NoCur);
xPos0=0;yPos0=0;
s0="Temperature is:";
WriteString(s0,xPos0,yPos0);
xPos1=2;yPos1=1;//显示小数点、温度单位
WriteChar(0x2e,xPos1,yPos1);
xPos1=4;yPos1=1;
WriteChar(0xdf,xPos1,yPos1);
xPos1=5;yPos1=1;
WriteChar(0x43,xPos1,yPos1);
for(i=0;i<=5;i++)
{
tmpchange();
temp=tmp();
A1=temp/100;
A2=temp%100/10;
A3=temp%10;
xPos1=0;yPos1=1;
WriteChar(0x30+A1,xPos1,yPos1);
xPos1=1;yPos1=1;
WriteChar(0x30+A2,xPos1,yPos1);
xPos1=3;yPos1=1;
WriteChar(0x30+A3,xPos1,yPos1);
mdelay(300);
}
//ClrLcd();
/*****************测温**********************************/
send_byte(CMD_TEST); //
for (j=0;j<3;j++) // 3
{
delay10ms(100);
}
send_byte(CMD_RESET); //消除显示*/
//*********************************************
//10S无键盘按下,顺序执行
//**********************************************
wait_cnter=0;
key_number=0xff;
write7279(BLINKCTL,0xfc); // 1 2位为闪烁位
write7279(UNDECODE,0X08); // 1 '_'
write7279(UNDECODE+1,0x08); // 2 '_' */
do
{
if (!key) //有键按下
{
key_number=read7279(CMD_READ);//读出键码
write7279(DECODE1+1,key_number/16);//第2位显示键码高8位
write7279(DECODE1,key_number&0x0f);//第1位显示键码低 8位
while (!key); //等待键码按下
wait_cnter=0;
}
wait_cnter++;
} while (key_number!=0 && wait_cnter<0x90000);
//按键为0和超时进入下一步
write7279(BLINKCTL,0xff); // 消除闪烁
//快速计数
for (j=0;j<5;j++) // 初始值00000
{
digit[j]=0;
write7279(DECODE0+j,digit[j]);
}
while (digit[4]<2) // 计数到20000就停止
{
digit[0]++;
if (digit[0]>9)
{
digit[0]=0;
digit[1]++;
if (digit[1]>9)
{
digit[1]=0;
digit[2]++;
if (digit[2]>9)
{
digit[2]=0;
digit[3]++;
if (digit[3]>9)
{
digit[3]=0;
digit[4]++;
if (digit[4]>9)
{
digit[4]=0;
}
}
}
}
}
write7279(DECODE0,digit[0]);
if (digit[0]==0)
{
write7279(DECODE0+1,digit[1]);
if (digit[1]==0)
{
write7279(DECODE0+2,digit[2]);
if (digit[2]==0)
{
write7279(DECODE0+3,digit[3]);
if (digit[3]==0)
{
write7279(DECODE0+4,digit[4]);
}
- 1
- 2
- 3
前往页