51单片机以定时中断的方法实现DS18B20时序

    由于DS18B20是单线操作,所以必须严格遵守它的时序要求才能正常与之建立联系并实现读写操作。

    网上见到的程序多是在主程序中以延时的方式实现,而且要求关中断,以实现18B20对时序的要求。但是实际应用中,测温操作一般是作为辅助功能,主要任务是通信及数据处理等其他操作,这样一来,如果将DS18B20的程序代码放在主程序中,势必影响其他需要实时处理的中断。

    前些天用到DS18B20,就尝试以51定时中断的方法实现DS18B20时序,在面包板上成功跑了起来。

用的单片机是STC11F16XE,使用外部晶振24MHz。下面的程序中不仅有DS18B20的操作,还包含了数码管显示、按键检测、EEPROM的操作。定时器T1专门用于DS18B20时序产生,定时器T0用于按键检测、数码管显示,主函数中做EEPROM及其他的操作。程序中有些注释是调试过程中加的,并且有些代码部分在调试中修改过,先前的注释并没有同时删去,所以看下面的代码的时候,不要被注释误导了。

代码如下:

#include "REG51.H"
#include "INTRINS.H"


typedef unsigned char BYTE;
typedef unsigned int WORD;


sfr P1M0 = 0x92; //                                                                      
sfr P1M1 = 0x91; // 


sfr P3M0 = 0xB2;
sfr P3M1 = 0xB1;


sfr P2M0 = 0x96;
sfr P2M1 = 0x95;


/*sfr associated with the IAP*/
sfr IAP_DATA = 0xc2;
sfr IAP_ADDRH = 0xc3;
sfr IAP_ADDRL = 0xc4;
sfr IAP_CMD = 0xc5;
sfr IAP_TRIG = 0xc6;
sfr IAP_CONTR = 0xc7;
/*ISP/IAP/EEPROM command*/
#define CMD_IDLE 0
#define CMD_READ 1
#define CMD_PROGRAM 2
#define CMD_ERASE 3


#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81//if SYSCLK<24MHz


//start address for STC11/10xx series EEPROM
#define IAP_ADDRESS0x0000


void Delay(BYTE N);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE val);
void IapEraseSector(WORD addr);


#define MINUTE 8400  //60*140=8400 interrupts per minute
#define DAY3S 4320  //there are 72*60*8400=4320*8400 interrupts in 72 hours
//
sbit shi = P3^7;
sbit ge = P3^2;
//sbit led = P1^5;


sbit key1 = P3^3;
sbit key2 = P3^4;
sbit key3 = P3^5;


sbit heat = P2^7;
sbit water = P2^5;
sbit beep = P2^0;


unsigned char code digit[11] ={
0xbf,//0
0x83,//1
0xed,//2
0xeb,//3
0xd3,//4
0xfa,//5
0xfe,//6
0xa3,//7
0xff,//8
0xfb,//9
0xc0//nfinished
}; 


unsigned char code cmd[4] = {0xcc,0x44,0xcc,0xbe};
unsigned int cmd_n;
bit nodevice,cunz;
unsigned char saom;
unsigned int num,t1_num;
unsigned char temp,led;
unsigned int jiaoshui,jiaoshui_t,jiaoshui_tt;


unsigned char wendu,cishu;
unsigned int ds18b20;
unsigned char menu,inc,dec;
BYTE kflag;  //
bit adjust;
bit updateEEP;


unsigned int heat_t;


sbit DQ = P3^1;                     //DS18B20?????P3.3
BYTE TPH;                           //?????????
BYTE TPL;                           //?????????
BYTE dat;


void main()
{
  updateEEP = 0;
num = 0;
temp = 0;
saom = 0;
led = 0x00;
nodevice = 0;

menu = 0;
inc = 0;
dec = 0;
kflag = 0x00;
adjust = 0;

wendu = 50;
cishu = 72;
heat = 1;
water = 1;
jiaoshui = 0;
jiaoshui_t = 1;
jiaoshui_tt = 0;

P2M0 = 0x01;
P2M1 = 0x00;
beep = 0;

P1M0 = 0xff; //                                                                      
  P1M1 = 0x00; // 
// P1 = digit[0];

P3M0 = 0x84; //                                                                         
  P3M1 = 0x84;
P3 = 0X0;

TMOD = 0x11; //TMOD = 0x1;
TH0 = 0x00;
TL0 = 0xff;
TR0 = 1;
ET0 = 1;

TH1 = 0xff;
TL1 = 0x88;//256-120=136=0x88
TR1 = 0;
ET1 = 1; // enable T1 interrupt
PT0 = 0;
PT1 = 1; // T1优先级高

EA = 1;


//read wendu and cishu value from EEPROM
Delay(10);
wendu = IapReadByte(0x0002);
cishu = IapReadByte(0x0003);


jiaoshui = 8400/cishu;


//
  while (1)
{
if(updateEEP == 1)
{
updateEEP = 0;

IapEraseSector(0x0000);
IapProgramByte(0x0002,wendu);
IapProgramByte(0x0003,cishu);

jiaoshui = 8400/cishu;
}


beep= (ds18b20>30)? 1:0;
heat= (ds18b20>30)? 0:1;
water=(jiaoshui_t<420)? 0:1;
// beep= (jiaoshui_t<420)? 1:0;
}
}




