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 CCS Technical Support

MSP430 MASTER - PIC 16F876A SLAVE
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

MSP430 MASTER - PIC 16F876A SLAVE
PostPosted: Wed Jan 12, 2011 6:37 am     Reply with quote

Hello again guys. New post because its another subject.

I have a TelosB mote (functioning with the MSP430 microprocessor) and successfully drive leds with the PCF8574 IC with I2C.(all this with tinyOS). Now i want to connect the mote with the PIC16F876A. The mote only works as master mode so i have to set the pic as slave.

This is the main.c
Code:

   #include <16F876A.h>                       
   #DEVICE ADC= 8
   #use delay(clock=4000000)
   #include "lib_mot_moway.h"                 

int rcv_buf[0x10];       
int wrt_buf[0x10];       
int cmd=0xFF; 

#int_SSP // interrupt on i2c activity
void  i2c_isr(void)
{
    int state, incoming;
    output_high(LED_TOP_GREEN);
    state = i2c_isr_state(TB);
    incoming = i2c_read(TB);
    if(state < 0x80)
    {
       
        if (state == 1)
        {
        cmd = incoming;
        }
       
        else if (state > 1)
        {
        output_high(LED_TOP_RED);
            rcv_buf[state-2]=incoming;
        }
    }
    else
    {
        i2c_write(TB,wrt_buf[state-0x80]);
    }
}

void main()
   {
output_high(LED_R);
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);

   

while(1){}


lib_mot_moway.h
Code:


//********************
//*   DEFINITIONS    *
//********************
//I2C configuration
#use i2c(Master,Fast,sda=PIN_C1,scl=PIN_C0,restart_wdt,stream=RB)
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0x8A,force_hw,stream=TB)

and some other commands of the master function of the i2c



The only thing that works is the output_high of the main function, the leds of the interrupt don't work. Is there a problem in my code? Something else I have to do?
Thanks
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jan 12, 2011 7:21 am     Reply with quote

Do you have the proper value resistors on the I2C lines for the speed and Vdd that you use?

Are the pins you used connected to the internal hardware I2C peripheral?
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Wed Jan 12, 2011 7:49 am     Reply with quote

i have 10k resistors on SDA and SCK with 3.3V.
The pins C3 and C4 are connected.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Wed Jan 12, 2011 8:10 am     Reply with quote

Lower those.
For standard mode, at 5v, 10K, allows a maximum bus capacitance of 120pF. For standard mode with 3.3v, this drops to just under 80pF. For 'fast' mode, the allowable capacitances for 10K, fall to just 30pF at 5v (and is actually beyond the range of recommended values), and to just 19pF at 3.3v (and isn't even on the graphs....). The minimum resistor value allowed, is just under 1K at 3.3v. realistically a 'normal' value for 3.3v fast mode, would be something like 1.8K to 2.2K. 10K is too large.

Best Wishes
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Wed Jan 12, 2011 8:16 am     Reply with quote

do you think there is a problem in the code? or the code is fine?
and something else, what about the address? i can use whatever address i want? on the slave mode?
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Wed Jan 12, 2011 10:00 am     Reply with quote

Some comments.
1) A 'slave', does not have a speed. This is controlled by the master. 'Fast' is not wanted in the slave setup.
2) Hopefully your LED's have got current limiting resistors. Common error.
3) You don't really want to 'read' from the I2C device on write transactions:
Code:


void  i2c_isr(void) {
    int state, incoming;
    output_high(LED_TOP_GREEN);
    state = i2c_isr_state(TB);
    if(state < 0x80)  {
        incoming = i2c_read(TB);
     
        if (state == 1)  {
           cmd = incoming;
        }
        else if (state > 1) {
           output_high(LED_TOP_RED);
           rcv_buf[state-2]=incoming;
        }
    }
    else {
        i2c_write(TB,wrt_buf[state-0x80]);
    }
}

3) Do try lower pull ups. They are needed on 3.3v
4) Ideally add tests to ensure the code does not overrun the buffers.

Best Wishes
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 9:55 am     Reply with quote

Well, I bought 1K8 and 2.2K resistors. Tried again, fixed the code as you see above and I would like to mention some things, if you can help me.
I've tested the PIC as master on the PCF 8574 and it works fine. The default address of the PCF 8574 is 0 1 0 0 A0 A1 A2 0, which if I set the A0,A1,A2 to ground it will come out as 0x40h. wrote on address 0x40h and everything was ok.
Then I tried to write with the MSP430 on the PCF 8574 and it the only way it could be written is to address it on 0x20h which means I have one shift right of the address (don't know why is that, I didn't even search it).

So next step tried to connect the MSP430(master) with the PIC16F876A(slave). The code below as Ttelmah helped me.
Code:

#include <16F876A.h>
#device adc=8                                                     
#use delay(clock=4000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
#define PIC_ADDRESS 0x40
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x40)
BYTE address, buffer[0x10];

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;

   state = i2c_isr_state();
   
   if(state <= 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
      if(state == 1)                     //First received byte is address
         address = incoming;
      if(state == 2)                     //Second received byte is data
         buffer[address] = incoming;
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(buffer[address]);
   }
}

void main ()
{
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);

   while (TRUE) {}
}


I've set the address on MSP430 set as 0x20h (as I figured this out).

To see if the I2C communication is done, I have a LED on the MSP430 to turn on, and if its failed one other to turn on as well.
Before I've changed the resistors and had the address as 0x40 (instead of 0x20) the failed led came on. No none of those two is turning on.
I don't know what to do next, I don't have any debugging tools so I refer to you.

Thanks in advance
Stelios
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 2:03 pm     Reply with quote

I don't know what a TelosB node is. Do you control the code inside the
MSP430 ? Is the i2c section simple and short (< 100 lines) ? If so, post it.
We need to know the exact i2c commands and data that are being sent
to the slave.

If you don't control the MSP430 code, and it's some sort of pre-
programmed device, then post a link to the manual for it. As I said, we
need to see the i2c "datagram" that shows what is being sent to the slave.
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 2:13 pm     Reply with quote

It's written in a different programming language called nesC in tinyOS environment.
This program is written in high-level, I don't use the low-level programming of the MSP430. I've used this site http://www.tinyos.net/tinyos-2.x/doc/html/tep117.html to work with it. I remind you that I manage to drive the PCF 8574 IC correctly with the difference that instead of 0x40h address (that says in the datasheet) I used 0x20h.

More configurations are found http://openwsn.berkeley.edu/browser/tinyos-2.x/tos/chips/msp430/usart/msp430usart.h?rev=620 and http://openwsn.berkeley.edu/browser/tinyos-2.x/tos/chips/msp430/usart/Msp430I2CP.nc?rev=620

Code:

#include "printf.h"

module I2CC
{
  uses interface I2CPacket<TI2CBasicAddr> as I2CBasicAddr;
  uses interface Boot;
  uses interface Leds;
  uses interface Resource;
  uses interface Timer<TMilli> as Timer;
}

implementation{
  uint8_t buf = 0xFF;

  event void Boot.booted(){
    printf("\nBOOTED\n");
    printfflush();
        call Resource.request();
  }

async event void I2CBasicAddr.writeDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data){
  if (error==SUCCESS)      {
  call Leds.led2Toggle();
   printf("\nwriteDone is OK\n");  }
  if (error==FAIL)      {
call Leds.led0Toggle();
        printf("\nwriteDone has a problem\n");
}
  printfflush();
       
    return;
  }

async event void I2CBasicAddr.readDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data){
   if (error==SUCCESS)      {
   printf("\nreadDone is OK\n");
  }
  if (error==FAIL)      {
printf("\nreadDone has a problem\n");
}
     printfflush();
  return;
  }

  event void Resource.granted(){
       call Timer.startOneShot(1024);
    return;
  }

  event void Timer.fired() {
    printf("\nFIRED\n");
    printfflush();
        if (call I2CBasicAddr.write(I2C_START|I2C_STOP, 0x20, 1, &buf)==SUCCESS){
         printf("\nsuccess to write\n");
         printfflush();
                call Leds.led1Toggle();}
        return;
  }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 2:33 pm     Reply with quote

I still don't know what i2c commands and data you are sending to the
slave PIC.

Look at the top 3 lines in this i2c interpreter.
http://www.pctestinstruments.com/logicport/interpreters.htm
It shows a write operation to the slave, with a start bit, a slave address
of 50h with the R/W bit = 0, and then an acknowledge, and after that
presumably a data byte of 0x00. (Note: CCS would refer to this as a
slave address of 0xA0).

That's the level of detail that I wanted to see. Maybe not a logic analyzer
diagram, but a list of what is being sent to the slave. Then, I can look at
the CCS slave code and see if it can handle what the master is sending
to it.
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 2:53 pm     Reply with quote

Code:

typedef struct {
241     unsigned int i2cstt: 1; // I2CSTT Bit 0 START bit. (0=No action; 1=Send START condition)
242     unsigned int i2cstp: 1; // I2CSTP Bit 1 STOP bit. (0=No action; 1=Send STOP condition)
243     unsigned int i2cstb: 1; // I2CSTB Bit 2 Start byte. (0=No action; 1=Send START condition and start byte (01h))
244     unsigned int i2cctrx: 1; //I2CTRX Bit 3 I2C transmit. (0=Receive mode; 1=Transmit mode) pin.
245     unsigned int i2cssel: 2; // I2C clock source select. (00=No clock; 01=ACLK; 10=SMCLK; 11=SMCLK)
246     unsigned int i2ccrm: 1;  // I2C repeat mode
247     unsigned int i2cword: 1; // I2C word mode. Selects byte(=0) or word(=1) mode for the I2C data register.
248   } __attribute__ ((packed)) msp430_i2ctctl_t;


