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

最新更新时间:2022-04-21来源: eefocus关键字: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();

}

关键字:51单片机  定时中断  DS18B20  时序 编辑:什么鱼 引用地址:51单片机以定时中断的方法实现DS18B20时序

上一篇:单片机_LCD12864显示自己制作的图片(时钟为例)
下一篇:基于单片机的电梯(四层)控制系统设计

推荐阅读

用AT89C51单片机显示倒计时程序
;可设定时间的倒计时定时器,可选择5/15/20/30/35/45/50分钟倒计时;倒计时时间由四位拨码开关的2/3/4位来控制,;第2位表示5分钟,第3位表示15分钟,第4位表示30分钟,;通过不同的组合可以产生5/15/20/30/35/45/50分钟倒计时;P1.0口的外接的发光二极管为状态LED,定时未开始时LED常亮,定时过程中LED闪烁;K1为开始按钮,K2为停止按钮适用STM8S/STM8L/STM8A N76E003 脱机编程器/烧录器/下载器/SP_00【包邮】m.tb.cn/h.UlXVKiOa_bit equ 20h ;数码管个位数存放内存位置b_bit equ 21h ;数码管十位数存放内存位置temp eq
发表于 2023-01-13
51单片机数码管静态显示和动态显示原理及实验 夜猫子
数码管多位数码管,即是两个或两个以上单个数码管并列集中在一起形成一体的数码管。当多位一体时,它们内部的公共端是独立的,而负责显示什么数字的段线全部是连接在一起的,独立的公共端可以控制多位一体中的哪一位数码管点亮,而连接在一起的段线可以控制这个能点亮数码管亮什么数字,通常我们把公共端叫做“位选线”,连接在一起的段线叫做“段选线”有了这两个线后,通过单片机及外部驱动电路就可以控制任意的数码管显示。一般一位数码管有10个引脚,二位数码管也是10个引脚,四位数码管是12个引脚。为了更方便区分段选和位选,请看下原理图:如图为两个4位一体的数码管,可以看到与8个com相连的是两个数码管的位选,位选与引脚相连,所以位选控制那个灯亮。段选可以看到a
发表于 2023-01-12
<font color='red'>51单片机</font>数码管静态显示和动态显示原理及实验 夜猫子
51单片机独立按键和矩阵按键实现
独立按键实验按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。我们开发板上使用的按键及内部简易图如下图所示管脚与管脚之间(注意是距离)距离长的是导通状态,短的是接通状态。通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号如下图所示:如图所示,按键闭合式不会立刻稳定的接通,断开时也不会一下子断开,会伴随一些抖动。抖动的时间长短有按键特性决定,一般为5Ms到10ms.按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖。消抖消抖可分为硬件消抖和软件消抖。为了使电路更加简单,通常采用软件消抖。一般来说一个简单的按键消抖就是先读取按键的状态, 如果得到按键按下
发表于 2023-01-12
51单片机8*8点阵原理及实现
LED点阵(8*8)LED 点阵是由发光二极管排列组成的显示器件,在我们日常生活的电器中随处可见,被广泛应用于汽车报站器,广告屏等。通常应用较多的是 8* 8 点阵,然后使用多个 8 * 8 点阵可组成不同分辨率的 LED点阵显示屏,比如 16* 16 点阵可以使用 4 个 8* 8 点阵构成。因此理解了 8* 8LED点阵的工作原理,其他分辨率的 LED 点阵显示屏都是一样的。这里以 8* 8LED 点阵来做介绍。发光原理8* 8 点阵共由 64 个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置 1 电平(行所接的是二极管的阳极,所以为高电平),某一列置 0 电平(列所接的是二极管的阴极极,所以为低
发表于 2023-01-12
51单片机中断基本概念
问题引入在了解基本概念之前,先看三个问题:1.你想使用的中断是哪个?2.你所希望的触发条件是什么?3.你希望在中断之后做什么?可以边看边思考,文章最后给出答案中断概念为什么引入中断?中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。中断系统特点:①分时操作。CPU 可以分时为多个 I/O 设备服务,提高了计算机的利用率;②实时响应。CPU 能够及时处理应用系统的随机事件,系统的实时性大大增强;③可靠性高。CPU 具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高中断过程对于单片机来讲,中断是指CPU在处理某一时间A时,发生了另一事件B请求CPU立
发表于 2023-01-12
51单片机外部中断点亮LED
外部中断软件设计原理中断发生的三个条件①中断源有中断请求;②此中断源的中断允许位为 1;③CPU 开中断(即 EA=1)。比如我们配置外部中断 0,对应的配置程序如下:EA=1;//打开总中断开关EX0=1;//开外部中断 0IT0=0/1;//设置外部中断的触发方式(下降沿触发)如果要配置的是外部中断 1,只需将 EX0 改为 EX1,IT0 改为 IT1在编写程序时通常我们会将外部中断的配置放到一个自定义函数内便于管理维护。如下伪代码所示:void Int0Init(){//设置 INT0IT0=1;//边沿触发方式(下降沿)EX0=1;//打开 INT0 的中断允许。EA=1;//打开总中断}/*当触发中断后即会进入中断服务函
发表于 2023-01-12

推荐帖子

一种低功耗的热释电人体感应模块
GH-718人体感应模块 [■应用范围 ■安防产品■人体感应玩具■人体感应灯具■工业自动化控制等 主要技术参数: 1使用工作电压:DC4.5~20V 2静态电流:50uA 3电平输出:高3.3V低0V 4保持时间:3-900秒可调 5感应角度:110度 6感应距离:7M 详细资料下载 [本帖最后由珊珊于2008-12-1410:30编辑]一种低功耗的热释电人体感应模块
珊珊 安防电子
使用BBB的IO口
本帖最后由wytalfred于2014-3-821:40编辑 从Terminal直接控制IO口的方法如下:root@beaglebone:~#cd/sys/class/gpio root@beaglebone:/sys/class/gpio#ls-l total0 --w-------1rootroot4096Jan100:00export lrwxrwxrwx1rootroot0Jan100:00gpiochip0->../../dev
wytalfred DSP 与 ARM 处理器
体贴的戒指闹钟
前些时体贴的戒指闹钟 间我发了一个帖子问有没有给一个人的闹钟。现在有了[体贴的戒指闹钟 ],情侣双方很多时候可能会遇到起床时间不同,设计不同时间的闹钟的话会打扰到对方,可这款设计不会像普通闹钟一样靠刺耳的声音催人起床,而是通过另一种温柔的方式让人慢慢醒来。看来和我想法一样的人还大有人在啊体贴的戒指闹钟
xyh_521 创意市集
请问这个应该调用何函数?
我用监视器在串口上获得串口请求如下,请问调用哪2个API才能得到下面的请求呢? IOCTL_SERIAL_SET_WAIT_MASK IOCTL_SERIAL_WAIT_ON_MASK PS:比如,调用ReadFile,获得的请求为IRP_MJ_READ; WriteFile为IRP_MJ_WRITE; ClearCommError为IOCTL_SERIAL_GET_COMMSTATUS。 非常感谢!!!!!!!!!请问这个应该调用何函数?
xtaccount 嵌入式系统
2013f题复测
本帖最后由paulhyde于2014-9-1503:06编辑2013f题复测 2013f题复测
2357470983 电子竞赛
【行空板 Python编程学习主控板测评】开发环境与开机配置
本帖最后由jinyi7016于2022-10-3110:59编辑 首先感应EEWORLD与DFRobot选择我进行这些行空板的试用。收到开发板后,第一时间开箱开机开发板有两种配件,一个是一条Type-c的USB线,这条线是两用的,还可以连接microusb接口,还有一些ph2.0的3P与4P的连接线,可以连接DFRobot的一些模块。行空板的教程,都可以在这里找到:行空板官方教程-wiki.unihiker.com一、芯片组行空板的硬件资源很丰富,如下所示:
jinyi7016 嵌入式系统
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved