|
So,
we are going to write a piece of code that implements the 1-wire protocol.
Start
by gathering info, the first thing to look at is the DS18B20 datasheet,
get a feeling of what is about. No need to understand everything in the
datasheet. On Maxim's site there are tones of application notes, I would
suggest application notes 162,187,126,120, with this sequence, probably
first AVR318 application note which is easy to follow. Come on, show an
aggressive attitude, although you don't understand everything, I don't
either. Do not copy/paste pieces of code hoping it's going to work, it
will not. From the ground we go up. Try to simplify thinks by asking yourself
simple questions.
You
see that many thermos can be connected together on a bus, a micro talks
to them, so they have to be addressed with a unique ID (think ethernet
& IP analogy). There is a single wire, so only one speaks at a time.
Who coordinates discussion? The master, the micro (forget ethernet analogy).
Well, if it does how the hell it knows which thermo is on the bus? There
is an algorithm for doing that, the search algorithm. Do I care? No, not
for this project, we have a single thermo on the bus. Is there a way to
identify communication errors or malfunctioning thermos? The CRC does
that.
If you were a microcontroller, and wanted to talk over your half-duplex
conference phone to your fellow thermometers, what interogation commands you
would like to have? There are a few simple concepts, that reasonably fit
into the puzzle. Don't bypass them.
Hmm, where to start? The first think to try after getting the
idea is sending 1s and 0s. Reading 1s and 0s would help too. It comes
down to holding the pin for output and releasing it for input. When set
for output, the pin can be written, when set for input the pin can be
read ... Have a look at the following defs and see if they make any sense.
// set pin mask
#define wmask 0x08
// set 1-wire pin for output
#define wOut DDRA |= wmask
// set 1-wire pin for input (bus released)
#define wIn DDRA &= ~wmask
// set 1-wire bus high
#define wH PORTA |= wmask
// set 1-wire bus low
#define wL PORTA &= ~wmask
// get 1-wire bus input (bus released)
#define wR PINA & wmask
Now, this is just pin toggling, from that we need to get
to the basic bus signals. Let's go one level up. Hmm, wait a minute, it
looks like we need a delay first. OK. Think of ...
// delay = 5.70 + (1.22 * count)us
void uDelay(u8 count)
{
while(count--);
}
This is a delay but how long does it last? You need
to simulate your code with AVRStudio, please do so. Go to Debug => AVR
Simulator Options => Frequency=7.3728 MHz. After compiling, Debug =>
Start Debugging, press F11 a couple of times and look at the stopwatch.
You may reset your stopwatch by right clicking on it. I hope you get the
same result as I did: delay = 5.70 + 1.22 * count microseconds for a
7.3728MHz clock. One time slot is 60us and looking at the AVR318 app. note
we can realize how to output 1s and 0s....
void wTxbit (u8 bit)
{
wOut;wL;
if (bit)
{
uDelay (4); // 10.58us
wIn;
uDelay (46); // 61.82us
}
else
{
uDelay (46); // 61.82us
wIn; // better releash the bus
uDelay (4); // 10.58us
}
}
Delay constrains have to be met but, the protocol timing
is not very strict. Onto the read routine ...
u8 wRxbit (void)
{
u8 data;
wOut;wL;
uDelay (0); // 10.58us
wIn;
uDelay (0); // 10.58us
data=wR;
uDelay (23); // 61.82us
return data;
}
Your time has come, after clearly understanding the above, you
have to implement the Reset/Presence signal. Lucky you!
|