Sie sind auf Seite 1von 5

1- Wire the thermometer

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 D518B20 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 Os. Reading 1s and Os 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.

I I set pin mask

#define wmask Ox08

II set ]-wire pin for output

#define wOut DDRA 1= wmask

II set ]-wire pin for input (bus released)

#define wIn DDRA &= -wmask

II set ]-wire bus high

#define wH PORTA 1= wmask

II set ]-wire bus low

#define wL PORTA &= -wmask

II get ]-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 ...

II delay = 5.70 + (].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 Fll 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 Os ....

void wTxbit (uS bit)
wout; wL;
if (bit)
uDelay (4) ; II 10.58us
wIn;
uDelay (46) ; II 61. 82us
else
uDelay (46) ; II 61. 82us
wIn; II better re1eash the bus
uDelay (4) ; II 10.58us Delay constrains have to be met but, the protocol timing is not very strict. Onto the read routine ...

uS wRxbit (void)

uS data;

wout; wL; uDelay (0); wIn;

uDelay (0); data=wR; uDelay (23);

II 10.58us

II 10.58us

1161.82us

return data;

Your time has come, after clearly understanding the above, you have to implement the Reset/Presence signal. Lucky you!

Commands up up and away Having the bits and getting to the bytes should be easy. Single thing to remeber here is communication happens least significant bit first. This is when you have a byte to send, you are going to send bitO first and bit7 last. I would suggest give it a go alone first, don't look, don't ...

void wTxbyte (uS data) {

uS i;

for (i=O; i<S; i++)

wTxbit (data & Ox01); data»=l;

For 8 times we mask the LSB bit and we send it. Each time, we shift for the next bit.

uS wRxbyte (void)

uS i, bit, data;

data=O;

for (i=O; i<S; i++)

bit=wRxbit() ; data I =bit«i;

return data;

For 8 times we read a bit and we place it in the data byte. Ohh, I was about to forget, in case you are in doubt about your l-wire Reset routine ....

uS Reset1Wire (void) {

uS present;

wout;wL;

uDe1ay (192); uDe1ay (193); 114Bl.10us wIn;

uDe1ay (46); 1161.B2us

present=wR;

uDe1ay (163); uDe1ay (164); 11410.34us

II 0 for device present! Sorry Reisga, Dave return present;

To be honest with you, the ResetlWire routine is the first you should write cause it gives feedback. By just sending bits over your l-wire it doesn't really tell you something. You can for example try to turn on the LED in case there is a thermo present. If you manage to make this one work you will also be sure about your timing calculations.

Reading this paragraph means that you have your low levell-wire stuff up and running and tested. If you just copy/pasted please let me know cause I am seriously thinking of bugging up my code. Whatever the case, its time to do the high level stuff. Give it a go, decide what you need and then go through. It looks pretty much straight forward ...

• First, we need to Reset our l-wire device and wait for the Presence signal.

• After we get it, we issue a Skip ROM command, we don't really need to address our slave.

• Then, we can tell our thermo to capture temperature data, this is the Convert

Temperature command.

• We need again to Reset our l-wire device and wait for the Presence signal.

• After we get it, we issue again a Skip ROM command to forse our thermo talk.

• Eventually, we will request the temperature data, this is the Read RAM command.

• What we get is a frame of 9 bytes, 2 for temperature, 6 for the thermo ID and 1 for the cyclic redundancy code.

The Convert Temperature and the Read RAM commands have to be separated, each one has to be preceded by a Reset and a Skip ROM command. To me, this was not clear from the beginning, I had to do many tests. So ... tell me what you think.

uS Reset1Wire (void) {

uS present;

wout;wL;

uDelay (192); uDelay (193); 114Bl.10us wIn;

uDelay (46); 1161.B2us

present=wR;

uDelay (163); uDelay (164); 11410.34us

II 0 for device present! Sorry Reisga, Dave return present;

You should know by now your thermo's unique ID and your room's temperature! You like it? I feel your excitement. Well, it does work. But, it is a bit crappy. No, not crappy just incomplete. Although it works? Yes, having something that works is not everything! Would you monitor your nuclear reactor's temperature with this routine? No? Why not?

By the way, you might be wondering if someone whispered to me the Delay values. No, I did many tests, sending bytes via the serial port with shorter delays.

Das könnte Ihnen auch gefallen