📄 ds1820.c
字号:
#include "OPEX.h"
// DS1820.c
// (C) 2004 Steve Childress stevech@san.rr.com
// this math works for CPU clocks 1MHz or more
// CPU clock at 6000000 so 1/f = 0.16uSec = 160nsec
const int CLOCKS_PER_USEC = 1000 / 160; // 1000 nSec = 1uSec
// 8MHz = 125ns
// 10Mhz = 100ns
// 16MHz = 62ns
#define IODDR DDRA
#define OUTPORT PORTA
#define INPORT PINA
#define IOBIT 7
#define IOBITMASK 0x80
void report(OPEX_TCB *);
extern char StringBuf1[];
///////////////////////////////////////////////
// this will loop for about 250 microseconds, normal conditions
int onew_presence_check(void) // return 1 if presence of 1-wire chip(s) detected
{
BYTE t;
int ret = 0;
t = 0;
while ((INPORT & IOBITMASK) == 0) // should go hi after RC chargeup
if (++t == 0)
goto err0;
t = 0;
while ((INPORT & IOBITMASK) != 0) // should go low, presence pulse
if (++t == 0)
goto err0;
t = 0;
while ((INPORT & IOBITMASK) == 0) // should go hi at end of 240us presence pulse
if (++t == 0)
goto err0;
ret = 1;
err0:
return(ret);
}
void *onew_reset_tcb;
////////////////////////////////////////////////
void onew_reset_end(OPEX_TCB *me)
{
cli(); // presence pulse comes soon
sbi(OUTPORT, IOBIT); // unreset
cbi(IODDR, IOBIT); // pin is an input
if (onew_presence_check())
++me->state;
sei();
me->funcp = onew_reset_tcb;
OPEX_sched_resched(me, 0, 0, 0, 0, 0);
}
////////////////////////////////////////////////
void onew_reset_begin(OPEX_TCB *me)
{
sbi(IODDR, IOBIT); // output mode
cbi(OUTPORT, IOBIT); // begin the reset
onew_reset_tcb = me->funcp;
me->funcp = &onew_reset_end;
OPEX_sched_resched(me, 0, 0, 0, 0, 1);
}
////////////////////////////////////////////////
void onew_sendbit(BYTE d)
{
register int n; // must be two bytes
//cli();
cbi(OUTPORT, IOBIT); // start bit cell
n = (CLOCKS_PER_USEC * 6) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
if (d)
sbi(OUTPORT, IOBIT); // sending a 1
n = (CLOCKS_PER_USEC * 60) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(OUTPORT, IOBIT);
n = (CLOCKS_PER_USEC * 1) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
//sei();
}
//////////////////////////////////////////////////
void onew_send(BYTE b)
{
BYTE i;
sbi(IODDR, IOBIT); // output mode
cli(); // takes about 600 uSec for this loop
for (i = 1; i != 0; i <<= 1)
onew_sendbit( (b & i) != 0 );
sei();
}
/////////////////////////////////////////////////
// receive one bit from one wire.
// caller should have turned off interrupts
BYTE onew_receivebit(void)
{
BYTE b;
register int n;
sbi(IODDR, IOBIT); // make output
cbi(OUTPORT, IOBIT); // start bit cell
n = (CLOCKS_PER_USEC * 6) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(OUTPORT, IOBIT); // for pull up
cbi(IODDR, IOBIT); // make input
n = (CLOCKS_PER_USEC * 12) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
b = INPORT & IOBITMASK;
n = (CLOCKS_PER_USEC * 60) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
sbi(IODDR, IOBIT); // make output, port bit is 1
n = (CLOCKS_PER_USEC * 2) / 3; // compile-time math
while (--n) // delay, 3 clocks per loop iteration
;
return(b != 0);
}
/////////////////////////////////////////////////
BYTE onew_receive_byte(void)
{
BYTE b = 0;
BYTE i;
cli();
for (i = 8; i != 0; --i) {
b >>= 1;
if (onew_receivebit() != 0)
b |= 0x80;
}
sei();
return(b);
}
BYTE onew_data[9];
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
void DS1820(OPEX_TCB *me)
{
union {
int n;
BYTE b[2];
} temperature;
BYTE t;
char *p = NULL;
sbi(IODDR, IOBIT); // output
sbi(OUTPORT, IOBIT); // put a one on the bus, let it sit a while
//report(me);
switch(me->state) {
case 0:
++me->state;
onew_reset_begin(me); // skips next state if presence of chip(s) detected
break;
case 1:
goto err0; // error condition
break;
case 2:
onew_send(0xcc); // skip ROM, just one device
++me->state;
OPEX_sched_resched(me, 0, 0, 0, 0, 1);
break;
case 3:
++me->state;
onew_send(0x44); // convert command takes 750mSec
OPEX_sched_now(me);
OPEX_sched_resched(me, 0, 0, 0, 0, TicksPerSecond - (TicksPerSecond/4) );
break;
case 4:
++me->state;
onew_reset_begin(me); // skips next state if presence of chip(s) detected
break;
case 5:
goto err0;
break;
case 6:
++me->state;
onew_send(0xcc); // skip ROM, just one device
OPEX_sched_resched(me, 0, 0, 0, 0, 1);
break;
case 7:
onew_send(0xBE); // read scratchpad command
for (t = 0; t <= 8; ++t)
onew_data[t] = onew_receive_byte();
temperature.b[0] = onew_data[0];
temperature.b[1] = onew_data[1];
for (t = 0; t <= 8; ++t) {
sprintf_P(StringBuf1, PSTR(" %d 0x%X"), t, onew_data[t]);
OPEX_puts(StringBuf1);
}
OPEX_nl();
if (temperature.n >= 0)
t = (temperature.n & 1) ? 5 : 0;
else
t = (temperature.n & 1) ? 0 : 5;
sprintf_P(StringBuf1, PSTR(" Temp: %d.%d C 0x%X"), temperature.n/2, t, temperature.n);
OPEX_putline(StringBuf1);
if (temperature.n >= 0)
t = (temperature.n & 1) ? 5 : 0;
else
t = (temperature.n & 1) ? 0 : 5;
// temperature LSB is 2**-1.
temperature.n = ((18 * temperature.n) / 10) + (32*2); // mul by 10*1.8 divide by 10 add scaled 32
sprintf_P(StringBuf1, PSTR(" Temp: %d.%d F 0x%X"), temperature.n/2, t, temperature.n);
OPEX_putline(StringBuf1);
goto out;
break;
}
return; // reenter, with state variable set
err0:
sei();
p = PSTR("onew presence err");
out:
sbi(IODDR, IOBIT);
sbi(OUTPORT, IOBIT); // leave at 1
if (p != NULL)
OPEX_putline_P(p);
me->state = 0;
//OPEX_sched_resched(me, 0, 0, 0, 3, 0); // again later
OPEX_sched_quit();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -