|
|
View previous topic :: View next topic |
Author |
Message |
Andrew Sheppard Guest
|
One wire bus |
Posted: Fri Mar 14, 2003 8:58 am |
|
|
Ok, I'm new to this. I've got the 12f675 and 16f84 up and running with some test programs - the usual (talking to a 2*40 LCD ok with the 16f84, blinking an LED with the 12f675.) These did not seem to be a problem at all. Actually worked out quite well. I'm quite impressed with the easy so far and was elated to see my messages come up on the LCD.
However, I want to run a one wire bus between the PICS with one 16f84 driving the LCD and displaying messages from another 16f84 and a 12f675. I have been looking at the pbusm.c example to implement a one wire bus. I've searched this forum for help and found one brief explanation of the code with respect to the "float high" concept which I understand.
Does anyone have a documented version of the code or other documented examples of a one wire bus.
Am I suppose to tie the Ext interupt line to the bus?
Any and all help is appreciated.
Thanks in advance.
Andrew
___________________________
This message was ported from CCS's old forum
Original Post ID: 12668 |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 12:33 pm |
|
|
If I understand you correctly then you are missing code for a PIC to emulate a one wire device.......as opposed to the PIC being the master controller of the one wire bus.
I used a simple RC network to time the RESET pulse and drive an interrupt into EXT-INT B0 in this case.
The dow line is read on a seperate bin TOUCH_PIN which must be the open drain pin EX a4
Float ( an input in disguise) is OK when you are the master since you always get to choose when you want to read. The slave must always be ready to be in read state but only when the DOW RESET pulse is received . A dallas hardware slave device is dedicated and always has data ready. The PIC slave will often be off doing something and may only have data partially ready or may be interrupted by the master because the master had higher priority things to do...so there is code to restart the slave and inform the master if the slave isn't quite ready
Anyway the code below might help get you started,
/// drivers for dallas slave device emulation ////////////
//// ///////////
//// electrical interface //////////
//// TOUCH_PIN should be open drain pulled up via 4.7K
//// to avoid loading dow when device id off
///// a high on the TOUCH_PIN switches the 2n7000 on ////////
///// holding cap 10nf at ground //////
//// a low on the TOUCH_PIN switches the 2n7000 off ////////
//// causing the 10nf cap to charge via R 33k ////////
//// after 10*nf*33k or 330us pin B0 is high ////////
//// any shorter time the voltage will not have risen enough /////
//// the next high on the dow (end of reset pulse ) /////
//// the 2n7000 conducts disharging the 10nf cap //////
//// In other words B0 goes from H to L on the rising edge at //////
//// completion of the reset pulse //////
//// diag //////
//// | Vdd +5V //////
//// | //////
//// > //////
//// R < 33K //////
//// > //////
//// | //////
//// |----------------------------->B0 //////
//// |-------__| D /////
//// | |_G________________TOUCHPIN /////
//// | __| | /////
//// | | | S 2n7000 | /////
//// | | | /////
/// C =====10nf | --- 5.6v /////
//// | | ^ zener /////
//// | | | /////
//// ^^^ ^^^ Vss (Gnd) ^^^ /////
//// /////
// major code needs to set these
// #define TOUCH_PIN PIN_XX
//byte const dev_id[8]={0xFE,0x00,0x24,0xC6,0x50,0x00,0x00,0x97};
int dow_status;
#define slave_ready 1
#define slave_busy 2
#define master_ready 3
#define slave_not_ready 4
#define PCLATH 0x0A
#define PCL 0x02
#define INTF 1
//#define INTCON 0x0B
#define INTE 4
///////////////////////////////PROTOCOL /////////////////////////////////////
// slave fills transmit buff xmit_buff and sets dow_status to slave_ready
// if slave is ready master reads '{' data in buff '}' Ex {25C65} or{T6963}
// if slave is not ready master reads '!' and polls again
// if slave is busy processing a previous command
// an interrupt may cause it to hang
// Ex master interrupts a read of a previous command in progress
// leaving slave waiting for write slots
// a normal isr path would return the slave to the place it is reading
// only now the master has a new command probably causing the slave to hang
// to avoid returning to the point of interrupt a PC of 00 is jammed on the stack
// causing a complete CPU reset in otherwords a reboot of the slave
//
// when slave is busy doing things other than processing a master command
// ( Ex. monitoring the key board ) it sets the status to slave_not_ready
// the isr will send '!' back to master during match_rom polls allowing master
// to wait and repoll with a match_rom
// If master suspects the slave is hung a search_rom will reboot the slave
//
byte dow_read_byte() {
/// master goes low for less than 15us
/// after 30 us from beginning slave samples
/// if high we have 1 if low we have zero
byte i,data;
for(i=1;i<=8;++i) {
while (input(TOUCH_PIN) ); // wait till line goes low
// line is now low master will either release for a 1 or keep low for a 0
delay_us(30); // sample point
shift_right(&data,1,input(TOUCH_PIN));
while(!input(TOUCH_PIN)); // wait till line is high
}
return(data);
}
byte dow_write_byte(byte data) {
/// master goes low for less than 15us
/// immediately slave goes low for an additional 15us to write 1
/// otherwise we allow line to float high
/// master samples within 5us of bringing the line low
byte i;
for(i=1;i<=8;++i)
{
while(input(TOUCH_PIN)); // wait for master to go low
if(shift_right(&data,1,0)) { output_float(TOUCH_PIN); }
else {
output_low(TOUCH_PIN);
}
delay_us(15);
output_float(TOUCH_PIN);
delay_us(40);
}
return(TRUE);
}
#INLINE
void dow_presence() {
// master held line low for a least 240us and then goes high for 20 us
// slave sends presence pulse of a low of 100us
while(!input(TOUCH_PIN)); //wait until line is high
delay_us(20);
// presence
output_low(TOUCH_PIN);
delay_us(100);
output_float(TOUCH_PIN);
while(!input(TOUCH_PIN)); // wait for other devices to finish presence pulse
}
#INLINE
byte dow_search_rom()
{
byte i,j,this_byte;
short int this_bit;
// master has sent an 0xF0 search rom command
// master sends two read time slots
// we the slave send our true bit and then its inverse
// master then sends a select bit and if it matches we stay online
// for another cycle otherwise we go offline and wait for a reset pulse
for(j=0;j<=7;j++)
{
this_byte=dev_id[j];
for(i=1;i<=8;++i)
{
this_bit=shift_right(&this_byte,1,0); // note protocol ships LSbit first
// send true bit
// wait for low
while (input(TOUCH_PIN)) ;
// we now are seeing low
if(this_bit) {
output_float(TOUCH_PIN);
} else {
output_low(TOUCH_PIN);
}
//delay_us(15);
delay_us(20);
output_float(TOUCH_PIN);
while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
// send inverse bit
// wait for low
while (input(TOUCH_PIN)) ;
if(!this_bit) {
output_float(TOUCH_PIN);
} else {
output_low(TOUCH_PIN);
}
//delay_us(15);
delay_us(20);
output_float(TOUCH_PIN);
while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
// now see if master wants us if it does then it will write our bit
// read a bit
// wait for low
while (input(TOUCH_PIN)) ;
delay_us(20); // sample point
if(this_bit!=input(TOUCH_PIN)) return(FALSE);
while(!input(TOUCH_PIN) ); // wait till line goes high
}// i loop
}// j loop
return(TRUE);
}
#INLINE
byte dow_match_rom()
{
byte i,j,this_byte;
short int this_bit;
// master has sent an 0x55 match rom command
// master then sends a select bit and if it matches we stay online
// for another cycle otherwise we go offline and wait for a reset pulse
for (j=0;j<=7;j++)
{
this_byte=dev_id[j];
for(i=1;i<=8;++i)
{
this_bit=shift_right(&this_byte,1,0); // note rs232 ships LSBit first
// read a bit
// wait for low
while (input(TOUCH_PIN)) ;
delay_us(20); // sample point
if(this_bit!=input(TOUCH_PIN)) return (FALSE);
while(!input(TOUCH_PIN)); // wait till line is high
}// of i loop
}// of j loop
return(TRUE);
}
int compcrc(char * string, int nbytes)
{
int crc,i,count;
char input;
crc=0;
for (i=0;i
input=*(string+i);
#asm
movlw 8
movwf count
/* need to xor bit 0 of crc with next bit of input */
crc_loop:
movf crc,w
rrf input,f // rot right and save and next bit is in carry
btfsc status,carry
// need to know if xor result is a one or zero
// if carry is 0 then xor with zero = value of crc bit 0
// else carry is 1 xor with one = comp of crc bit 0
goto cbit_1
goto cbit_0
cbit_1:
// carry=input was 1
btfss crc,0
goto xor_bit1 // was 0 so complement to 1
goto xor_bit0 // was 1 so complement to 0
cbit_0:
// carry=input was 0
btfss crc,0
goto xor_bit0 // was 0
goto xor_bit1 // was 1
xor_bit1:
xorlw 0x18 // xors bits 4 and 5
movwf crc
rrf crc,f
bsf crc,7
goto loop_test
xor_bit0:
movwf crc
rrf crc,f
bcf crc,7
loop_test:
decfsz count,f
goto crc_loop
#endasm
}
return(crc);
}
#inline
void abort()
{
#asm
bcf INTCON,INTE /// turn off EXT_INT
bcf INTCON,INTF /// Clear the flag to avoid a repeat
clrf PCLATH /// clear high bits of progran counter
clrf PCL /// clear the low bits CPU will now restart
#endasm
}
#INT_EXT
void ext_int_isr()
{
byte cmd,i;
if (dow_status==slave_busy) abort(); /// not expecting an interrupt
/// master will have to reset again
/// after pausing to allow us to re-init
/// this clears up any glitches
dow_presence();
cmd=dow_read_byte();
if (cmd==0xF0) { //search rom
//------------------------------------------------------------------------
//-------------------------------------------------------------------------
if (!dow_search_rom()) goto quit;
if(dow_status==slave_not_ready) abort(); // slave was hung up
goto quit; // we are selected but will wait for a 0x55
}
if (cmd==0x55){ // match rom
if (!dow_match_rom()) goto quit;
// we are now selected and wait for master to read
if (dow_status==slave_ready)
{
#ifdef LED1
output_high(LED1);
#endif
dow_write_byte('{');
// send out id sentence of Eg.T6963
for(i=0;i<=7;i++)
{
if (dev_name[i]==0) break; // null terminated
dow_write_byte(dev_name[i]);
}
dow_write_byte('}');
#ifdef BUFF_SIZE
for(i=0;i
#endif
#ifdef LED1
output_low(LED1);
#endif
dow_status=master_ready; // master next will send commands
}
else dow_write_byte('!');// slave is not ready master will have to wait
// for slave to assert status slave_ready
// or send FO to reset
}
quit:
output_float(TOUCH_PIN);
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12672 |
|
|
Hans Wedemeyer Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 12:33 pm |
|
|
If you want to implement a 1-Wire connection between two PIC's you have to do the grunt work at each end.
Visit the Maxim/Dallas Semi. site and you will find several docs. describing the protocol.
I do not recommend you do it that way.... lots of work and could be difficult to debug without an emulator.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12673 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 12:33 pm |
|
|
:=
:=Does anyone have a documented version of the code or other documented examples of a one wire bus.
:=
:=Am I suppose to tie the Ext interupt line to the bus?
:=
---------------------------------------------------------
I have never tested that example. They do have a faq page
on it. <a href="http://www.ccsinfo.com/faq/?23" TARGET="_blank">http://www.ccsinfo.com/faq/?23</a>
Yes, they use the External Interrupt line. This is Pin B0 for
the 16F84 and GP2 for the 12F675.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12674 |
|
|
Andrew Sheppard Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 1:56 pm |
|
|
:=:=
:=:=Does anyone have a documented version of the code or other documented examples of a one wire bus.
:=:=
:=:=Am I suppose to tie the Ext interupt line to the bus?
:=:=
:=---------------------------------------------------------
:=I have never tested that example. They do have a faq page
:=on it. <a href="http://www.ccsinfo.com/faq/?23" TARGET="_blank"> <a href="http://www.ccsinfo.com/faq/?23" TARGET="_blank">http://www.ccsinfo.com/faq/?23</a></a>
:=Yes, they use the External Interrupt line. This is Pin B0 for
:=the 16F84 and GP2 for the 12F675.
Clarification, Am I to tie BOTH pins (an i/o pin and the interrupt pin) to the bus. I'm getting from your comment that I ONLY tie the interrupt line to the bus.
It is the faq page that first got me interested in this. Thanks for the link anyway.
Andrew
___________________________
This message was ported from CCS's old forum
Original Post ID: 12677 |
|
|
Andrew Sheppard Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 2:00 pm |
|
|
:=If you want to implement a 1-Wire connection between two PIC's you have to do the grunt work at each end.
:=
:=Visit the Maxim/Dallas Semi. site and you will find several docs. describing the protocol.
:=
:=I do not recommend you do it that way.... lots of work and could be difficult to debug without an emulator.
Relating to your comments above
1. By grunt work I assume you mean monitoring the line and responding accordingly?
2. Is this the same as the 1-wire examle from CCS - I am under the impression that it is not???
3. Ok, what do you recommend. I'm open for suggestions. I'm assuming this mode of com is common between picks??
Thanks
Andrew
___________________________
This message was ported from CCS's old forum
Original Post ID: 12678 |
|
|
Andrew Sheppard Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 2:04 pm |
|
|
My understanding of the pbusm example is that there is no master. Each PIC monitors the bus and waits until it is "quite" before communicating.
I am not as concerned to emulate a one wire device such as the Dallas devices as I am to simply provide communications between devices (controllers).
Any further comments to alleviate my fog?
Andrew
:=If I understand you correctly then you are missing code for a PIC to emulate a one wire device.......as opposed to the PIC being the master controller of the one wire bus.
:=I used a simple RC network to time the RESET pulse and drive an interrupt into EXT-INT B0 in this case.
:=The dow line is read on a seperate bin TOUCH_PIN which must be the open drain pin EX a4
:=Float ( an input in disguise) is OK when you are the master since you always get to choose when you want to read. The slave must always be ready to be in read state but only when the DOW RESET pulse is received . A dallas hardware slave device is dedicated and always has data ready. The PIC slave will often be off doing something and may only have data partially ready or may be interrupted by the master because the master had higher priority things to do...so there is code to restart the slave and inform the master if the slave isn't quite ready
:=
:=
:=Anyway the code below might help get you started,
:=
:=
:=
:=/// drivers for dallas slave device emulation ////////////
:=//// ///////////
:=//// electrical interface //////////
:=//// TOUCH_PIN should be open drain pulled up via 4.7K
:=//// to avoid loading dow when device id off
:=///// a high on the TOUCH_PIN switches the 2n7000 on ////////
:=///// holding cap 10nf at ground //////
:=//// a low on the TOUCH_PIN switches the 2n7000 off ////////
:=//// causing the 10nf cap to charge via R 33k ////////
:=//// after 10*nf*33k or 330us pin B0 is high ////////
:=//// any shorter time the voltage will not have risen enough /////
:=//// the next high on the dow (end of reset pulse ) /////
:=//// the 2n7000 conducts disharging the 10nf cap //////
:=//// In other words B0 goes from H to L on the rising edge at //////
:=//// completion of the reset pulse //////
:=//// diag //////
:=//// | Vdd +5V //////
:=//// | //////
:=//// > //////
:=//// R < 33K //////
:=//// > //////
:=//// | //////
:=//// |----------------------------->B0 //////
:=//// |-------__| D /////
:=//// | |_G________________TOUCHPIN /////
:=//// | __| | /////
:=//// | | | S 2n7000 | /////
:=//// | | | /////
:=/// C =====10nf | --- 5.6v /////
:=//// | | ^ zener /////
:=//// | | | /////
:=//// ^^^ ^^^ Vss (Gnd) ^^^ /////
:=//// /////
:=
:=
:=
:=
:=// major code needs to set these
:=
:=// #define TOUCH_PIN PIN_XX
:=
:=//byte const dev_id[8]={0xFE,0x00,0x24,0xC6,0x50,0x00,0x00,0x97};
:=
:=int dow_status;
:=#define slave_ready 1
:=#define slave_busy 2
:=#define master_ready 3
:=#define slave_not_ready 4
:=#define PCLATH 0x0A
:=#define PCL 0x02
:=#define INTF 1
:=//#define INTCON 0x0B
:=#define INTE 4
:=///////////////////////////////PROTOCOL /////////////////////////////////////
:=// slave fills transmit buff xmit_buff and sets dow_status to slave_ready
:=// if slave is ready master reads '{' data in buff '}' Ex {25C65} or{T6963}
:=// if slave is not ready master reads '!' and polls again
:=// if slave is busy processing a previous command
:=// an interrupt may cause it to hang
:=// Ex master interrupts a read of a previous command in progress
:=// leaving slave waiting for write slots
:=// a normal isr path would return the slave to the place it is reading
:=// only now the master has a new command probably causing the slave to hang
:=// to avoid returning to the point of interrupt a PC of 00 is jammed on the stack
:=// causing a complete CPU reset in otherwords a reboot of the slave
:=//
:=// when slave is busy doing things other than processing a master command
:=// ( Ex. monitoring the key board ) it sets the status to slave_not_ready
:=// the isr will send '!' back to master during match_rom polls allowing master
:=// to wait and repoll with a match_rom
:=// If master suspects the slave is hung a search_rom will reboot the slave
:=//
:=
:=
:=
:=
:=
:=
:=
:=byte dow_read_byte() {
:=/// master goes low for less than 15us
:=/// after 30 us from beginning slave samples
:=/// if high we have 1 if low we have zero
:=
:= byte i,data;
:=
:=
:=
:= for(i=1;i<=8;++i) {
:=
:= while (input(TOUCH_PIN) ); // wait till line goes low
:=
:= // line is now low master will either release for a 1 or keep low for a 0
:=
:= delay_us(30); // sample point
:= shift_right(&data,1,input(TOUCH_PIN));
:=
:= while(!input(TOUCH_PIN)); // wait till line is high
:=
:= }
:=
:=
:=return(data);
:=}
:=
:=
:=byte dow_write_byte(byte data) {
:=/// master goes low for less than 15us
:=/// immediately slave goes low for an additional 15us to write 1
:=/// otherwise we allow line to float high
:=/// master samples within 5us of bringing the line low
:= byte i;
:=
:= for(i=1;i<=8;++i)
:= {
:= while(input(TOUCH_PIN)); // wait for master to go low
:=
:= if(shift_right(&data,1,0)) { output_float(TOUCH_PIN); }
:=
:= else {
:=
:= output_low(TOUCH_PIN);
:=
:=
:= }
:= delay_us(15);
:= output_float(TOUCH_PIN);
:= delay_us(40);
:=
:= }
:= return(TRUE);
:=}
:=
:=#INLINE
:= void dow_presence() {
:=
:=// master held line low for a least 240us and then goes high for 20 us
:=// slave sends presence pulse of a low of 100us
:=
:= while(!input(TOUCH_PIN)); //wait until line is high
:=
:=
:= delay_us(20);
:= // presence
:= output_low(TOUCH_PIN);
:= delay_us(100);
:= output_float(TOUCH_PIN);
:=
:= while(!input(TOUCH_PIN)); // wait for other devices to finish presence pulse
:=
:=
:=}
:=
:=#INLINE
:=byte dow_search_rom()
:={
:= byte i,j,this_byte;
:= short int this_bit;
:=// master has sent an 0xF0 search rom command
:=// master sends two read time slots
:=// we the slave send our true bit and then its inverse
:=// master then sends a select bit and if it matches we stay online
:=// for another cycle otherwise we go offline and wait for a reset pulse
:=
:=for(j=0;j<=7;j++)
:= {
:=
:= this_byte=dev_id[j];
:=
:= for(i=1;i<=8;++i)
:= {
:=
:= this_bit=shift_right(&this_byte,1,0); // note protocol ships LSbit first
:=
:= // send true bit
:=
:= // wait for low
:=
:= while (input(TOUCH_PIN)) ;
:=
:= // we now are seeing low
:= if(this_bit) {
:= output_float(TOUCH_PIN);
:=
:= } else {
:= output_low(TOUCH_PIN);
:=
:= }
:= //delay_us(15);
:= delay_us(20);
:= output_float(TOUCH_PIN);
:=
:= while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
:=
:=// send inverse bit
:=
:=// wait for low
:=
:= while (input(TOUCH_PIN)) ;
:=
:= if(!this_bit) {
:= output_float(TOUCH_PIN);
:=
:= } else {
:= output_low(TOUCH_PIN);
:=
:= }
:= //delay_us(15);
:= delay_us(20);
:= output_float(TOUCH_PIN);
:=
:= while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
:=
:=// now see if master wants us if it does then it will write our bit
:=
:=// read a bit
:= // wait for low
:=
:= while (input(TOUCH_PIN)) ;
:=
:= delay_us(20); // sample point
:=
:= if(this_bit!=input(TOUCH_PIN)) return(FALSE);
:=
:=
:= while(!input(TOUCH_PIN) ); // wait till line goes high
:=
:= }// i loop
:=}// j loop
:=
:=return(TRUE);
:=}
:=#INLINE
:=byte dow_match_rom()
:={
:= byte i,j,this_byte;
:= short int this_bit;
:=// master has sent an 0x55 match rom command
:=// master then sends a select bit and if it matches we stay online
:=// for another cycle otherwise we go offline and wait for a reset pulse
:=
:=
:=
:=for (j=0;j<=7;j++)
:= {
:= this_byte=dev_id[j];
:= for(i=1;i<=8;++i)
:= {
:=
:= this_bit=shift_right(&this_byte,1,0); // note rs232 ships LSBit first
:=
:=
:=
:=// read a bit
:= // wait for low
:=
:= while (input(TOUCH_PIN)) ;
:=
:= delay_us(20); // sample point
:=
:= if(this_bit!=input(TOUCH_PIN)) return (FALSE);
:=
:= while(!input(TOUCH_PIN)); // wait till line is high
:=
:=
:= }// of i loop
:=}// of j loop
:=return(TRUE);
:=}
:=
:=
:=int compcrc(char * string, int nbytes)
:={
:=int crc,i,count;
:=char input;
:=crc=0;
:= for (i=0;i
:= input=*(string+i);
:=#asm
:=movlw 8
:=movwf count
:=/* need to xor bit 0 of crc with next bit of input */
:=crc_loop:
:=movf crc,w
:=rrf input,f // rot right and save and next bit is in carry
:=btfsc status,carry
:=// need to know if xor result is a one or zero
:=// if carry is 0 then xor with zero = value of crc bit 0
:=// else carry is 1 xor with one = comp of crc bit 0
:=goto cbit_1
:=goto cbit_0
:=
:=cbit_1:
:=// carry=input was 1
:=btfss crc,0
:=goto xor_bit1 // was 0 so complement to 1
:=goto xor_bit0 // was 1 so complement to 0
:=
:=cbit_0:
:=// carry=input was 0
:=
:=btfss crc,0
:=goto xor_bit0 // was 0
:=goto xor_bit1 // was 1
:=
:=xor_bit1:
:=xorlw 0x18 // xors bits 4 and 5
:=movwf crc
:=rrf crc,f
:=bsf crc,7
:=goto loop_test
:=
:=xor_bit0:
:=movwf crc
:=rrf crc,f
:=bcf crc,7
:=
:=loop_test:
:=decfsz count,f
:=goto crc_loop
:=
:=#endasm
:=}
:=return(crc);
:=}
:=
:=#inline
:=void abort()
:={
:=#asm
:=bcf INTCON,INTE /// turn off EXT_INT
:=bcf INTCON,INTF /// Clear the flag to avoid a repeat
:=clrf PCLATH /// clear high bits of progran counter
:=clrf PCL /// clear the low bits CPU will now restart
:=#endasm
:=}
:=
:=#INT_EXT
:=void ext_int_isr()
:={
:=byte cmd,i;
:=
:=if (dow_status==slave_busy) abort(); /// not expecting an interrupt
:= /// master will have to reset again
:= /// after pausing to allow us to re-init
:= /// this clears up any glitches
:=
:=dow_presence();
:=cmd=dow_read_byte();
:=
:=
:=if (cmd==0xF0) { //search rom
:=//------------------------------------------------------------------------
:=
:=//-------------------------------------------------------------------------
:= if (!dow_search_rom()) goto quit;
:= if(dow_status==slave_not_ready) abort(); // slave was hung up
:= goto quit; // we are selected but will wait for a 0x55
:= }
:=
:=if (cmd==0x55){ // match rom
:=
:= if (!dow_match_rom()) goto quit;
:=
:= // we are now selected and wait for master to read
:=
:= if (dow_status==slave_ready)
:= {
:=#ifdef LED1
:= output_high(LED1);
:=#endif
:= dow_write_byte('{');
:= // send out id sentence of Eg.T6963
:= for(i=0;i<=7;i++)
:= {
:= if (dev_name[i]==0) break; // null terminated
:= dow_write_byte(dev_name[i]);
:= }
:= dow_write_byte('}');
:=#ifdef BUFF_SIZE
:= for(i=0;i
:=#endif
:=
:=#ifdef LED1
:= output_low(LED1);
:=#endif
:= dow_status=master_ready; // master next will send commands
:= }
:= else dow_write_byte('!');// slave is not ready master will have to wait
:= // for slave to assert status slave_ready
:= // or send FO to reset
:= }
:=
:=quit:
:=output_float(TOUCH_PIN);
:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12679 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 2:37 pm |
|
|
:=Clarification, Am I to tie BOTH pins (an i/o pin and the interrupt pin) to the bus. I'm getting from your comment that I ONLY tie the interrupt line to the bus.
:=
----------------------------------------------------------
No. You only use one pin on each PIC. Use the INT_EXT pin.
This is shown in the schematic in the FAQ, and in the
instructions at the top of the EX_PBUSM.C file.
(Of course, you do need a common ground connection between
the two PICs).
___________________________
This message was ported from CCS's old forum
Original Post ID: 12682 |
|
|
Freddie L Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 10:12 pm |
|
|
If you simply want to provide communication between two PICs why not use RS232? This would require 2 wires, one for Tx and one for Rx. CCS provides built-in commnads to configure any port for RS232 Tx or Rx. Reference the User Manual or search the list for RS232 to find many examples.
:=My understanding of the pbusm example is that there is no master. Each PIC monitors the bus and waits until it is "quite" before communicating.
:=
:=I am not as concerned to emulate a one wire device such as the Dallas devices as I am to simply provide communications between devices (controllers).
:=
:=Any further comments to alleviate my fog?
:=
:=Andrew
:=
:=
:=
:=:=If I understand you correctly then you are missing code for a PIC to emulate a one wire device.......as opposed to the PIC being the master controller of the one wire bus.
:=:=I used a simple RC network to time the RESET pulse and drive an interrupt into EXT-INT B0 in this case.
:=:=The dow line is read on a seperate bin TOUCH_PIN which must be the open drain pin EX a4
:=:=Float ( an input in disguise) is OK when you are the master since you always get to choose when you want to read. The slave must always be ready to be in read state but only when the DOW RESET pulse is received . A dallas hardware slave device is dedicated and always has data ready. The PIC slave will often be off doing something and may only have data partially ready or may be interrupted by the master because the master had higher priority things to do...so there is code to restart the slave and inform the master if the slave isn't quite ready
:=:=
:=:=
:=:=Anyway the code below might help get you started,
:=:=
:=:=
:=:=
:=:=/// drivers for dallas slave device emulation ////////////
:=:=//// ///////////
:=:=//// electrical interface //////////
:=:=//// TOUCH_PIN should be open drain pulled up via 4.7K
:=:=//// to avoid loading dow when device id off
:=:=///// a high on the TOUCH_PIN switches the 2n7000 on ////////
:=:=///// holding cap 10nf at ground //////
:=:=//// a low on the TOUCH_PIN switches the 2n7000 off ////////
:=:=//// causing the 10nf cap to charge via R 33k ////////
:=:=//// after 10*nf*33k or 330us pin B0 is high ////////
:=:=//// any shorter time the voltage will not have risen enough /////
:=:=//// the next high on the dow (end of reset pulse ) /////
:=:=//// the 2n7000 conducts disharging the 10nf cap //////
:=:=//// In other words B0 goes from H to L on the rising edge at //////
:=:=//// completion of the reset pulse //////
:=:=//// diag //////
:=:=//// | Vdd +5V //////
:=:=//// | //////
:=:=//// > //////
:=:=//// R < 33K //////
:=:=//// > //////
:=:=//// | //////
:=:=//// |----------------------------->B0 //////
:=:=//// |-------__| D /////
:=:=//// | |_G________________TOUCHPIN /////
:=:=//// | __| | /////
:=:=//// | | | S 2n7000 | /////
:=:=//// | | | /////
:=:=/// C =====10nf | --- 5.6v /////
:=:=//// | | ^ zener /////
:=:=//// | | | /////
:=:=//// ^^^ ^^^ Vss (Gnd) ^^^ /////
:=:=//// /////
:=:=
:=:=
:=:=
:=:=
:=:=// major code needs to set these
:=:=
:=:=// #define TOUCH_PIN PIN_XX
:=:=
:=:=//byte const dev_id[8]={0xFE,0x00,0x24,0xC6,0x50,0x00,0x00,0x97};
:=:=
:=:=int dow_status;
:=:=#define slave_ready 1
:=:=#define slave_busy 2
:=:=#define master_ready 3
:=:=#define slave_not_ready 4
:=:=#define PCLATH 0x0A
:=:=#define PCL 0x02
:=:=#define INTF 1
:=:=//#define INTCON 0x0B
:=:=#define INTE 4
:=:=///////////////////////////////PROTOCOL /////////////////////////////////////
:=:=// slave fills transmit buff xmit_buff and sets dow_status to slave_ready
:=:=// if slave is ready master reads '{' data in buff '}' Ex {25C65} or{T6963}
:=:=// if slave is not ready master reads '!' and polls again
:=:=// if slave is busy processing a previous command
:=:=// an interrupt may cause it to hang
:=:=// Ex master interrupts a read of a previous command in progress
:=:=// leaving slave waiting for write slots
:=:=// a normal isr path would return the slave to the place it is reading
:=:=// only now the master has a new command probably causing the slave to hang
:=:=// to avoid returning to the point of interrupt a PC of 00 is jammed on the stack
:=:=// causing a complete CPU reset in otherwords a reboot of the slave
:=:=//
:=:=// when slave is busy doing things other than processing a master command
:=:=// ( Ex. monitoring the key board ) it sets the status to slave_not_ready
:=:=// the isr will send '!' back to master during match_rom polls allowing master
:=:=// to wait and repoll with a match_rom
:=:=// If master suspects the slave is hung a search_rom will reboot the slave
:=:=//
:=:=
:=:=
:=:=
:=:=
:=:=
:=:=
:=:=
:=:=byte dow_read_byte() {
:=:=/// master goes low for less than 15us
:=:=/// after 30 us from beginning slave samples
:=:=/// if high we have 1 if low we have zero
:=:=
:=:= byte i,data;
:=:=
:=:=
:=:=
:=:= for(i=1;i<=8;++i) {
:=:=
:=:= while (input(TOUCH_PIN) ); // wait till line goes low
:=:=
:=:= // line is now low master will either release for a 1 or keep low for a 0
:=:=
:=:= delay_us(30); // sample point
:=:= shift_right(&data,1,input(TOUCH_PIN));
:=:=
:=:= while(!input(TOUCH_PIN)); // wait till line is high
:=:=
:=:= }
:=:=
:=:=
:=:=return(data);
:=:=}
:=:=
:=:=
:=:=byte dow_write_byte(byte data) {
:=:=/// master goes low for less than 15us
:=:=/// immediately slave goes low for an additional 15us to write 1
:=:=/// otherwise we allow line to float high
:=:=/// master samples within 5us of bringing the line low
:=:= byte i;
:=:=
:=:= for(i=1;i<=8;++i)
:=:= {
:=:= while(input(TOUCH_PIN)); // wait for master to go low
:=:=
:=:= if(shift_right(&data,1,0)) { output_float(TOUCH_PIN); }
:=:=
:=:= else {
:=:=
:=:= output_low(TOUCH_PIN);
:=:=
:=:=
:=:= }
:=:= delay_us(15);
:=:= output_float(TOUCH_PIN);
:=:= delay_us(40);
:=:=
:=:= }
:=:= return(TRUE);
:=:=}
:=:=
:=:=#INLINE
:=:= void dow_presence() {
:=:=
:=:=// master held line low for a least 240us and then goes high for 20 us
:=:=// slave sends presence pulse of a low of 100us
:=:=
:=:= while(!input(TOUCH_PIN)); //wait until line is high
:=:=
:=:=
:=:= delay_us(20);
:=:= // presence
:=:= output_low(TOUCH_PIN);
:=:= delay_us(100);
:=:= output_float(TOUCH_PIN);
:=:=
:=:= while(!input(TOUCH_PIN)); // wait for other devices to finish presence pulse
:=:=
:=:=
:=:=}
:=:=
:=:=#INLINE
:=:=byte dow_search_rom()
:=:={
:=:= byte i,j,this_byte;
:=:= short int this_bit;
:=:=// master has sent an 0xF0 search rom command
:=:=// master sends two read time slots
:=:=// we the slave send our true bit and then its inverse
:=:=// master then sends a select bit and if it matches we stay online
:=:=// for another cycle otherwise we go offline and wait for a reset pulse
:=:=
:=:=for(j=0;j<=7;j++)
:=:= {
:=:=
:=:= this_byte=dev_id[j];
:=:=
:=:= for(i=1;i<=8;++i)
:=:= {
:=:=
:=:= this_bit=shift_right(&this_byte,1,0); // note protocol ships LSbit first
:=:=
:=:= // send true bit
:=:=
:=:= // wait for low
:=:=
:=:= while (input(TOUCH_PIN)) ;
:=:=
:=:= // we now are seeing low
:=:= if(this_bit) {
:=:= output_float(TOUCH_PIN);
:=:=
:=:= } else {
:=:= output_low(TOUCH_PIN);
:=:=
:=:= }
:=:= //delay_us(15);
:=:= delay_us(20);
:=:= output_float(TOUCH_PIN);
:=:=
:=:= while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
:=:=
:=:=// send inverse bit
:=:=
:=:=// wait for low
:=:=
:=:= while (input(TOUCH_PIN)) ;
:=:=
:=:= if(!this_bit) {
:=:= output_float(TOUCH_PIN);
:=:=
:=:= } else {
:=:= output_low(TOUCH_PIN);
:=:=
:=:= }
:=:= //delay_us(15);
:=:= delay_us(20);
:=:= output_float(TOUCH_PIN);
:=:=
:=:= while(!input(TOUCH_PIN)); // wait until another device (if any) finishes writing 1
:=:=
:=:=// now see if master wants us if it does then it will write our bit
:=:=
:=:=// read a bit
:=:= // wait for low
:=:=
:=:= while (input(TOUCH_PIN)) ;
:=:=
:=:= delay_us(20); // sample point
:=:=
:=:= if(this_bit!=input(TOUCH_PIN)) return(FALSE);
:=:=
:=:=
:=:= while(!input(TOUCH_PIN) ); // wait till line goes high
:=:=
:=:= }// i loop
:=:=}// j loop
:=:=
:=:=return(TRUE);
:=:=}
:=:=#INLINE
:=:=byte dow_match_rom()
:=:={
:=:= byte i,j,this_byte;
:=:= short int this_bit;
:=:=// master has sent an 0x55 match rom command
:=:=// master then sends a select bit and if it matches we stay online
:=:=// for another cycle otherwise we go offline and wait for a reset pulse
:=:=
:=:=
:=:=
:=:=for (j=0;j<=7;j++)
:=:= {
:=:= this_byte=dev_id[j];
:=:= for(i=1;i<=8;++i)
:=:= {
:=:=
:=:= this_bit=shift_right(&this_byte,1,0); // note rs232 ships LSBit first
:=:=
:=:=
:=:=
:=:=// read a bit
:=:= // wait for low
:=:=
:=:= while (input(TOUCH_PIN)) ;
:=:=
:=:= delay_us(20); // sample point
:=:=
:=:= if(this_bit!=input(TOUCH_PIN)) return (FALSE);
:=:=
:=:= while(!input(TOUCH_PIN)); // wait till line is high
:=:=
:=:=
:=:= }// of i loop
:=:=}// of j loop
:=:=return(TRUE);
:=:=}
:=:=
:=:=
:=:=int compcrc(char * string, int nbytes)
:=:={
:=:=int crc,i,count;
:=:=char input;
:=:=crc=0;
:=:= for (i=0;i
:=:= input=*(string+i);
:=:=#asm
:=:=movlw 8
:=:=movwf count
:=:=/* need to xor bit 0 of crc with next bit of input */
:=:=crc_loop:
:=:=movf crc,w
:=:=rrf input,f // rot right and save and next bit is in carry
:=:=btfsc status,carry
:=:=// need to know if xor result is a one or zero
:=:=// if carry is 0 then xor with zero = value of crc bit 0
:=:=// else carry is 1 xor with one = comp of crc bit 0
:=:=goto cbit_1
:=:=goto cbit_0
:=:=
:=:=cbit_1:
:=:=// carry=input was 1
:=:=btfss crc,0
:=:=goto xor_bit1 // was 0 so complement to 1
:=:=goto xor_bit0 // was 1 so complement to 0
:=:=
:=:=cbit_0:
:=:=// carry=input was 0
:=:=
:=:=btfss crc,0
:=:=goto xor_bit0 // was 0
:=:=goto xor_bit1 // was 1
:=:=
:=:=xor_bit1:
:=:=xorlw 0x18 // xors bits 4 and 5
:=:=movwf crc
:=:=rrf crc,f
:=:=bsf crc,7
:=:=goto loop_test
:=:=
:=:=xor_bit0:
:=:=movwf crc
:=:=rrf crc,f
:=:=bcf crc,7
:=:=
:=:=loop_test:
:=:=decfsz count,f
:=:=goto crc_loop
:=:=
:=:=#endasm
:=:=}
:=:=return(crc);
:=:=}
:=:=
:=:=#inline
:=:=void abort()
:=:={
:=:=#asm
:=:=bcf INTCON,INTE /// turn off EXT_INT
:=:=bcf INTCON,INTF /// Clear the flag to avoid a repeat
:=:=clrf PCLATH /// clear high bits of progran counter
:=:=clrf PCL /// clear the low bits CPU will now restart
:=:=#endasm
:=:=}
:=:=
:=:=#INT_EXT
:=:=void ext_int_isr()
:=:={
:=:=byte cmd,i;
:=:=
:=:=if (dow_status==slave_busy) abort(); /// not expecting an interrupt
:=:= /// master will have to reset again
:=:= /// after pausing to allow us to re-init
:=:= /// this clears up any glitches
:=:=
:=:=dow_presence();
:=:=cmd=dow_read_byte();
:=:=
:=:=
:=:=if (cmd==0xF0) { //search rom
:=:=//------------------------------------------------------------------------
:=:=
:=:=//-------------------------------------------------------------------------
:=:= if (!dow_search_rom()) goto quit;
:=:= if(dow_status==slave_not_ready) abort(); // slave was hung up
:=:= goto quit; // we are selected but will wait for a 0x55
:=:= }
:=:=
:=:=if (cmd==0x55){ // match rom
:=:=
:=:= if (!dow_match_rom()) goto quit;
:=:=
:=:= // we are now selected and wait for master to read
:=:=
:=:= if (dow_status==slave_ready)
:=:= {
:=:=#ifdef LED1
:=:= output_high(LED1);
:=:=#endif
:=:= dow_write_byte('{');
:=:= // send out id sentence of Eg.T6963
:=:= for(i=0;i<=7;i++)
:=:= {
:=:= if (dev_name[i]==0) break; // null terminated
:=:= dow_write_byte(dev_name[i]);
:=:= }
:=:= dow_write_byte('}');
:=:=#ifdef BUFF_SIZE
:=:= for(i=0;i
:=:=#endif
:=:=
:=:=#ifdef LED1
:=:= output_low(LED1);
:=:=#endif
:=:= dow_status=master_ready; // master next will send commands
:=:= }
:=:= else dow_write_byte('!');// slave is not ready master will have to wait
:=:= // for slave to assert status slave_ready
:=:= // or send FO to reset
:=:= }
:=:=
:=:=quit:
:=:=output_float(TOUCH_PIN);
:=:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12697 |
|
|
Hans Wedemeyer Guest
|
Re: One wire bus |
Posted: Fri Mar 14, 2003 10:20 pm |
|
|
:=Relating to your comments above
:=1. By grunt work I assume you mean monitoring the line and responding accordingly?
Well you got lucky someone did it for you !
<a href="http://www.pic-c.com/forum/general/posts/12672.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/12672.html</a>
:=3. Ok, what do you recommend. I'm open for suggestions. I'm assuming this mode of com is common between picks??
There are several questions I would ask first.
Are you really limited to 1 wire and Common Ground ?
Do you need bi-directional communication ?
What kind of data rate ?
Is this a Master/Slave scenario ?
How critical is the other code, can it be interrupted while communications takes place or must it perform some functions during communications ?
etc. etc.
Based upon the answer I would then determin what best fits.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12698 |
|
|
j_purbrick Guest
|
Re: One wire bus |
Posted: Sat Mar 15, 2003 1:10 pm |
|
|
: I want to run a one wire bus between the PICS with one 16f84 driving the LCD and displaying messages from another 16f84 and a 12f675.
:=Andrew
I wouldn't be scared of a 1-wire bus running 8-bit serial communication in half duplex mode, with one processor acting as the "master"--meaning it sends out a transmission, and the "slave" units each respond after a delay, or respond if they've been individually addressed (could do it either way). There's no absolute reason to use a standard baud rate, but if you do you can have a computer "eavesdrop" on the line and check that everthing's OK.
But if you want to let any unit speak up asynchronously, with the risk of collisions on the line--then I'd be scared.
Incidentally, 1 wire operating over any kind of distance is going to have transmission line problems--are the various units in the same box?
___________________________
This message was ported from CCS's old forum
Original Post ID: 12723 |
|
|
Andrew Sheppard Guest
|
Re: One wire bus |
Posted: Wed Mar 19, 2003 12:17 pm |
|
|
Units will be on the same board, side by side.
:=: I want to run a one wire bus between the PICS with one 16f84 driving the LCD and displaying messages from another 16f84 and a 12f675.
:=:=Andrew
:=
:=I wouldn't be scared of a 1-wire bus running 8-bit serial communication in half duplex mode, with one processor acting as the "master"--meaning it sends out a transmission, and the "slave" units each respond after a delay, or respond if they've been individually addressed (could do it either way). There's no absolute reason to use a standard baud rate, but if you do you can have a computer "eavesdrop" on the line and check that everthing's OK.
:=
:=But if you want to let any unit speak up asynchronously, with the risk of collisions on the line--then I'd be scared.
:=
:=Incidentally, 1 wire operating over any kind of distance is going to have transmission line problems--are the various units in the same box?
___________________________
This message was ported from CCS's old forum
Original Post ID: 12841 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|