正好我以前写过DS18B20的程序,现在共享给你。
我的单片机频率是8M,如果你的频率不同,请自己计算后把延时参数修改一下就可以了。
DS1820温度传感器单线总线读时间片
read: push r24
in r24,SREG
push r24
ldi r22,$FF
clr r23
out PORTB,r22 ;升高单线总线
out DDRB,r22 ;B口为输出口
out PORTB,r23 ;拉低单线总线
ldi r24,$05
read1: dec r24
brne read1 ;延迟10个时钟周期(大约1.25微秒)
out DDRB,r23 ;B口为输入口
ldi r24,$30
read2: dec r24
brne read2 ;延迟96个时钟周期(大约12微秒)
in r21,PINB ;读单线总线
ldi r24,$C8
read3: dec r24
brne read3 ;延迟400个时钟周期(大约50微秒)
pop r24
out SREG,r24
pop r24
ret
DS1820温度传感器单线总线写0时间片
write0: push r24
in r24,SREG
push r24
ldi r22,$FF
clr r23
out PORTB,r22 ;升高单线总线
out DDRB,r22 ;B口为输出口
out PORTB,r23 ;拉低单线总线
clr r24
wr0j1: dec r24
dec r24
nop
nop
brne wr0j1 ;延迟640个时钟周期(大约80微秒)
out PORTB,r22 ;升高单线总线
ldi r24,$07
wr0j2: dec r24
brne wr0j2 ;延迟14个时钟周期(大约1.75微秒)
out DDRB,r23 ;B口为输入口
pop r24
out SREG,r24
pop r24
ret
DS1820温度传感器单线总线写1时间片
write1: push r24
in r24,SREG
push r24
ldi r22,$FF
clr r23
out PORTB,r22 ;升高单线总线
out DDRB,r22 ;B口为输出口
out PORTB,r23 ;拉低单线总线
ldi r24,$07
wr1j1: dec r24
brne wr1j1 ;延迟14个时钟周期(大约1.75微秒)
out PORTB,r22 ;升高单线总线
clr r24
wr1j2: dec r24
dec r24
nop
nop
brne wr1j2 ;延迟640个时钟周期(大约80微秒)
out DDRB,r23 ;B口为输入口
pop r24
out SREG,r24
pop r24
ret
我使用的是Code Vision AVR C V2.03.4,其中带了一个DS18B20网络的读写控制程序,只要把DS18B20并联在这个网络中,就可以使用程序读写了。其全部代码如下:
/* Multipoint thermometer with LCD display
using the Maxim DS18B20
1 Wire bus temperature sensors
CodeVisionAVR C Compiler
(C) 2000-2005 HP InfoTech S.R.L.
www.hpinfotech.ro
Chip: ATmega8515
Memory Model: SMALL
Data Stack Size: 128 bytes
PLEASE MAKE SURE THAT THE CKSEL0..3 FUSE
BITS ARE PROGRAMMED TO USE THE EXTERNAL
3.6864MHz CLOCK SOURCE OF THE STK500 AND NOT
THE INTERNAL 1MHz OSCILLATOR.
The ATmega8515 chip comes from the factory
with CKSEL0..3 fuse bits set to use the
internal 1 MHz oscillator.
The DS18B20 sensors are connected to
bit 6 of PORTA of the ATmega8515 as follows:
[DS18B20] [STK500 PORTA HEADER]
1 GND - 9 GND
2 DQ - 7 PA6
3 VDD - 10 +5V
All the temperature sensors must be connected
in parallel
AN 4.7k PULLUP RESISTOR MUST BE CONNECTED
BETWEEN DQ (PA6) AND +5V !
*/
#asm
.equ __w1_port=0x1b
.equ __w1_bit=6
#endasm
/* Use an 2x16 alphanumeric LCD connected
to PORTC as follows:
[LCD] [STK500 PORTC HEADER]
1 GND- 9 GND
2 +5V- 10 VCC
3 VLC- LCD contrast control voltage 0..1V
4 RS - 1 PC0
5 RD - 2 PC1
6 EN - 3 PC2
11 D4 - 5 PC4
12 D5 - 6 PC5
13 D6 - 7 PC6
14 D7 - 8 PC7
*/
#asm
.equ __lcd_port=0x15
#endasm
#include
#include
#include
#include
char lcd_buffer[33];
/* maximum number of DS18B20 connected to the 1 Wire bus */
#define MAX_DEVICES 8
/* DS18B20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];
main()
{
unsigned char i,j,devices;
lcd_init(16);
lcd_putsf("CodeVisionAVR\n1 Wire Bus Demo");
delay_ms(2000);
lcd_clear();
/* detect how many DS18B20 devices
are connected to the 1 Wire bus */
devices=w1_search(0xf0,rom_code);
sprintf(lcd_buffer,"%u DS18B20\nDevice detected",devices);
lcd_puts(lcd_buffer);
delay_ms(2000);
/* display the ROM codes for each device */
if (devices)
{
for (i=0;i
sprintf(lcd_buffer,"Device #%u ROM\nCode is:",i+1);
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(2000);
lcd_clear();
for (j=0;j<8;j++)
{
sprintf(lcd_buffer,"%02X ",rom_code[i][j]);
lcd_puts(lcd_buffer);
if (j==3) lcd_gotoxy(0,1);
};
delay_ms(5000);
};
}
else
while (1); /* stop here if no devices were found */
/* configure each DS18B20 device for 12 bit temperature
measurement resolution */
for (i=0;i
{
sprintf(lcd_buffer,"Init error for\ndevice #%u",i);
lcd_clear();
lcd_puts(lcd_buffer);
while (1); /* stop here if init error */
};
/* measure and display the temperature(s) */
while (1)
{
j=1;
for (i=0;i
sprintf(lcd_buffer,"t%u=%+.3f\xdfC",j++,ds18b20_temperature(&rom_code[i][0]));
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(500);
};
};
}
程序很简洁,它这里使用的是Mega8515芯片,使用外部3.6864MHz晶振;DS18B20的DQ接在端口A的第6个端口位上,要接4.7K的上拉电阻;液晶显示器接在端口C上,使用4位数据总线方式。程序自动检测DS18B20的个数,并且设置DS18B20的工作方式,再显示各自测量的温度。
在实际使用时根据需要修改程序,比如更改DS18B20的接线位置和LCD使用的端口。
我来回答:基本上是这样的,可以用仿真器读取每一个18B20的序列号.也可以单独找一块有数码管或液晶显示的板子,专门烧个片子读序列号,然后显示出来,玩单片机的人这种板子肯定会有吧,没有的话焊一块出来也很快.
如果有兴趣的话还可以把读序列号的子程序融合到你测量温度的主程序中.条件:单片机内含有或板上有EEPROM.方法:设一个I/O口跳线,可临时将I/O口置高电平或低电平(实际上接个按钮也行),主程序一开始就读这个I/O口,低电平就读序列号,并将序列号写入EEPROM(当然18B20每次只能接一个读取,多个18B20可分次读取,存入EEPROM不同的地址),如果高电平就执行测量温度的程序,序列号从EEPROM中获取.这种方法比较麻烦,但可提高系统的可维护性,做好了就一劳永逸,否则一旦某个18B20损坏更换,就必须依赖仿真器读序列号,还要到主程中修改,再用编程器重新烧片子. 6432希望对你有用!
最简单的方法是,去www.ouravr.com下个别人的例子,把18B20的那部分复制下来就行!
我就是这么干的,有别人的用,自己就没去写了~!