Hello,
Have you actually observed the waveform on the one-wire bus with an oscilloscope, to see if the timing is reasonable. This may also reveal if there are any pin conflict issues. I think I can see a potential problem with your use of the DELAYUS() macro, within the following code.
char read_bit(void){
char i;
DisableInterrupts;
ONE_WIRE_SET_LOW
DELAYUS(1);
ONE_WIRE_SET_HIGH
ONE_WIRE_DELAY(10);
ONE_WIRE_DIR=0; // This would appear unnecessary
i=ONE_WIRE_PIN;
EnableInterrupts;
// You will need an additional delay here, say 48us, to reach the end of the bit period
return i;
}
.
This means that, with a 4 MHz bus, the X value will commence to decrement from zero, giving a pulse width of more than 1024 cycles. I wonder if this is the problem?
In this instance, it would appear better to pad out the ONE_WIRE_SET_LOW macro with additional NOPs, so that the output will remain low for a minimum of 1us for the highest bus frequency, to meet the requirements of the device.
I subsequently found a problem with the DELAYUS macro. The pragma is present to allow the use of immediate addressing within the inline code, but this is incompatible with the label format that allows multiple use of the macro within a single function. This consequently produced compile errors, which I presume you discovered. I solved this problem by calling a function/subroutine within the macro. This does increase the initial overhead, but this is now acceptable with a minimum delay requirement of 10us (with padding for the 1us requirement).
Further problems with your read_bit() code are that you are not globally disabling interrupts during the critical timing, and you are not waiting until the end of the bit period before exiting the function. The total bit period has a minimum of 60 microseconds, and you will be potentially attempting to read the next bit within this period.
You will also need to ascertain whether the global disabling of interrupts for the periods necessary for one-wire operation, will give problems for Zigbee operation.
Have you noticed that reading a bit is very similar to writing a one. It is therefore possible to use a single function for both read and write operations. Using this concept, to read a byte value, you would write a dummy byte value of 0xFF.
I have attached some code that uses this approach. For code simplicity, I am also using the carry flag (CF) to communicate with the function. This is possible, in this instance, because of the extensive use of inline assembly, which ensures that the compilation process does not corrupt the flag state.
The following code snippet shows the usage of the one-wire functions, based on my interpretation of the datasheet for the DS1822. I have not actually tested a device.
#include <hidef.h> /* EnableInterrupts macro */#include "derivative.h" /* peripheral declarations */#include "One-wire.h"#include "DS1822.h"// Global variables:SCRATCHPAD spad;...... // Start temperature conversion: if (OW_reset()) { (void)OW_byteproc( SKIP_ROM); (void)OW_byteproc( CONVERT_T); // Wait for conversion complete while (OW_byteproc( DUMMY) == 0x00) __RESET_WATCHDOG(); } // Get results from scratchpad: if (OW_reset()) { (void)OW_byteproc( SKIP_ROM); (void)OW_byteproc( READ_SPAD); // Read scratchpad data for (i = 0; i < 9; i++) { spad.array[i] = OW_byteproc( DUMMY); } }Note that the RTC module is not suited to timing intervals of tens of microseconds.
Regards,
Mac