Search Microcontrollers

Showing posts with label SPI. Show all posts
Showing posts with label SPI. Show all posts

Thursday, May 21, 2015

Cortex M3 - SPI / 1

I have been playing with SPI a few times, but never on a Cortex M3 using CMSIS.

That, by itself, it should be a good reason to dig into this topic, however I have a nice project in mind and it will require SPI communicatin, so... let's  get to it!

Some basic stuff first :
SPI uses four pins: MOSI (Master Out Slave In), MISO (you guess it), CLK (clock) , SSEL and as Chip enable/select to activate the slave, normally a simple GPIO pin on the master.

NXP Cortex M3s implement a variation of SPI called SSP (Synchronous Serial Port) which supports the "old" SPI.
In the LPC1768 there are two SSP peripherals called SSP0 and SSP1.

The LPC17xx manual says:

"The two SSP interfaces, SSP0 and SSP1 are configured using the following registers:

  1. Power: In the PCONP register, set bit PCSSP0 to enable SSP0 and bit PCSSP1 to enable SSP1.
    Remark: On reset, both SSP interfaces are enabled (PCSSP0/1 = 1).
  2. Clock: In PCLKSEL0 select PCLK_SSP1; in PCLKSEL1 select PCLK_SSP0. In master mode, the clock must be scaled down.
  3. Pins: Select the SSP pins through the PINSEL registers and pin modes through the PINMODE registers.
  4. Interrupts: Interrupts are enabled in the SSP0IMSC register for SSP0 and SSP1IMSC register for SSP1. Interrupts are enabled in the NVIC using the appropriate Interrupt Set Enable register.
  5. Initialization: There are two control registers for each of the SSP ports to be configured: SSP0CR0 and SSP0CR1 for SSP0, SSP1CR0 and SSP1CR1 for SSP1.
  6. DMA: The Rx and Tx FIFOs of the SSP interfaces can be connected to the GPDMA controller
Remark: SSP0 is intended to be used as an alternative for the SPI interface, which is included as a legacy peripheral. Only one of these peripherals can be used at the any one time" 
(@NXP LPC17xx user manual)

It seems to me this is a pretty good checklist.

1) Power ON


Power CONtrol for Peripherals (PCONP) is the register we use to turn the SSP (or any other) interfaces on:

  LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
  LPC_SC->PCONP |= (1 << 10); /* Enable power to SSPI1 block */

Normally we just need one, I reported the lines for both so you can decide which one to use.

2) Clock in

The Peripheral clock selection is done via the PCLKSEL0 and 1.
Each peripheral uses 2 bits

00 : PCLK_peripheral = CCLK/4 00
01 : PCLK_peripheral = CCLK
10 : PCLK_peripheral = CCLK/2
11 : PCLK_peripheral = CCLK/8

SSP0 uses bits 11:10 of PCLKSEL1 and SSP1 uses bits 21:20 of PCLKSEL0

LPC_SC->PCLKSEL1 &= ~(3<<10);  /* PCLKSP0 = CCLK/4 */
LPC_SC->PCLKSEL1 |=  (1<<10);  /* PCLKSP0 = CCLK */

LPC_SC->PCLKSEL0 &= ~(3<<20);  /* PCLKSP1 = CCLK/4*/
LPC_SC->PCLKSEL0 |=  (1<<20);  /* PCLKSP1 = CCLK */

3) Pins

Here we will set MISO, MOSI and CLK pins, plus you need to remember to set 1 GPIO as output to enable the slave, in this example we will assume you are using GPIO P1.21 as SSEL (Slave Selection / Enable).
Normally SPI slaves are selected active when SSEL is LOW.

A summary of the available configurations for SSP pins :



 /* ----> SSEL : output set to high. */
LPC_PINCON->PINSEL3 &= ~(0<<10);   /* P1.21 SSEL (used as GPIO)   */
LPC_GPIO1->FIODIR   |=  (1<<21);   /* P1.21 is output */
LPC_GPIO1->FIOPIN   |=  (1<<21);   /* set P1.21 high*/
  
 /* ----> SSP0 : SCK, MISO, MOSI  */
LPC_PINCON->PINSEL3 &= ~(3UL<<8);       /* P1.20 cleared  */
LPC_PINCON->PINSEL3 |=  (3UL<<8);       /* P1.20 SCK0  */
   /* P1.23, P1.24 cleared        */ 
LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); 
   /* P1.23 MISO0, P1.24 MOSI0    */ 
LPC_PINCON->PINSEL3 |=  ((3<<14) | (3<<16)); 

 /* ----> SSP1 : SCK, MISO, MOSI  */
LPC_PINCON->PINSEL0 &= ~(0x3F<<14);  /* P0.7,8,9 cleared  */
    /* ... an then set to function 2 */
LPC_PINCON->PINSEL0 |=  (2UL<<14) | (2UL<<16) | (2UL<<18);

4) Interrupts

As suggested by the checklist, we will use the SSP Interrupt Mask Registers SSPxIMSC.


As you can see, these interrupts are used to identify error conditions or FIFO status to ease buffered communication.
Since SSP is a synchronous communication (unlike the UART), there is no point in having a RX data ready interrupt.
In fact, each time you want a slave device to send you some data, using SPI / SPSS you explicitly have to ask for it (polling), meaning you should also be already listening for it to arrive, no need for an interrupt.

Should you need to implement some more advanced control, feel free to enable those interrupts, in that case you should check the SSPxRIS (Raw Interrupt Status), SSPxMIS (Masked Interrupt Status) and SSPxICR (Interrupt Clear) registers.

5) Initialisation

Ok, we definitely need this one.
What we need here is to accurately set the bit frequency, so that it will match the frequency supported by the slave device we are interfacing.
This is done via the Prescaler Register (CPSR) that divides the peripheral clock (pclk) we initially configured in step 2 (PCLKSEL0 and 1).

So, let's assume our processor is running at 100MHz, we fed the peripheral with the same clock speed (by providing a divider = 1) and now we want to obtain a 400KBit/s rate.
How do we do that?

#define sspKBps 400000
int prescaler = SystemCoreClock / sspKBps; 
/* 100.000.000/400.000 = 250 */

LPC_SSP0->CPSR = prescaler; /* for SSP0 */
LPC_SSP1->CPSR = prescaler; /* for SSP1 */

Now we need to use the SSP Control registers to specify how many bits should be transferred and which protocol -Frame Format- to use (remember, the SSP can do more than SPI, in fact it supprots TI and Microwire formats too). 
Also, we can further reduce the bit rate here by dividing the value of the prescaler, plus we can set clock phase and polarity.

  
/* SSP0 : 8Bit, SPI, CPOL=0, CPHA=0 */                                  
LPC_SSP0->CR0  = 0x0007;   
/* SSP1 : 8Bit, SPI, CPOL=0, CPHA=0 */                                  
LPC_SSP1->CR0  = 0x0007;   

The Control Register 1 (CR1) allows to enable the SSP port and to configure it as master or slave.



LPC_SSP0->CR1  = 0x0002;       /* SSP0 enable, master  */
LPC_SSP1->CR1  = 0x0002;       /* SSP1 enable, master  */

6) DMA

I am sure some day I will feel particularly brave and will have a go at it, for now, let's just say that we can enable DMA transfers for SSP ports using the SSPxDMACR registers.



Ok, with all this our SSP port should be ready for communication, at least on the Master side.

So, where do we put output data and from where do we get input?
There is a Data Register SSPxDR (we can use the low 16 bits) that is used both for RX and TX.
Why is this possible?
SSP (or SPI) is synchronous communication, meaning you cannot write and read at the same time on the line, or better, for every byte you send out, you will get a byte back.

