|
|
View previous topic :: View next topic |
Author |
Message |
stelios1988
Joined: 10 Jan 2011 Posts: 13
|
MSP430 MASTER - PIC 16F876A SLAVE |
Posted: Wed Jan 12, 2011 6:37 am |
|
|
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
|
|
Posted: Wed Jan 12, 2011 7:21 am |
|
|
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
|
|
Posted: Wed Jan 12, 2011 7:49 am |
|
|
i have 10k resistors on SDA and SCK with 3.3V.
The pins C3 and C4 are connected. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Wed Jan 12, 2011 8:10 am |
|
|
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
|
|
Posted: Wed Jan 12, 2011 8:16 am |
|
|
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: 19538
|
|
Posted: Wed Jan 12, 2011 10:00 am |
|
|
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
|
|
Posted: Thu Jan 13, 2011 9:55 am |
|
|
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
|
|
Posted: Thu Jan 13, 2011 2:03 pm |
|
|
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
|
|
Posted: Thu Jan 13, 2011 2:13 pm |
|
|
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
|
|
Posted: Thu Jan 13, 2011 2:33 pm |
|
|
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
|
|
Posted: Thu Jan 13, 2011 2:53 pm |
|
|
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
|
|
Posted: Thu Jan 13, 2011 2:56 pm |
|
|
That isn't what I wanted. I can't really help any more on this. |
|
|
stelios1988
Joined: 10 Jan 2011 Posts: 13
|
|
Posted: Thu Jan 13, 2011 3:13 pm |
|
|
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: 19538
|
|
Posted: Thu Jan 13, 2011 3:47 pm |
|
|
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
|
|
Posted: Thu Jan 13, 2011 4:32 pm |
|
|
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! |
|
|
|
|
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
|