CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI 1 wire devices

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
uhohrobbo
Guest







SPI 1 wire devices
PostPosted: Fri Aug 05, 2005 4:19 am     Reply with quote

Hey,

I know that CCS C supports 2 and 3 wire SPI devices. Has anyone managed to get a 1 wire (or iButton) device to work with a non-1wire device (i.e. PIC18F248)?

Cheers
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Aug 05, 2005 7:52 am     Reply with quote

Maybe you are asking can a PIC device act as a slave on a Dallas one wire (DOW) system.
Here is code I wrote a while back
The PIC takes on a DOW 8 byte unique identity via dev_id[8] it sends to a master ( there is CCS library code for a PIC to be a Master for the DOW see touch.c etc) upon a reset. The slave drops out if it is not being addressed
The reset pulses are triggered by a RC 33k 10nf that trips the interrupt on B0 the DOW line is driven by the PIC using the pin TOUCH_PIN
There is some reference to tokens ("T6063") where the pic would act as a DOW interface to say a T6963 LCD controller accepting data from a DOW master and displaying it on an LCD screen

The code is for the 16F84 so watch out for the register specific assignments.



Code:
///         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<nbytes;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<BUFF_SIZE;i++) dow_write_byte(xmit_buff[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);
}
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Aug 05, 2005 7:53 am     Reply with quote

Duplicate posting
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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