The LPC17xx manual says :

"Write: software can write data to be sent in a future frame to this register whenever the TNF bit in the Status register is 1, indicating that the Tx FIFO is not full. If the Tx FIFO was previously empty and the SSP controller is not busy on the bus, transmission of the data will begin immediately. Otherwise the data written to this register will be sent as soon as all previous data has been sent (and received). If the data length is less than 16 bits, software must right-justify the data written to this register.

Read: software can read data from this register whenever the RNE bit in the Status register is 1, indicating that the Rx FIFO is not empty.
When software reads this register, the SSP controller returns data from the least recent frame in the Rx FIFO. If the data length is less than 16 bits, the data is right-justified in this field with higher order bits filled with 0s"

Looks like we need to check the Status Register (SSPxSR)


So, putting it all together, to exchange 1 byte we need to :

int SSP1_sendbyte(int out)
{
// enable your GPIO used as SSEL
 LPC_GPIO1->FIOCLR = 1<<21; // enable slave
 // while(!(LPC_SSP1->SR & 1)) ; // Wait until TX Empty
 // might need a grace period here, depending on the slave
 LPC_SSP1->DR = out; // output data
 // while(LPC_SSP1->SR & (1 << 4)); // Wait until SSP is busy
  while(LPC_SSP1->SR & (1 << 2)); // Wait until we have data in RX
 LPC_GPIO1->FIOSET = 1<<21; // disable slave
 return LPC_SSP1->DR;
}

In a future post we will test this with some SPI device.

Thursday, August 2, 2012

MSP430G2 - (USCI) SPI interface 3

I learnt something and that, by itself, its awesome.

In the previous post I discussed an issue I found with my procedure that handles the SPI communication between the launchpad and a digital pot.

Communication was working until I configured the SPI master to send out bits starting from MSB instead of LSB (like it should).
At that point the digital pot was not responding anymore (before it was responding and getting wrong values as bits were reversed).
Digging into the issue I found that with the MSB setting the MOSI line was keeping the value of the last bit sent, even after the communication was over.

I think it was a fair assumption since with LSB first I saw each time the MOSI line drop to low... but it was a wrong assumption.
Since I was sending 7 bit values, when they are serialized starting from LSB, the last bit in a (8 bit) byte is always ZERO, so the mosi line was still keeping the value of the last bit sent, regardless of MSB/LSB settings.

Posted a question about this on the TI forum and that's how I learnt something!
SPI does not define any specific idle state for data (miso/mosi) lines (while it does for the clock signal), so the behavior I found is "normal".
However, since I am experimenting with one single slave on the bus, I disregarded the Chip Select (CS) management and apparently this, in combination with the mosi line changing idle state, caused the problem.
I think this has to do with the SPI mode selection of the mcp4131, but I found the datasheet a bit cryptic on this subject, so I will not quote it here.

So I added the CS management and also switched to the USCI port B.

void setPotValue(unsigned char dataOut)
{
P1OUT &= ~BIT3; // enable slave (CS to Low)
UCB0TXBUF = 0;  // Send command
while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
UCB0TXBUF = dataOut; // Send wiper level
while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
P1OUT |= BIT3; // disable Slave (CS to High)
}

The CS signal has to be driven LOW to enable the chip and high to disable it, this wraps the data transmission.

Still something did not work, and checking with the Oscilloscope I found this :
(In red the clock, in yellow the CS line)


CS is enabled correctly right before the clock starts to oscillate, but then it is disabled BEFORE the last bit is sent.
This is happening because I was just waiting for the TX buffer to complete, which does not ensure that physically the bits have been transmitted on the line.

The UCXxSTAT status register has a bit (UCBUSY) that indicates if a TX or RX operation is in process.
Adding the following line

while (UCB0STAT & UCBUSY); // wait for the tx to complete

before disabling CS fixed the issue


And the digital pot output is (used as a voltage divider between vcc and gnd) :