/
void it_timer0(void) interrupt 1
{
TH0 = 0xc8;  //定时时间是1/140s
TL0 = 0x32;
num++;
/*
if(jiaoshui_t
   
   
    
    0) wendu--; 
else wendu=0; 
kflag = 0x00; break;}
else if(menu==2)
{if(cishu>0) cishu--;
else cishu=0; 
kflag = 0x00; break;}
else break;
default ://??????????????
break;
}
// P1M0 = 0xff;
// P1M1 = 0x00;

//显示
saom++;
saom = saom%3;

switch(menu)
{
case 0 : temp = ds18b20; led = 0x00; break;
case 1 : temp = wendu; led = 0x02; break;
case 2 : temp = cishu; led = 0x01; break;
default : temp = ds18b20; break;
}

if(nodevice)
{
shi = 0;
ge = 0;
P1 = digit[10];
}
else
switch(saom)
{
case 0 :
shi = 0;
ge = 1;
P1 = digit[temp/10];
break;
case 1 :
shi = 1;
ge = 0;
P1 = digit[temp%10];
break;
case 2 :
shi = 1;
ge = 1;
if(num < 80) P1 = led;
else P1 = 0x80;
break;
default : break;
}
/*
//加热定时
if(ds18b20>30) {heat = 1; heat_t++;}
if((heat_t > 0) && (heat_t < 1400))
{heat_t++;}
else {heat_t = 0; heat = 0;}
*/


//采集18B20
if(num>=140)
{
num = 0;
t1_num = 0; cmd_n = 0; nodevice = 0;
TR1 = 1; 
}


}




void it_timer1(void) interrupt 3
{

switch(t1_num)
{
case 0 :
case 33 :
cunz = 1; DQ = 0; break;
case 8 :
case 41 :
DQ = 1; break;
case 9 :
case 42 :
cunz = DQ; break;
case 16 :  //写字节  第一位
case 49 :
if(cunz) {/*ET1 = 0;*/TR1 = 0; nodevice = 1; break;}
else
{
dat = cmd[cmd_n++]; DQ = 0; _nop_(); _nop_(); 
dat >>= 1; DQ = CY; break;
}
case 17 : //cmd[0]
case 18 :
case 19 :
case 20 :
case 21 :
case 22 :
case 23 :

case 25 : //cmd[1]
case 26 :
case 27 :
case 28 :
case 29 :
case 30 :
case 31 :

case 50 : //cmd[2]
case 51 :
case 52 :
case 53 :
case 54 :
case 55 :
case 56 :

case 58 : //cmd[3]
case 59 :
case 60 :
case 61 :
case 62 :
case 63 :
case 64 :

DQ = 1; _nop_(); _nop_(); //恢复数据线,恢复时间
 DQ = 0; _nop_(); _nop_(); //开始下一位
 dat >>= 1; DQ = CY; break;
case 24 :
case 57 :
DQ = 1; _nop_(); _nop_(); //写第一个字节结束
dat = cmd[cmd_n++];       //填充dat
DQ = 0; _nop_(); _nop_();  //写第二个字节
dat >>= 1; DQ = CY; break;
case 32 :
DQ = 1; _nop_(); _nop_();  //写第二个字节结束 0x44
_nop_(); _nop_();
case 65 :
DQ = 1; _nop_(); _nop_();   //0xbe 命令发完
dat = 0; //读TPL
dat >>= 1;
DQ = 0; _nop_(); _nop_();
DQ = 1; _nop_(); _nop_();
if(DQ) dat |= 0x80;
break;
case 66 :
case 67 :
case 68 :
case 69 :
case 70 :
case 71 :
case 72 :

case 74 :
case 75 :
case 76 :
case 77 :
case 78 :
case 79 :
case 80 :
dat >>= 1;
DQ = 0; _nop_(); _nop_();
DQ = 1; _nop_(); _nop_();
if(DQ) dat |= 0x80;
break;
case 73 :
TPL = dat;
 dat = 0; //读TPH
dat >>= 1;
DQ = 0; _nop_(); _nop_();
DQ = 1; _nop_(); _nop_();
if(DQ) dat |= 0x80;
break;
case 81 :
TPH = dat;
TPL = (TPL>>4) & 0x0f;
TPH = (TPH<<4) & 0xf0;
ds18b20 = TPL | TPH;
if(ds18b20>99 | ds18b20 <=0)
nodevice = 1;

TR1 = 0;
break;
default : break;
}

t1_num++;

TH1 = 0xff;
TL1 = 0x88;//256-120=136=0x88
}


//
void Delay(BYTE n)
{
WORD x;
while(n--)
{
x = 0;
while(++x);
}
}


void IapIdle()
{
IAP_CONTR = 0;
IAP_CMD = 0;
IAP_TRIG = 0;
IAP_ADDRH = 0xff;
IAP_ADDRL = 0xff;
}


BYTE IapReadByte(WORD addr)
{
BYTE rdval;

IAP_CONTR = ENABLE_IAP;
IAP_CMD = CMD_READ;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5a;
IAP_TRIG = 0xa5;
_nop_();

rdval = IAP_DATA;
IapIdle();

return rdval;
}


void IapProgramByte(WORD addr, BYTE val)
{
IAP_CONTR = ENABLE_IAP;
IAP_CMD = CMD_PROGRAM;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_DATA = val;
IAP_TRIG = 0x5a;
IAP_TRIG = 0xa5;
_nop_();

IapIdle();
}


void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP;
IAP_CMD = CMD_ERASE;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5a;
IAP_TRIG = 0xa5;
_nop_();

IapIdle();
}

   
   


  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值