Cảm biến nhiệt độ DS18B20
DS18B20 giao tiếp với MCU theo giao thức 1_wire, mạch thể hiện trong lab này như hình. Với giao thức này đề nghị một port open drain với một điện trở kéo lên cỡ 4.7 kΩ - 10 kΩ.
Để gửi "1", thiết bị chủ bus gửi một xung thấp rất ngắn (1–15 µs). Để gửi "0", thiết bị chủ gửi một xung thấp 60 µs. Cạnh đi xuống của xung được sử dụng để bắt đầu một monostable multivibrator trên thiết bị phụ thuộc. Multivibrator trong đồng hồ của thiết bị phụ thuộc để đọc dòng dữ liệu trong khoảng 30 µs sau khi cạnh xung đi xuống. Multivibrator của thiết bị phụ thuộc không thể tránh khỏi có dung sai tương tự ảnh hưởng đến thời gian chính xác của nó, đó là lý do tại sao xung "0" phải dài 60 µs, và xung "1" không thể dài hơn 15 µs.
Khi nhận dữ liệu, thiết bị chủ gửi một xung 0 volt 1–15-µs để bắt đầu mỗi bit. Nếu đơn vị truyền phụ thuộc muốn gửi "1", nó không làm gì, và bus quay lại điện áp cao. Nếu thiết bị truyền phụ thuộc muốn gửi "0", nó kéo đường data xuống điện áp thấp trong 60 µs.
Trình tự cơ bản là một xung reset theo sau bởi một lệnh 8-bit, và sau đó dữ liệu được gửi hoặc nhận trong các nhóm 8-bit.
Hàm sau đây mô tả quá trình gửi dữ liệu, thực hiện với PIC 16F887
//-------------------------------
void onewire_write(int data)
{
int count;
for (count=0; count<8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // pull 1-wire low to initiate write time-slot.
output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // set output bit
delay_us( 60 ); // wait until end of write slot.
output_float(ONE_WIRE_PIN); // set 1-wire high again,
delay_us( 2 ); // for more than 1us minimum.
}
}
Và đây là hàm nhận
//-------------------------------
int onewire_read() {
int count, data;
for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us( 8 ); // let device state stabilise,
shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result.
delay_us( 120 ); // wait until end of read slot.
}
return( data );
}
Để 16F887 nhận dữ liệu từ DS18B20 ta cần một hàm thực hiện theo quy định phần cứng của thiết bị ta dùng hàm ds1820_read
float ds1820_read()
{
nt8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
onewire_reset();
onewire_write(0xCC);
onewire_write(0x44);
while (busy == 0) busy = onewire_read();
onewire_reset();
onewire_write(0xCC);
onewire_write(0xBE);
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
result = (float) temp3 / 16.0; //Calculation for DS18B20 with 0.1 deg C resolution
delay_ms(200);
return(result);
}
Trong hàm trên có sử dụng một hàm reset được mô tả như sau
void onewire_reset() // good for one device
{
output_low(ONE_WIRE_PIN);
delay_us( 500 ); // pull 1-wire low for reset pulse
output_float(ONE_WIRE_PIN); // float 1-wire high
delay_us( 500 ); // wait-out remaining initialisation window.
output_float(ONE_WIRE_PIN);
}
Nếu các hàm trên có sử dụng hàm shift_right mà bạn cảm thấy khó hiểu, hãy thay thế bằng hàm sau
//TA modify -> OK, but not optimal
void make_one_wire_pin(){//mục đích cho gọn để dễ xem hàm bên dưới
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us( 8 ); // let device state stabilise,
}
int _1wire_read(){
int i,data=0,temp;
for(i=0;i<8;++i){
make_one_wire_pin();
//----thay thế shift_right
temp=input(ONE_WIRE_PIN);
temp<<=i;
data|=temp;
//----------------
delay_us(120);
}
return data;
}
// end TA test