Finally, the overall code (uses port usci B on pins clk = 1.5 , mosi = 1.7 ) is :


#include <msp430g2553.h>
 unsigned char potLevel;

void clockConfig()
{
 // configure the CPU clock (MCLK)
 // to run from DCO @ 16MHz and SMCLK = DCO / 4
 BCSCTL1 = CALBC1_16MHZ; // Set DCO
 DCOCTL = CALDCO_16MHZ;
 BCSCTL2= DIVS_2 + DIVM_0; // divider=4 for SMCLK and 1 for MCLK
}

void pinConfig()
{
 // set the pin mode 3 for pins 5,6 & 7 of port 1 (USCI mode)
 P1SEL = BIT5 + BIT6 + BIT7; // low bit = 1 for pins 5,6 and 7 BIT 3 is 0 (CS via GPIO)
 P1SEL2 = BIT5 + BIT6 + BIT7; // high bit = 1 for pins 5,6 and 7 BIT 3 is 0 (CS via GPIO)
 P1DIR |= BIT3; // p1.3 set to output to drive CS
 P1OUT |= BIT3; // pull p1.3 to high - CS high -> chip is disabled
}

// USCI
void spiConfig()
{
 UCB0CTL1 = UCSWRST; // reset
 UCB0CTL0 |= UCCKPL +UCMST  + UCSYNC +UCMSB; // synchronous (=SPI) master 3 wire SPI, clock polarity High
 UCB0CTL1 |= UCSSEL_2; //use SCLK : 4MHz (MCP4131 supports up to 10MHz write via SPI)
  // set baud rate = SMCLK, no further division
 UCB0BR0 = 0;
 UCB0BR1 = 0;
 UCB0CTL1 &= ~UCSWRST; // **Initialize USCI **
}

// drives a MCP4131 digital potentiometer via SPI
void setPotValue(unsigned char dataOut)
{
 P1OUT &= ~BIT3; // enable slave (CS to Low)
 UCB0TXBUF = 0;  // Send command
 while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
 UCB0TXBUF = dataOut; // Send wiper level
 while (!(IFG2 & UCB0TXIFG)); // wait for TX buffer ready
 while (UCB0STAT & UCBUSY); // wait for the tx to complete
 P1OUT |= BIT3; // disable Slave (CS to High)
}

void main(void)
{
// setup
 WDTCTL = WDTPW + WDTHOLD;
 clockConfig();
 pinConfig();
 spiConfig();
    // program execution loop
 while (1)
 {
  for (potLevel=0;potLevel<127;potLevel++)
  {
   setPotValue(potLevel);
   __delay_cycles(20000);
  }
  for (potLevel=127;potLevel>0;potLevel--)
  {
   setPotValue(potLevel);
   __delay_cycles(20000); 
  }
 }}


Wednesday, August 1, 2012

MSP430G2 - (USCI) SPI interface 2

Time to check what's happening on the other end of the bus.
Nope, it's not a school-bus, it's a SPI bus which I started discussing here, if you missed the first part, you will probably not be able to follow this one (but we have a solution for that, right? Uhm, let me think... yeah! how about you check that one first?).

In the last post I showed how to output some data on the SPI bus of a MSP430G2553 MCU, but I did not really check if the data was correct or not for the connected device (MCP4131).
Turns out it was not :)

Particularly the procedure :

void setPotValue(unsigned char dataOut)
{
   while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
   UCA0TXBUF = 0; // Send command 0
   __delay_cycles(50);
   while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
   UCA0TXBUF = dataOut; // Send wiper level
   __delay_cycles(50);

}

had a few issues.
The first one was immediately visible from the oscilloscope output : apparently the level byte was sent BEFORE the command.

That happened because the "wait for TX ready" was placed before the instruction that fills the TX buffer, so the wiper level of the previous command was sent right before the command zero (you can verify that in the video of the previous post).