Code:

typedef struct {
254     unsigned int :1;
255     unsigned int mst: 1;      //Master mode (0=slave; 1=master)
256     unsigned int :1;
257     unsigned int listen: 0;   //Listen enable (0=disabled; 1=enabled, feed tx back to receiver)
258     unsigned int xa: 0;       //Extended addressing (0=7-bit addressing; 1=8-bit addressing)
259     unsigned int :1;
260     unsigned int txdmaen: 0;  //DMA to TX (0=disabled; 1=enabled)
261     unsigned int rxdmaen: 0;  //RX to DMA (0=disabled; 1=enabled)
262      
263     unsigned int :4;
264     unsigned int i2cssel: 0x2;  //Clock source (00=disabled; 01=ACLK; 10=SMCLK; 11=SMCLK)
265     unsigned int i2crm: 1;    //Repeat mode (0=use I2CNDAT; 1=count in software)
266     unsigned int i2cword: 0;  //Word mode (0=byte mode; 1=word mode)
267   
268     unsigned int i2cpsc: 0;   //Clock prescaler (values >0x04 not recomended)
269   
270     unsigned int i2csclh: 0x3;  //High period (high period=[value+2]*i2cpsc; can not be lower than 5*i2cpsc)
271   
272     unsigned int i2cscll: 0x3;  //Low period (low period=[value+2]*i2cpsc; can not be lower than 5*i2cpsc)
273   
274     unsigned int i2coa : 0;  // Own address register.
275     unsigned int :6;
276   } msp430_i2c_config_t;



Code:

call HplI2C.setMasterMode();
141       call HplI2C.setTransmitMode();
142      
143       call HplI2C.setSlaveAddress( addr );
144       call HplI2C.enableTransmitReady();
145       call HplI2C.enableAccessReady();
146       call HplI2C.enableNoAck();
147      
148       if ( flags & I2C_START )
149         call HplI2C.setStartBit();
150       else
151         nextWrite();
152      
153       return SUCCESS;
154      
155     }


Thats all the info considering the sending procedure.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 2:56 pm     Reply with quote

That isn't what I wanted. I can't really help any more on this.
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 3:13 pm     Reply with quote

Code:

async command void HplI2C.setTransmitMode() { I2CTCTL |= I2CTRX; }
async command void HplI2C.setSlaveAddress( uint16_t addr ) { I2CSA = addr; }
async command void HplI2C.enableTransmitReady() { I2CIE |= TXRDYIE; }
async command void HplI2C.enableAccessReady() { I2CIE |= ARDYIE; }
async command void HplI2C.enableNoAck() { I2CIE |= NACKIE; }
async command void HplI2C.setStartBit() { I2CTCTL |= I2CSTT; }


How can i find more info on that?
I went lower as i can go.
Thats the steps. The registers that i've posted now are the MSP430 ones.
Page 321 on this
http://focus.ti.com/lit/ug/slau049f/slau049f.pdf

I think the info that i gave you is enough.
Thanks although even if you can't find any more info on this last post.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 3:47 pm     Reply with quote

The 20, versus 40, may imply that the code for the MPS430, uses the original I2C nomenclature.

Basically, each I2C character, is 8 bits.

For the 'address' byte, there are seven 'address' bits, followed by a single R/W bit.

So on some makes of device/code, you would have:

0x40

0b0100000x

Where 'x' is the R/W flag, and 0100000 is the address = 0x20.

Then the read/write bit is dealt with separately.

On the PIC, you instead just treat the 'address' byte as a byte, and effectively multiply the 'address' by two, before putting it into the byte, with the R/W bit added at the bottom.

Obviously if this is the case, the _maximum_ address the PCF can use, becomes 127, and if the PIC is at address 0xA0 (it's notation), the PCF would need to talk to address 0x50....

Best Wishes
stelios1988



Joined: 10 Jan 2011
Posts: 13

View user's profile Send private message

PostPosted: Thu Jan 13, 2011 4:32 pm     Reply with quote

The MSP430 sends this. But why I can't see an interrupt happening? Every command I add to #INT_SSP doesn't get executed.
What's the reason that INT_SSP doesn't work even though with the same connection I get an PCF 8574 to work fine and the PIC not even get the interrupt right!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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