Jump to content
43oh

USCI_B0 in SPI mode


Recommended Posts

I am trying to use USCI_B0in SPI mode but when I probe the MOSI line as well as the CLK line with a scope I do not see anything. I can see that what I am sending is in the TX buffer in the watch window. My code is below, any help would be very welcomed.

 

Thanks

Kas

 

WDTCTL = WDTPW + WDTHOLD; // Stop WDT[/size]
TACTL = TASSEL_1 + ID_0 + MC_0 + ~TAIFG; // ACLK, /1, stopped, clear flag
TACCR0= 0;


int initSPI(void)
{
P1SEL = BIT5 + BIT6 + BIT7; // Configure SPI on USCI0 port B
P1SEL2 = BIT5 + BIT6 + BIT7; // Configure SPI on USCI0 port B
UCB0CTL1 |= UCSWRST; // Disable USCI
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2 + UCSWRST;			// SMCLK
UCB0BR0 |= 0x02;						 // /2
UCB0CTL1 &= ~UCSWRST; //LOOK here for issues					 // Initialise USCI state machine
IE2 |= UCB0RXIE;						 // Enable USCI0 RX interrupt
P1OUT |= 0x08; // Set high to deselect IC
P1DIR |= 0x08; // Set as CS for SPI
return 0;
}

]void spiWrite(unsigned char wrAddr, unsigned char wrData)
{
P1OUT &= ~0x08; // Set CS;[/size]
__no_operation(); // wait for CS to assert
__no_operation();
__no_operation();
// Set the TX buffer for each byte, then go to LPM0 while waiting for the TX to complete
UCB0TXBUF = WRITEINST;
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/interrupt
UCB0TXBUF = wrAddr;
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/interrupt
UCB0TXBUF = wrData;
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/interrupt
__no_operation();
P1OUT |= 0x08; // release CS
__no_operation(); // de-assert CS
__no_operation();
return;
}


// USCI RX interrupt service routine
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCIB0RX_ISR(void)
{
IFG2 &= ~UCB0RXIFG;
_BIC_SR_IRQ(LPM0_bits); // Return to active mode after finishing ISR
}

 

 