void setPotValue(unsigned char dataOut)
{
   UCA0TXBUF = 0; // Send command 0
   while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
   UCA0TXBUF = dataOut; // Send wiper level
   
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
}

Ok, that's an easy fix, I also removed the delay which is not really needed, it was there just for debug purposes.
The result is this :


Much better, using the cursor I was also able to check that all the 8 bits of the command were sent before the value : it works.

The other thing I had to check was the clock polarity (also discussed in the previous post), and for this the MCP4131 Datasheet provides the needed information.


It seems it can work either way (called mode 1.1 and 0.0), I decided to go for 1.1, clock polarity high.
We should be all set, time to probe what's happening with the wiper.
Since oscilloscopes can measure voltages, but not directly resistance, I created a simple voltage divider using the digital pot terminals, so that the voltage on the wiper varies based on its position.

Now, lowering considerably the scan frequency of the scope, I would expect to see a ramp from 0 to 127 and from 127 down to 0, basically a triangle waveform with low frequency.
Instead this is what I got.


Doh!
Not quite a triangle eh?
The issues appears quite obvious : see the signal is going to zero every other change?
That means that the highest bit is changing at each iteration, but in a normal increment  that should happen to the lowest bit... unless you reversed your byte.
Yop, SPI can send MSB first or LSB first and, guess what, the slave needs MSB first and I am sending LSB first instead.
That did not affect the command ( 0 ) since it is symmetric, but it did absolutely affect the wiper level byte.

USCI has a bit to configure MSB /LSB settings, so I updated the spiConfig procedure : 
UCA0CTL0 |=   UCCKPL +UCMST + UCMODE_0 + UCSYNC + UCMSB;

Did it work?
Nope!! I got a flat steady value on the wiper level, so I checked again what was going through the SPI bus and I found this : 


  
Oh! This is NOT nice.
Turns out (don't know the reason yet) that if the last bit sent is high, the spi bus is maintained high instead of falling back to low.
This happens only if you set the UCMSB flag in the configuration (Control Register 0 ).
Not sure what's happening there, I might be using the wrong constant, will digg deeper, anyhow there is an easy workaround : reverse the byte via software while keeping the hardware settings to LSB.

I did a simple test first, while in LSB first mode, I replaced the ramp generation with a single bit output step with the following sequence :
128 , 64, 32, 16, 8, 4, 2, 1

And this was the result (red line) :

And this confirms that the bits are reversed, so the setPotValue proc becomes
void setPotValue(unsigned char dataOut)
{
unsigned char revData;
UCA0TXBUF = 0;  // Send command
revData=0;
int i;
unsigned char bit;
for (i=0;i<8;i++)
{
bit = dataOut & 1;
dataOut = dataOut >> 1;
revData = revData << 1;
if (bit==1) revData++;
}
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
UCA0TXBUF = revData;//dataOut; // Send wiper level
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
}

The ramp generation is reactivated again,and... tadaaa!


The workaround is a temporary solution until I figure out how to fix this MSB issue, however it's not too bad as it's not affecting the code execution performance since the byte reversal is done while waiting for the SPI TX buffer to be ready to receive another byte.

I am now (almost) ready to plug this circuit into the rest of my experiment, which involves 80V, 5.5Amps, some FET, a Hall effect current sensor... and probably some "magic smoke" :)

Before working on that one, however, I thought it might be useful to consider an interesting detail of the USCI serial :
It actually has two ports (A and B) and while port A supports UART,SPI, I2C, port B supports "only" SPI and I2C.
It would probably make sense in my case to switch my spi bus to port B and free up port A to drive a RS485 uart.
It's probably a good idea, if you are using a single SPI or I2C, to drive it with port B. 

Saturday, July 28, 2012

MSP430G2 - (USCI) SPI interface 1

