由于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();
}
上一篇:单片机_LCD12864显示自己制作的图片(时钟为例)
下一篇:基于单片机的电梯(四层)控制系统设计
推荐阅读最新更新时间:2024-11-12 10:48
推荐帖子
- 【MPS商城钜惠体验季】开箱+资料
- 上月通过朋友介绍参加了MPS商城的购物体验活动,感谢给与机会。首先MPS的箱子搞的还真是大,一点点元件都搞的好大个箱子,还以为买了好多元件。下面是大箱子,上面是小纸箱子收到的芯片是长这个样子下面的封装框图:原理图:【MPS商城钜惠体验季】开箱+资料开发板呢?就弄了两个芯片吗?
- king86 LED专区
- 电力电子装置控制系统的DSP设计方案
- 作者:武汉大学王奇陈柏超来源:单片机及嵌入式系统应用摘要以TI公司的电机控制专用芯片TMS320LF2407aDSP为例,介绍电力电子装置中控制系统的硬件设计方案。包括DSP的电平转换、时钟、复位、译码、片外存储、键盘、液晶显示和E2PROM电路与必要的外围电路。关键词DSP硬件设计电力电子装置PCB引言在现代高性能电力电子和交流电机控制系统中,DSP已经取代了微控制器成为控制器的核心。其快速强大的运算和处理能力以及并行运行的能力,满足了电力电子装置控制
- hellodsp DSP 与 ARM 处理器
- 【藏书阁】几何绕射理论
- 目录:第一章几何光学和几何绕射理论的基本概念1.1几何光学1.1.1各向同性不均匀媒质中的电磁场1.1.2高频的几何光学近似1.1.3几何光学的基本方程1.1.4几何光学的强度定律1.2均匀媒质中射线场的基本表示式1.3费马原理1.4几何绕射理论的基本概念1.5几何光学入射场和反射场1.5.l几何光学入射场1.5.2几何光学反射场1.6绕射射线场1.6.1边缘绕射射线场1.6.2表面统射射线场1.6.3尖顶绕射射线场l.7
- wzt RF/无线
- 为DIY大赛加把油:LaunchPad超多代码分享
- 同事分享的:TITEMBOOTemboo支持7种编程语言,其平台相当于为程序员提供了一个基于云系统的图书馆,拥有超过2000个的代码和代码编排,供程序员直接取用。当你的App希望支持将文件同步到Dropbox,或支持用PayPal支付时,Temboo上都有相应的工具包,让曾经烦琐的写代码过程缩减到五行代码就能搞定,结果是程序员手边就能拿到各种软件包。如果某个在线服务商的API发生变动,Temboo也会相应在后台调整代码——这给程序员省了大把时间,而且解决了他们最头疼的API频繁更新问题
- soso 微控制器 MCU
- BLE4.0之CC2541串口应用从基础实验到协议栈
- 为什么要发个这个帖子呢?学习BLE4.0有一个月了吧,发这个帖子也是为了记录自己的学习过程相信大家都是学过其他系列的单片机,CC2541集51内核,肯定少不了51的影子,肯定要知道串口,在学习中,串口调试是必不可少的,它能打印出很多有用的信息出来。CC2541的串口引脚是:P0.2--------UART_RXP0.3--------UART_TX先说基础实验吧,上代码: voidInitUart(void) { P0SEL|=BV(2)|BV(3)
- ywlzh 无线连接
- 为什么FREERTOS里好多例程编译通不过
- 请问高手,为什么为什么FREERTOS里好多例程编译通不过?谢谢为什么FREERTOS里好多例程编译通不过对开发环境有要求呗,甚至是版本,有的支持文件不同
- chenbingjy 实时操作系统RTOS
设计资源 培训 开发板 精华推荐
- 采用双层 TO-220 封装的 3.3V 1A、低 EMI、效率达 92% 的直流/直流模块参考设计
- LT6654AHS6-2.5 具有升压输出电流和电流限制的电压基准的典型应用
- ADR423 超精密、低噪声、3.00 Vout XFET 电压基准作为可编程电流源的典型应用
- ADR435A 5 Vout 超低噪声 XFET 电压基准的典型应用,具有灌电流和拉电流能力
- LTC4263 DC981A 中跨演示板,带有 DC981B 端跨插件
- MIC29152WD大电流低压降可调输出稳压器的典型应用
- LF18ABPT-TR 1.8V 顺序极低压降稳压器多输出电源的典型应用
- EVAL-ADM3055EEBZ,用于评估 ADM3055E 5kV rms、信号和电源隔离、CAN FD CAN 收发器的评估板
- DC480A-C,使用 LTC3405AES6-1.8、2.5 至 5.5 Vin、1.8Vout @ 300mA 薄型 SOT 同步降压稳压器和小尺寸电感器的演示板
- 具有双输入的 LTC3126EFE 12V、2MHz 降压转换器的典型应用电路
- 直播已结束【英飞凌智能门锁解决方案】
- 有奖直播|5G多场景终端应用对连接器的新要求及Molex的5G连接方案
- 模电怎么学?TI帮你定制课程清单!体验“模电选课测试”功能,赢精彩好礼
- 学习 TI E2E 工业设计资料抢楼有礼
- 有奖直播|安森美先进的封装和驱动技术助力碳化硅能源应用
- 已结束|Maxim IO-Link通信协议设计方案详解,5大优势助你轻松联网!
- 年终大冲关!第二期光荣榜活动震撼登场!
- 有奖直播|安森美高能效产品在 EV-Charger 市场的应用
- TI Simplelink 狂欢正嗨,热门产品 9 折特惠!更有分享好礼任性送!
- 【EEWORLD第四十三届】2012年10月社区明星人物揭晓!