I have probed all the pins that would be used for SPI as well as for JTAG as someone had mentioned this maybe an issue (I'm using a launchpad kit)

 

P1.4 - Always low

P1.5 - Pulled low, during code execution pulled high

P1.7 - occasional byte being sent/received

RST - not bytes but activity on this pin as well

TEST- set high (it does alternate when programming the device as well as when I am stepping through the code, looks like bits being sent & received)

Link to post
Share on other sites

I'm not seeing anything really obvious, but I did notice one thing - you disable USCI multiple times. Here's the sample for USCI A from TI. UCSWRST is already set at power-up. Might be worth a try to see if that fixes it. I'll try to test out your code tonight when I get home as well.

 

void main(void)
{
volatile unsigned int i;

WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1OUT = 0x00; // P1 setup for LED & reset output
P1DIR |= BIT0 + BIT5; //
P1SEL = BIT1 + BIT2 + BIT4;
P1SEL2 = BIT1 + BIT2 + BIT4;
UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 |= 0x02; // /2
UCA0BR1 = 0; //
UCA0MCTL = 0; // No modulation
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI0 RX interrupt



P1OUT &= ~BIT5; // Now with SPI signals initialized,
P1OUT |= BIT5; // reset slave

__delay_cycles(75); // Wait for slave to initialize

MST_Data = 0x01; // Initialize data values
SLV_Data = 0x00;

UCA0TXBUF = MST_Data; // Transmit first character

__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
}

 

Also - here's the recommended initilization from the users guide for the MSP430G2XXX series:

NOTE: Initializing or Re-Configuring the USCI Module
The recommended USCI initialization/re-configuration process is:
1. Set UCSWRST (BIS.B #UCSWRST,&UCAxCTL1)
2. Initialize all USCI registers with UCSWRST = 1 (including UCAxCTL1)
3. Configure ports.
4. Clear UCSWRST via software (BIC.B #UCSWRST,&UCAxCTL1)
5. Enable interrupts (optional) via UCAxRXIE and/or UCAxTXIE

Link to post
Share on other sites

Here is the updated function I tried

 

 

int initSPI(void)
{
P1OUT = 0x00;[/indent]
P1SEL = BIT5 + BIT6 + BIT7; // Configure SPI on USCI0 port B[/indent]
P1SEL2 = BIT5 + BIT6 + BIT7; // Configure SPI on USCI0 port B[/indent]
//UCB0CTL1 |= UCSWRST; // Disable USCI[/indent]
UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCMODE_0 + UCSYNC; // 3-pin, 8-bit SPI master /*TODO: Update This Line*/[/indent]
UCB0CTL1 |= UCSSEL_2;// + UCSWRST;			// SMCLK[/indent]
UCB0BR0 |= 0x01;						 // prescaler LSB (UCxxBR0 + UCxxBR1 * 256) = Prescaler[/indent]
UCB0BR1 = 0x00;	 // prescaler MSB[/indent]
UCB0CTL1 &= ~UCSWRST;					// Initialise USCI state machine[/indent]
IE2 |= UCB0RXIE;						 // Enable USCI0 RX interrupt[/indent]
P1OUT |= 0x08; // Set high to deselect IC[/indent]
P1DIR |= 0x08; // Set as CS for SPI[/indent]
return 0;[/indent]
}

This didn't help the issue, but thank you for the suggestion. :smile:

 

I also tried starting up the launchpad with the TEST and RST jumpers removed, this too did not provide anything on the outputs. I'm really getting confused with this one now. :-(

Link to post
Share on other sites

A frequent issue with I2C/SPI on the Launchpad is that P1.6 (MISO/SCL) is wired to the green LED. On at least some LP revisions you have to remove the jumper, or the USCI signals don't work work properly. FWIW, you also generally don't have to set PxDIR when in peripheral mode: the PxSEL setting has that effect (but check the port schematic pages in the data sheet because it's not true for every peripheral function).

Link to post
Share on other sites

How about something like this:

 

P1OUT |= 0x08; // Set high to deselect IC
P1DIR |= 0x08; // Set as CS for SPI
// setup USIB
P1SEL |= BIT7 + BIT6 + BIT5;
P1SEL2 |= BIT7 + BIT6 + BIT5;
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2; // SMCLK
UCB0BR0 |= 0x02;
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST;


void spiWrite(unsigned char wrAddr, unsigned char wrData)

{
P1OUT &= ~0x08; // Set CS
UCB0TXBUF = WRITEINST;
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = wrAddr;
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = wrData;
while (!(IFG2 & UCB0RXIFG));
wrData = UCB0RXBUF;
P1OUT |= 0x08; // release CSreturn
}

Link to post
Share on other sites

A frequent issue with I2C/SPI on the Launchpad is that P1.6 (MISO/SCL) is wired to the green LED. On at least some LP revisions you have to remove the jumper, or the USCI signals don't work work properly.

 

Does this include the CLK line not giving any form of output, because I did not see any clock signal on the clock line. I also did try out of frustration to remove the jumpers to both LEDs and still nothing. Looks like the P1.4-7 pins are acting in JTAG mode but I can't seem to work out how to verify this or to change this. This was a suggestion by someone at TI but they gave no further information.

 

 

How about something like this:

 

P1OUT |= 0x08; // Set high to deselect IC
P1DIR |= 0x08; // Set as CS for SPI
// setup USIB
P1SEL |= BIT7 + BIT6 + BIT5;
P1SEL2 |= BIT7 + BIT6 + BIT5;
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2; // SMCLK
UCB0BR0 |= 0x02;
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST;


void spiWrite(unsigned char wrAddr, unsigned char wrData)

{
P1OUT &= ~0x08; // Set CS
UCB0TXBUF = WRITEINST;
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = wrAddr;
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = wrData;
while (!(IFG2 & UCB0RXIFG));
wrData = UCB0RXBUF;
P1OUT |= 0x08; // release CSreturn
}

 

RobG I'm not sure how this differs from the second code sample I submitted, unless changing the order in which you set-up P1SEL and P1SEL2 may have an effect. As for the second function, wont this waste a lot of cycles. I will however give this second function a try even though nothing there should stop the clock as far as I can tell... but you never know. (i should at least see the clock output if nothing else)

Link to post
Share on other sites

RobG I'm not sure how this differs from the second code sample I submitted, unless changing the order in which you set-up P1SEL and P1SEL2 may have an effect. As for the second function, wont this waste a lot of cycles. I will however give this second function a try even though nothing there should stop the clock as far as I can tell... but you never know. (i should at least see the clock output if nothing else)

Your SPI clock runs at half MCU clock speed, so it's about 16 cycles per byte.

Your code writes to the buffer, than puts MCU to sleep, then interrupts, clears the flag, and wakes the MCU.

Interrupt latency is 11 cycles, other stuff will use up several cycles too, so the total is probably more than 16.

In my code, after writing to the buffer, I am checking if the buffer is empty, then continue writing, that will take about 16 cycles as well (actually, after the first write, the buffer will be emptied right away, but the third write will have to wait twice as long.)

At slower SPI clock speeds, your method would save power, but in your case, they are pretty much the same except that I am not using interrupts.

Link to post
Share on other sites

Thank you guys for all of the suggestions,

 

I have now tried both RobG's suggestion as well as cuberg's and neither have solved the issue. I have used the sample code that TI gives you as examples for all the different ports and I can get SPI working on port A. When I try I2C on port B (no SPI examples for port B ) I don't see a clock tick or anything going out. While I originally thought this was due to the JTAG, when I set all my pins as GPIO (P1.0-7 & P2.0-7) and switch them up and down I can see that on the scope, so i have some control of these pins and therefore assume not a JTAG issue.

 

This is really getting frustrating because I can't think of any other tests to do to try solve this issue and I cant find any example code online of someone using port B in SPI mode. If anyone has any further suggestions for me to try, I will happily do so.

 

 

 

Thanks

Kazz

Link to post
Share on other sites
  • 1 month later...

Well I am new to this hardware myself, but noticed that turning the CPU off (LPM0 I think ? ) will cause some USCI examples to not work.. For me it was UART on USCI A0. It also frustrated me to no end. But I eventually got it working after adjusting several lines of code. Pin assignments were all wrong "out of the box".

 

In Grace, when you have the USCI AO module configured ( at least in UART mode ), it wont even produce output for the USCI B0 module( SPI ). But I will let you configure the B0 module without any noted conflicts. This leaves me wondering if there is some issue I am unaware of. Or, am I doing something wrong ? If so Grace does not know it. So yeah I am a bit confused :/

 

Just by reading through whats been said here, it seems to me that the common problem you and I both had was the CPU being shut off ( LPM0 ). Granted two different parts of the module, and in different modes.

 

EDIT: I should say I use the stand alone version of grace. I do not use the CCS plugin, since I only use CCS for compiling / debugging.

Link to post
Share on other sites

I believe what you say can only be correct. I've seen it done in videos demonstrating the Launchpad.Again, I do not know the hardware as well as I like. But have a feeling the example code was not fully checked before being released. At least for the given device. While yes, I know which device I am using, and was "forced" to select the correct device 2-3 times before  I could load the example code within CCS 5.2.  So yeah after a large time investment reading through various texts, and watching of videos. Short term the fix for me was to just remove the low power mode statements from the example code. Ideal ? No but now I know the code works.

 

As for what I said about Grace. There are known severe issues with the program / addon. Which the text I've read is not very specific about. However, I was able to get a "working" ( not tested on the device yet ) project going. After reordering how I defined the various modules on the device. Also in the end and relating to above post. Timing of the CLK to the module is important too. For me, I am wanting to run 12Mhz CPU, SMCLK divided by 8, with SPI bps at 128. This seems to work for Grace at any rate, and is more than adequate for my project at hand.

 

With all the above said, I am left feeling that TI needs to more polish on their tools. Especially if they expect more than $10 for code composer studio ( let alone $300 + ?! ). You guys here however seem to be great, and I love a several of the projects a few of you have done.

 

Kazz, if you're still interested in working out this problem of yours, I could paste the output from Grace for USCI B0 in SPI mode. One thing I did notice though. In your original post you mentioned using P1.4 for SCLK ? SPI SCLK output according to Grace is P1.5 for USCI B0. Maybe that was a typo, or I just do not know what I am talking about ? *shrug*

Link to post
Share on other sites
  • 2 months later...

A frequent issue with I2C/SPI on the Launchpad is that P1.6 (MISO/SCL) is wired to the green LED. On at least some LP revisions you have to remove the jumper, or the USCI signals don't work work properly. FWIW, you also generally don't have to set PxDIR when in peripheral mode: the PxSEL setting has that effect (but check the port schematic pages in the data sheet because it's not true for every peripheral function).

 

I can't thank you enough for this bit of info, you've just solved an issue that has been plaguing me for about 2 weeks now.  After being completely stumped by this problem, I came to this forum to write up a question, but I decided to search first and came across your post.  Thanks again, very much appreciated, I can finally get on with my project!!

 

Adam

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...