I have been testing the UART on the MSP430G2553 (using the launchpad) not long ago.
I managed to build a very simple RS485 interface and test it.
Links to that part here :
http://fortytwoandnow.blogspot.ch/2012/06/msp430g2-serial-communication-1.html
http://fortytwoandnow.blogspot.ch/2012/06/msp430g2-serial-communication-2-rs485.html

Today I am dealing with a SPI device, in my case a MCP4131 digital potentiometer.
If you don't know what SPI is, or you want to dig a bit more into it, I suggest you read here :[wikipedia].

A digital pot is quite a simple device which receives commands on the serial bus (SPI in this case, it's pretty common) and switches a resistor network emulating the wiper of a potentiometer.
It is an handy device used in i.e. hifi equipment to digitally set the volume.

The device I use is from Microchip, it's the quite popular MCP4131 -103



Anyhow, today I will focus on the lancuhpad part, I am not really checking if the values are set correctly on the pot, that will be a task for later.

The MSP430G2 microcontrollers have two peripherals to handle the hardware serial communications : the USI and the USCI.
Depending on which exact device you are using, you may have one or the other.
"High end" devices such as the G2553 will have USCI.

A list of devices with details on which is supporting USCI and which USI can be found here (TI website).

The basic difference is that USCI will support hardware TTL UART on top of I2C and SPI.
Since USCI and USI use different registers (they are actually significantly different implementations of hardware serial interfaces), this post will not be helpful if your device needs to be programmed using USI.

The first thing to find out is where to connect the MISO, MOSI and SCK lines on the microcontroller.


The device specific datasheet reports the various pins with the functionality they support.
If you followed my previous posts (or any other instruction material on these MCUs) you probably know that each pin can be configured to provide different functions.
In this case we find that the pin P1.4 also supports the hardware serial port A0 (UCA0) clock (CLK) signal.
Normally we need to specifically set the "direction" of each pin we select, however in this case the datasheets notifies us that the USCI interface will manage that.
This is because the USCI can be configured as SPI master (this will be our case) or SPI slave and in the first case it will OUTPUT a clock signal, while in the second one it will RECEIVE a signal from the master (the pin direction is different in the two cases)

We also notice that the UCA0CLK is "mode 3", so it is selected setting high the bit 4 in both the P1SEL and P2SEL registers.


In a partially failed attempt to confuse me, TI called the MISO (Master In Slave Out) "SOMI" and the MOSI (Master Out Slave In) "SIMO".
Anyhow we can find them at pin P1.1 and P1.2, still mdoe 3 and direction automatically set by USCI.

The SPI bus also needs a CS (Chip select) which is normally generated via a normal GPIO port.
This is needed when you have many devices connected on the same SPI bus (SPI supports multiple slaves), normally you want to communicate to each one of them individually, so a different CS line will be used to enable only one at a time.
In this experiment we only have 1 device, so we do not need to dynamically "select" it.

Let's get started with some code.
First we need to set up the cpu clock, I will go "full throttle" at 16MHz (just because we can, don't think it's needed nor smart for this specific application).
I plan to use SMCLK to generate the clock for the serial interface and a quick look to the MCP4131 tells me it won't work at 16MHz as it is rated for 10MHz maximum.
4MHz sounds reasonable, so SMCLK will be MCLK / 4.

If you don't know how to operate the MSP430G2 clock (and you want to know more about it), you can check here.

/*
 * main.c
 */


#include <msp430g2553.h>

unsigned char potLevel;


void clockConfig()
{
 // configure the CPU clock (MCLK)
 // to run from DCO @ 16MHz and SMCLK = DCO / 4
 BCSCTL1 = CALBC1_16MHZ; // Set DCO
 DCOCTL = CALDCO_16MHZ;
 BCSCTL2= DIVS_2 + DIVM_0; // divider=4 for SMCLK and 1 for MCLK
}

The second thing will be to set mode 3 for pins 1,2 and 4

void pinConfig()
{
 // set the pin mode 3 for pins 1  2 and 4 of port 1 (USCI mode)
 P1SEL = BIT1 + BIT2 + BIT4; // low bit = 1 for pin 1 and 2 4. BIT 3 is 0 (CS via GPIO)
 P1SEL2 = BIT1 + BIT2 + BIT4; // high bit = 1 for pin 1 and 2 4 BIT 3 is 0 (CS via GPIO)

 P1DIR |= BIT3; // p1.3 set to output to drive CS
 P1OUT &= ~BIT3; // pull p1.3 to low - CS low
}


I also decided to use pin 1.3 to drive the CS signal if needed.
Finally we have the most interesting part : configure USCI to work as a SPI Master.
Turns out it's pretty easy to achieve this, we will just need to :
  1. set the Control Register 0 for port UCA0 to be master, mode 0 and synchronous
  2. Select in the CR 1 the clock source to be SMCLK (UCSSEL_2) 
  3. Set the Baud Rate registers for any additional divider we may need
  4. Disable any modulation 
  5. Initialize the USCI 
// USCI
void spiConfig()
{
 UCA0CTL0 |= UCCKPL+ UCMST + UCMODE_0 + UCSYNC; 
  // synchronous (=SPI) master 3 wire SPI, clock polarity High
/*SPI mode is selected when the UCSYNC bit is set and SPI
mode (3-pin or 4-pin) is selected with the UCMODEx bits.*/

 //use SCLK : 4MHz (MCP4131 supports up to 10MHz write via SPI)
 UCA0CTL1 |= UCSSEL_2;
 // set baud rate = SMCLK, no further division
 UCA0BR0 = 0;
 UCA0BR1 = 0;
 UCA0MCTL = 0; // No modulation
 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI **
}  
Clock polarity can be set "high" or "low" using the UCCKPL bit in CR 0, to better understand what that means I suggest you check the video embedded below.

Finally I add a simple procedure to send out the SPI command to the digital pot.
According to the MCP4131 datasheet, to move the wiper (7 bit resolution) of the pot, we need to send command 0 (1 byte) followed by 1 byte with the value of the wiper position (0-127).
I added a small delay between the two bytes as that makes it easier for me to read the signal on the oscilloscope, might need to increase, lower or remove that delay in normal operations.


// drives a MCP4131 digital potentiometer via SPI
void setPotValue(unsigned char dataOut)
{
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
UCA0TXBUF = 0;  // Send command 0
__delay_cycles(50);
while (!(IFG2 & UCA0TXIFG)); // wait for TX buffer ready
UCA0TXBUF = dataOut; // Send wiper level
__delay_cycles(50);
}

and finally a main procedure that puts everything together.


void main(void)
{
// setup
 WDTCTL = WDTPW + WDTHOLD;
 clockConfig();
 pinConfig();
 spiConfig();
    // program execution loop
 while (1)
 {
for (potLevel=0;potLevel<128;potLevel++)
  {
setPotValue(potLevel);
__delay_cycles(100000); // I know, there are better ways...
  }
for (potLevel=127;potLevel>0;potLevel--)
  {
setPotValue(potLevel);
__delay_cycles(100000);
  }
 }
}


Time to build and load into the launchpad.

I connected my digital oscilloscope (100MHz, dual channel) to the clock and to MOSI.
The first thing I wanted to check (after verifying that indeed some clock and some data are actually sent over the SPI bus) is the clock frequency.




Manually placing the measurement cursors at the end of the rising edge of the clock, I found 4.032MHz, which is pretty close to the 4MHz we expected (need to account for some manual error in the way I placed the cursors and some tolerance in the DCO frequency).

Then I checked that the value passed as wiper level was changing over time, this is better visualized in the video I recorded



Now that it seems data is flowing through the SPI bus, I need to check it is correct and see if the MCP4131 receives it correctly, by monitoring he value of it's resistance... and this will be the topic of a future post, probably :)