Sign in

username:

password:



Not a member?

Search msp430



Search tips

Subscribe to msp430



Ads

Discussion Groups

See Also

DSPFPGAElectronics

Discussion Groups | MSP430 | SPI communcations appears to be losing a BIT

The purpose of this group is to foster exchange of information on the Texas Instruments MSP430 family of microcontrollers and related tools. Everyone welcome, all levels of familiarity/expertise.

SPI communcations appears to be losing a BIT - ajellisuk - Aug 25 5:09:40 2009

Hi

I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.

I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I'm expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I'm confident that they are ok. It would appear that the MSB is being lost in some SPI communications.

Has anyone else experienced problems like this? And if so how did you solve them?

I have pasted the relevent functions below.

Kind regards

Andrew

void init_spi0()
{
P3SEL |= 0x0E; // Setup P3 for SPI mode
P3DIR |= 0xE2; // P3.5 P3.1 for slave initialization
U0CTL |= SWRST;
ME1 |= USPIE0; // Module enable
U0CTL |= CHAR + SYNC + MM; // 8-bit, SPI, Master

U0TCTL_bit.STC = 1; // 3 pin SPI mode
U0TCTL_bit.SSEL1 = 1; // SMCLK
U0TCTL_bit.CKPH = 1;
U0TCTL_bit.CKPL = 1;

U0BR0 = 0x6b & 0xff; // SPICLK = SMCLK/40
U0BR1 = 0x00;
U0MCTL = 0x00; // No modulation
U0CTL &= ~SWRST; // SPI enable
}

unsigned long read_ADC24_1()

{

unsigned long int value = 0;

char dummy_char = 0;

U0TCTL_bit.CKPL = 1;

adc_CS = 1;

read_try=0;

adc_CS = 0;

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

//adc_time = 0;

while((U0TCTL & TXEPT) == 0);

read_try=0;

tosc=0;

while(!(IFG1 & URXIFG0)) {

if (tosc>50) {

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

//adc_time = 0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=1) {

if (read_try==15) return(0);

if (read_try==5) {

TXBUF0 = 0xFE; // Reset the ADC

tosc=0;

while(tosc<1);

TXBUF0 = 0xF0; // Do self cal

while(adc24_drdy==0);

while(adc24_drdy==1);

while(adc24_drdy==0);

while((U0TCTL & TXEPT) == 0);

}

read_try++;

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

// adc_time=0;

// }

}

}

}

IFG1 &= ~URXIFG0;

dummy_char = U0RXBUF;

read_try=0;

// Wait for 50 clk cycles

tosc=0;

while(tosc<50);

//adc_time=0;

while(adc24_drdy==1) {

// if (adc_time>=10) return (0);

}

// Read the most significant byte from the ADC

// We need to send a "dummy" bytes to the ADC to generate a clock pulse

// to clock out the data

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x02;

}

//adc_time=0;

while(!(IFG1 & URXIFG0)) {

// if (adc_time>=10) return (0);

while (adc24_drdy == 1);// return (0);

}

while (adc24_drdy == 1);// return (0);

IFG1 &= ~URXIFG0;

value = U0RXBUF;

value <<= 8;

//adc_time=0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=10) return (0);

}

// adc_time = 0;

while(adc24_drdy==1) {

// if (adc_time>=10) return (0);

}

// Read the middle byte

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x03;

}

// adc_time = 0;

while(!(IFG1 & URXIFG0)) {

//if (adc_time>=10) return (0);

while (adc24_drdy == 1);// return (0);

}

while (adc24_drdy == 1);// return (0);

IFG1 &= ~URXIFG0;

value |= U0RXBUF;

value <<= 8;

//adc_time = 0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=10) return (0);

}

// Read the least significant byte

//adc_time = 0;

while(adc24_drdy==1) {

// if (adc_time>=10) return (0);

}

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x04;

}

//adc_time = 0;

while(!(IFG1 & URXIFG0)) {

//if (adc_time>=10) return (0);

while (adc24_drdy == 1);// return (0);

}

// if (adc24_drdy == 1) return (0);

IFG1 &= ~URXIFG0;

value |= U0RXBUF;

adc_CS = 1;

return value;

}

unsigned long read_ADC24_2()

{

unsigned long int value = 0;

char dummy_char = 0;

adc_2_CS = 1;

read_try=0;

adc_2_CS = 0;

tosc=0;

U0TCTL_bit.CKPL = 1;

//while(tosc<500);

TXBUF0 = 0x50; // Write to reg 00h (setup reg)

while((U0TCTL & TXEPT) == 0);

TXBUF0 = 0x00; // reg is 1 byte

while((U0TCTL & TXEPT) == 0);

TXBUF0 = 0x00; // Set disable burnout and set gain to 1

while((U0TCTL & TXEPT) == 0);

//adc_time = 0;

while(adc24_2_drdy==1) {

//if (adc_time>=10) return (0);

}

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

while((U0TCTL & TXEPT) == 0);

read_try=0;

tosc=0;

while(!(IFG1 & URXIFG0)) {

if (tosc>50) {

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

//adc_time = 0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=1) {

if (read_try==15) return(0);

if (read_try==5) {

TXBUF0 = 0xFE; // Reset the ADC

tosc=0;

while(tosc<1);

TXBUF0 = 0xF0; // Do self cal

while(adc24_drdy==0);

while(adc24_drdy==1);

while(adc24_drdy==0);

while((U0TCTL & TXEPT) == 0);

}

read_try++;

// Issue a read command to the 24bit DAC

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x01;

}

// adc_time=0;

// }

}

}

}

IFG1 &= ~URXIFG0;

dummy_char = U0RXBUF;

read_try=0;

// Wait for 50 clk cycles

tosc=0;

while(tosc<50);

//adc_time=0;

while(adc24_2_drdy==1) {

// if (adc_time>=10) return (0);

}

// Read the most significant byte from the ADC

// We need to send a "dummy" bytes to the ADC to generate a clock pulse

// to clock out the data

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x02;

}

//adc_time=0;

while(!(IFG1 & URXIFG0)) {

// if (adc_time>=10) return (0);

while (adc24_2_drdy == 1);// return (0);

}

while (adc24_2_drdy == 1);// return (0);

IFG1 &= ~URXIFG0;

value = U0RXBUF;

value <<= 8;

//adc_time=0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=10) return (0);

}

// adc_time = 0;

while(adc24_2_drdy==1) {

// if (adc_time>=10) return (0);

}

// Read the middle byte

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x03;

}

// adc_time = 0;

while(!(IFG1 & URXIFG0)) {

//if (adc_time>=10) return (0);

while (adc24_2_drdy == 1);// return (0);

}

while (adc24_2_drdy == 1);// return (0);

IFG1 &= ~URXIFG0;

value |= U0RXBUF;

value <<= 8;

//adc_time = 0;

while((U0TCTL & TXEPT) == 0) {

//if (adc_time>=10) return (0);

}

// Read the least significant byte

//adc_time = 0;

while(adc24_2_drdy==1) {

// if (adc_time>=10) return (0);

}

if ((U0TCTL & TXEPT) == 1) {

TXBUF0 = 0x04;

}

//adc_time = 0;

while(!(IFG1 & URXIFG0)) {

//if (adc_time>=10) return (0);

while (adc24_2_drdy == 1);// return (0);

}

// if (adc24_drdy == 1) return (0);

IFG1 &= ~URXIFG0;

value |= U0RXBUF;

tosc=0;

// while(tosc<50);

adc_2_CS = 1;

tosc=0;

// while(tosc<50);

return value;

}

void set_channel_1(short channel)

{

adc_CS = 0;

U0TCTL_bit.CKPL = 1;

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

TXBUF0 = 0x51; // Write to reg 10h (MUX)

while((U0TCTL & TXEPT) == 0);

tosc=0;

while(tosc<50);

TXBUF0 = 0x00; // reg is 1 byte

while((U0TCTL & TXEPT) == 0);////////////////////////////////////////

tosc=0;

while(tosc<50);

TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel

while((U0TCTL & TXEPT) == 0);////////////////////////////////////////

tosc=0;

while(tosc<50);

//adc_time = 0;

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==0) {

//if (adc_time>=10) return (0);

}

while(adc24_drdy==1) {

//if (adc_time>=10) return (0);

}

adc_CS = 1;

}

------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )


Re: SPI communcations appears to be losing a BIT - old_cow_yellow - Aug 25 11:40:47 2009

Are you sure about your CKPL bit setting? I suspect that you are reading at the wrong edge.

--- In m...@yahoogroups.com, "ajellisuk" wrote:
>
> Hi
>
> I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.
>
> I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I'm expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I'm confident that they are ok. It would appear that the MSB is being lost in some SPI communications.
>
> Has anyone else experienced problems like this? And if so how did you solve them?
>
> I have pasted the relevent functions below.
>
> Kind regards
>
> Andrew
>
> void init_spi0()
> {
> P3SEL |= 0x0E; // Setup P3 for SPI mode
> P3DIR |= 0xE2; // P3.5 P3.1 for slave initialization
> U0CTL |= SWRST;
> ME1 |= USPIE0; // Module enable
> U0CTL |= CHAR + SYNC + MM; // 8-bit, SPI, Master
>
> U0TCTL_bit.STC = 1; // 3 pin SPI mode
> U0TCTL_bit.SSEL1 = 1; // SMCLK
> U0TCTL_bit.CKPH = 1;
> U0TCTL_bit.CKPL = 1;
>
> U0BR0 = 0x6b & 0xff; // SPICLK = SMCLK/40
> U0BR1 = 0x00;
> U0MCTL = 0x00; // No modulation
> U0CTL &= ~SWRST; // SPI enable
> }
>
> unsigned long read_ADC24_1()
>
> {
>
> unsigned long int value = 0;
>
> char dummy_char = 0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> adc_CS = 1;
>
> read_try=0;
>
> adc_CS = 0;
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> read_try=0;
>
> tosc=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> if (tosc>50) {
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=1) {
>
> if (read_try==15) return(0);
>
> if (read_try==5) {
>
> TXBUF0 = 0xFE; // Reset the ADC
>
> tosc=0;
>
> while(tosc<1);
>
> TXBUF0 = 0xF0; // Do self cal
>
> while(adc24_drdy==0);
>
> while(adc24_drdy==1);
>
> while(adc24_drdy==0);
>
> while((U0TCTL & TXEPT) == 0);
>
> }
>
> read_try++;
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
> // adc_time=0;
>
> // }
>
>
>
> }
>
>
>
> }
>
> }
>
> IFG1 &= ~URXIFG0;
>
> dummy_char = U0RXBUF;
>
> read_try=0;
>
>
>
> // Wait for 50 clk cycles
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time=0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> // Read the most significant byte from the ADC
>
> // We need to send a "dummy" bytes to the ADC to generate a clock pulse
>
> // to clock out the data
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x02;
>
> }
>
> //adc_time=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> // if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
> while (adc24_drdy == 1);// return (0);
>
> IFG1 &= ~URXIFG0;
>
>
>
> value = U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time=0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // adc_time = 0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> // Read the middle byte
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x03;
>
> }
>
>
>
> // adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
>
>
> while (adc24_drdy == 1);// return (0);
>
>
>
>
>
>
>
> IFG1 &= ~URXIFG0;
>
>
>
> value |= U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the least significant byte
>
> //adc_time = 0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x04;
>
> }
>
>
>
> //adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
>
>
> // if (adc24_drdy == 1) return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
> value |= U0RXBUF;
>
>
>
> adc_CS = 1;
>
>
>
> return value;
>
> }
>
>
>
> unsigned long read_ADC24_2()
>
> {
>
> unsigned long int value = 0;
>
> char dummy_char = 0;
>
> adc_2_CS = 1;
>
> read_try=0;
>
> adc_2_CS = 0;
>
>
>
> tosc=0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> //while(tosc<500);
>
>
>
> TXBUF0 = 0x50; // Write to reg 00h (setup reg)
>
> while((U0TCTL & TXEPT) == 0);
>
> TXBUF0 = 0x00; // reg is 1 byte
>
> while((U0TCTL & TXEPT) == 0);
>
> TXBUF0 = 0x00; // Set disable burnout and set gain to 1
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> //adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> read_try=0;
>
> tosc=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> if (tosc>50) {
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=1) {
>
> if (read_try==15) return(0);
>
> if (read_try==5) {
>
> TXBUF0 = 0xFE; // Reset the ADC
>
> tosc=0;
>
> while(tosc<1);
>
> TXBUF0 = 0xF0; // Do self cal
>
> while(adc24_drdy==0);
>
> while(adc24_drdy==1);
>
> while(adc24_drdy==0);
>
> while((U0TCTL & TXEPT) == 0);
>
> }
>
> read_try++;
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
> // adc_time=0;
>
> // }
>
>
>
> }
>
>
>
> }
>
> }
>
> IFG1 &= ~URXIFG0;
>
> dummy_char = U0RXBUF;
>
> read_try=0;
>
>
>
> // Wait for 50 clk cycles
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time=0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the most significant byte from the ADC
>
> // We need to send a "dummy" bytes to the ADC to generate a clock pulse
>
> // to clock out the data
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x02;
>
> }
>
> //adc_time=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> // if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
> while (adc24_2_drdy == 1);// return (0);
>
> IFG1 &= ~URXIFG0;
>
>
>
> value = U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time=0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the middle byte
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x03;
>
> }
>
>
>
> // adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
>
>
> while (adc24_2_drdy == 1);// return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
>
>
> value |= U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the least significant byte
>
> //adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x04;
>
> }
>
>
>
> //adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
>
>
> // if (adc24_drdy == 1) return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
> value |= U0RXBUF;
>
>
>
> tosc=0;
>
> // while(tosc<50);
>
>
>
> adc_2_CS = 1;
>
>
>
>
>
> tosc=0;
>
> // while(tosc<50);
>
> return value;
>
> }
>
>
>
> void set_channel_1(short channel)
>
> {
>
> adc_CS = 0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> TXBUF0 = 0x51; // Write to reg 10h (MUX)
>
> while((U0TCTL & TXEPT) == 0);
>
> tosc=0;
>
> while(tosc<50);
>
> TXBUF0 = 0x00; // reg is 1 byte
>
> while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
>
> tosc=0;
>
> while(tosc<50);
>
> TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel
>
> while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
>
>
>
>
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time = 0;
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> adc_CS = 1;
>
> }
>
------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - tintronic - Aug 25 13:24:48 2009

A couple of remarks:
> if ((U0TCTL & TXEPT) == 1)
Conceptually, this doesn't make any sense. It will only work if TXEPT is defines as 1. Given that case you should use either
if ((U0TCTL & 1) == 1)
or
if ((U0TCTL & TXEPT) == TXEPT)

Which is better written as just
if (U0TCTL & TXEPT)

Similarly, when testing TXEPT == 0, use
if (!(U0TCTL & TXEPT))

I don't know if you realize that for each byte sent, one byte is received, which automatically sets U0RXIFG. The code you posted has so many blank lines and commented code that it makes it very hard to follow. Also I'd say it's very disorderly written. What I can gather from your code is that you don't understand much about how the SPI hardware works. Take the time to read the SPI chapter COMPLETELY from top to bottom before continuing.

You think you're missing the msb, but I think you might be missing the lsb. Think about it: if you don't receive the last bit, each bit has half its weight, but if you miss the msb it would have double the value, not half of it. As OCY said, it might be a problem with the polarity. It's not always easy to match the MSP SPI graph with the SPI devices graph. There are many SPI communication examples in the web and in this forum. Search for a couple of them and compare them with your code. It doesn't matter that it is a different device like an EEPROM or RF chip, just compare the way the SPI communication is handled.

Regards,
Michael K.

--- In m...@yahoogroups.com, "ajellisuk" wrote:
>
> Hi
>
> I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.
>
> I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I'm expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I'm confident that they are ok. It would appear that the MSB is being lost in some SPI communications.
>
> Has anyone else experienced problems like this? And if so how did you solve them?
>
> I have pasted the relevent functions below.
>
> Kind regards
>
> Andrew
>
> void init_spi0()
> {
> P3SEL |= 0x0E; // Setup P3 for SPI mode
> P3DIR |= 0xE2; // P3.5 P3.1 for slave initialization
> U0CTL |= SWRST;
> ME1 |= USPIE0; // Module enable
> U0CTL |= CHAR + SYNC + MM; // 8-bit, SPI, Master
>
> U0TCTL_bit.STC = 1; // 3 pin SPI mode
> U0TCTL_bit.SSEL1 = 1; // SMCLK
> U0TCTL_bit.CKPH = 1;
> U0TCTL_bit.CKPL = 1;
>
> U0BR0 = 0x6b & 0xff; // SPICLK = SMCLK/40
> U0BR1 = 0x00;
> U0MCTL = 0x00; // No modulation
> U0CTL &= ~SWRST; // SPI enable
> }
>
> unsigned long read_ADC24_1()
>
> {
>
> unsigned long int value = 0;
>
> char dummy_char = 0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> adc_CS = 1;
>
> read_try=0;
>
> adc_CS = 0;
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> read_try=0;
>
> tosc=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> if (tosc>50) {
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=1) {
>
> if (read_try==15) return(0);
>
> if (read_try==5) {
>
> TXBUF0 = 0xFE; // Reset the ADC
>
> tosc=0;
>
> while(tosc<1);
>
> TXBUF0 = 0xF0; // Do self cal
>
> while(adc24_drdy==0);
>
> while(adc24_drdy==1);
>
> while(adc24_drdy==0);
>
> while((U0TCTL & TXEPT) == 0);
>
> }
>
> read_try++;
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
> // adc_time=0;
>
> // }
>
>
>
> }
>
>
>
> }
>
> }
>
> IFG1 &= ~URXIFG0;
>
> dummy_char = U0RXBUF;
>
> read_try=0;
>
>
>
> // Wait for 50 clk cycles
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time=0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> // Read the most significant byte from the ADC
>
> // We need to send a "dummy" bytes to the ADC to generate a clock pulse
>
> // to clock out the data
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x02;
>
> }
>
> //adc_time=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> // if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
> while (adc24_drdy == 1);// return (0);
>
> IFG1 &= ~URXIFG0;
>
>
>
> value = U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time=0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // adc_time = 0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> // Read the middle byte
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x03;
>
> }
>
>
>
> // adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
>
>
> while (adc24_drdy == 1);// return (0);
>
>
>
>
>
>
>
> IFG1 &= ~URXIFG0;
>
>
>
> value |= U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the least significant byte
>
> //adc_time = 0;
>
> while(adc24_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x04;
>
> }
>
>
>
> //adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_drdy == 1);// return (0);
>
> }
>
>
>
> // if (adc24_drdy == 1) return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
> value |= U0RXBUF;
>
>
>
> adc_CS = 1;
>
>
>
> return value;
>
> }
>
>
>
> unsigned long read_ADC24_2()
>
> {
>
> unsigned long int value = 0;
>
> char dummy_char = 0;
>
> adc_2_CS = 1;
>
> read_try=0;
>
> adc_2_CS = 0;
>
>
>
> tosc=0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> //while(tosc<500);
>
>
>
> TXBUF0 = 0x50; // Write to reg 00h (setup reg)
>
> while((U0TCTL & TXEPT) == 0);
>
> TXBUF0 = 0x00; // reg is 1 byte
>
> while((U0TCTL & TXEPT) == 0);
>
> TXBUF0 = 0x00; // Set disable burnout and set gain to 1
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> //adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> while((U0TCTL & TXEPT) == 0);
>
>
>
> read_try=0;
>
> tosc=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> if (tosc>50) {
>
>
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=1) {
>
> if (read_try==15) return(0);
>
> if (read_try==5) {
>
> TXBUF0 = 0xFE; // Reset the ADC
>
> tosc=0;
>
> while(tosc<1);
>
> TXBUF0 = 0xF0; // Do self cal
>
> while(adc24_drdy==0);
>
> while(adc24_drdy==1);
>
> while(adc24_drdy==0);
>
> while((U0TCTL & TXEPT) == 0);
>
> }
>
> read_try++;
>
> // Issue a read command to the 24bit DAC
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x01;
>
> }
>
> // adc_time=0;
>
> // }
>
>
>
> }
>
>
>
> }
>
> }
>
> IFG1 &= ~URXIFG0;
>
> dummy_char = U0RXBUF;
>
> read_try=0;
>
>
>
> // Wait for 50 clk cycles
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time=0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the most significant byte from the ADC
>
> // We need to send a "dummy" bytes to the ADC to generate a clock pulse
>
> // to clock out the data
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x02;
>
> }
>
> //adc_time=0;
>
> while(!(IFG1 & URXIFG0)) {
>
> // if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
> while (adc24_2_drdy == 1);// return (0);
>
> IFG1 &= ~URXIFG0;
>
>
>
> value = U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time=0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the middle byte
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x03;
>
> }
>
>
>
> // adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
>
>
> while (adc24_2_drdy == 1);// return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
>
>
> value |= U0RXBUF;
>
>
>
> value <<= 8;
>
>
>
> //adc_time = 0;
>
> while((U0TCTL & TXEPT) == 0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> // Read the least significant byte
>
> //adc_time = 0;
>
> while(adc24_2_drdy==1) {
>
> // if (adc_time>=10) return (0);
>
> }
>
>
>
> if ((U0TCTL & TXEPT) == 1) {
>
> TXBUF0 = 0x04;
>
> }
>
>
>
> //adc_time = 0;
>
> while(!(IFG1 & URXIFG0)) {
>
> //if (adc_time>=10) return (0);
>
> while (adc24_2_drdy == 1);// return (0);
>
> }
>
>
>
> // if (adc24_drdy == 1) return (0);
>
>
>
> IFG1 &= ~URXIFG0;
>
> value |= U0RXBUF;
>
>
>
> tosc=0;
>
> // while(tosc<50);
>
>
>
> adc_2_CS = 1;
>
>
>
>
>
> tosc=0;
>
> // while(tosc<50);
>
> return value;
>
> }
>
>
>
> void set_channel_1(short channel)
>
> {
>
> adc_CS = 0;
>
>
>
> U0TCTL_bit.CKPL = 1;
>
>
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
>
>
> TXBUF0 = 0x51; // Write to reg 10h (MUX)
>
> while((U0TCTL & TXEPT) == 0);
>
> tosc=0;
>
> while(tosc<50);
>
> TXBUF0 = 0x00; // reg is 1 byte
>
> while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
>
> tosc=0;
>
> while(tosc<50);
>
> TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel
>
> while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
>
>
>
>
>
> tosc=0;
>
> while(tosc<50);
>
>
>
> //adc_time = 0;
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==0) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> while(adc24_drdy==1) {
>
> //if (adc_time>=10) return (0);
>
> }
>
> adc_CS = 1;
>
> }
>
------------------------------------

______________________________
Stellaris® MCU Family: New Parts, New Package, New Price.


(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - ajellisuk - Aug 25 17:45:41 2009

Hi Michael & OCY

Thanks you for your replies and advice.

I will get my head down and read through the MSP430 documentation and some example SPI code before proceeding with my project.

Kind regards

Andrew

--- In m...@yahoogroups.com, "tintronic" wrote:
>
> A couple of remarks:
> > if ((U0TCTL & TXEPT) == 1)
> Conceptually, this doesn't make any sense. It will only work if TXEPT is defines as 1. Given that case you should use either
> if ((U0TCTL & 1) == 1)
> or
> if ((U0TCTL & TXEPT) == TXEPT)
>
> Which is better written as just
> if (U0TCTL & TXEPT)
>
> Similarly, when testing TXEPT == 0, use
> if (!(U0TCTL & TXEPT))
>
> I don't know if you realize that for each byte sent, one byte is received, which automatically sets U0RXIFG. The code you posted has so many blank lines and commented code that it makes it very hard to follow. Also I'd say it's very disorderly written. What I can gather from your code is that you don't understand much about how the SPI hardware works. Take the time to read the SPI chapter COMPLETELY from top to bottom before continuing.
>
> You think you're missing the msb, but I think you might be missing the lsb. Think about it: if you don't receive the last bit, each bit has half its weight, but if you miss the msb it would have double the value, not half of it. As OCY said, it might be a problem with the polarity. It's not always easy to match the MSP SPI graph with the SPI devices graph. There are many SPI communication examples in the web and in this forum. Search for a couple of them and compare them with your code. It doesn't matter that it is a different device like an EEPROM or RF chip, just compare the way the SPI communication is handled.
>
> Regards,
> Michael K.
>
> --- In m...@yahoogroups.com, "ajellisuk" wrote:
> >
> > Hi
> >
> > I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.
> >
> > I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I'm expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I'm confident that they are ok. It would appear that the MSB is being lost in some SPI communications.
> >
> > Has anyone else experienced problems like this? And if so how did you solve them?
> >
> > I have pasted the relevent functions below.
> >
> > Kind regards
> >
> > Andrew
> >
> > void init_spi0()
> > {
> > P3SEL |= 0x0E; // Setup P3 for SPI mode
> > P3DIR |= 0xE2; // P3.5 P3.1 for slave initialization
> > U0CTL |= SWRST;
> > ME1 |= USPIE0; // Module enable
> > U0CTL |= CHAR + SYNC + MM; // 8-bit, SPI, Master
> >
> > U0TCTL_bit.STC = 1; // 3 pin SPI mode
> > U0TCTL_bit.SSEL1 = 1; // SMCLK
> > U0TCTL_bit.CKPH = 1;
> > U0TCTL_bit.CKPL = 1;
> >
> > U0BR0 = 0x6b & 0xff; // SPICLK = SMCLK/40
> > U0BR1 = 0x00;
> > U0MCTL = 0x00; // No modulation
> > U0CTL &= ~SWRST; // SPI enable
> > }
> >
> > unsigned long read_ADC24_1()
> >
> > {
> >
> > unsigned long int value = 0;
> >
> > char dummy_char = 0;
> >
> >
> >
> > U0TCTL_bit.CKPL = 1;
> >
> >
> >
> > adc_CS = 1;
> >
> > read_try=0;
> >
> > adc_CS = 0;
> >
> >
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> >
> >
> > //adc_time = 0;
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> >
> >
> > read_try=0;
> >
> > tosc=0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > if (tosc>50) {
> >
> >
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> >
> >
> > //adc_time = 0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=1) {
> >
> > if (read_try==15) return(0);
> >
> > if (read_try==5) {
> >
> > TXBUF0 = 0xFE; // Reset the ADC
> >
> > tosc=0;
> >
> > while(tosc<1);
> >
> > TXBUF0 = 0xF0; // Do self cal
> >
> > while(adc24_drdy==0);
> >
> > while(adc24_drdy==1);
> >
> > while(adc24_drdy==0);
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> > }
> >
> > read_try++;
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> > // adc_time=0;
> >
> > // }
> >
> >
> >
> > }
> >
> >
> >
> > }
> >
> > }
> >
> > IFG1 &= ~URXIFG0;
> >
> > dummy_char = U0RXBUF;
> >
> > read_try=0;
> >
> >
> >
> > // Wait for 50 clk cycles
> >
> > tosc=0;
> >
> > while(tosc<50);
> >
> >
> >
> > //adc_time=0;
> >
> > while(adc24_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> >
> >
> > // Read the most significant byte from the ADC
> >
> > // We need to send a "dummy" bytes to the ADC to generate a clock pulse
> >
> > // to clock out the data
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x02;
> >
> > }
> >
> > //adc_time=0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > // if (adc_time>=10) return (0);
> >
> > while (adc24_drdy == 1);// return (0);
> >
> > }
> >
> > while (adc24_drdy == 1);// return (0);
> >
> > IFG1 &= ~URXIFG0;
> >
> >
> >
> > value = U0RXBUF;
> >
> >
> >
> > value <<= 8;
> >
> >
> >
> > //adc_time=0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // adc_time = 0;
> >
> > while(adc24_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> >
> >
> > // Read the middle byte
> >
> >
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x03;
> >
> > }
> >
> >
> >
> > // adc_time = 0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > //if (adc_time>=10) return (0);
> >
> > while (adc24_drdy == 1);// return (0);
> >
> > }
> >
> >
> >
> > while (adc24_drdy == 1);// return (0);
> >
> >
> >
> >
> >
> >
> >
> > IFG1 &= ~URXIFG0;
> >
> >
> >
> > value |= U0RXBUF;
> >
> >
> >
> > value <<= 8;
> >
> >
> >
> > //adc_time = 0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // Read the least significant byte
> >
> > //adc_time = 0;
> >
> > while(adc24_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> >
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x04;
> >
> > }
> >
> >
> >
> > //adc_time = 0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > //if (adc_time>=10) return (0);
> >
> > while (adc24_drdy == 1);// return (0);
> >
> > }
> >
> >
> >
> > // if (adc24_drdy == 1) return (0);
> >
> >
> >
> > IFG1 &= ~URXIFG0;
> >
> > value |= U0RXBUF;
> >
> >
> >
> > adc_CS = 1;
> >
> >
> >
> > return value;
> >
> > }
> >
> >
> >
> > unsigned long read_ADC24_2()
> >
> > {
> >
> > unsigned long int value = 0;
> >
> > char dummy_char = 0;
> >
> > adc_2_CS = 1;
> >
> > read_try=0;
> >
> > adc_2_CS = 0;
> >
> >
> >
> > tosc=0;
> >
> >
> >
> > U0TCTL_bit.CKPL = 1;
> >
> >
> >
> > //while(tosc<500);
> >
> >
> >
> > TXBUF0 = 0x50; // Write to reg 00h (setup reg)
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> > TXBUF0 = 0x00; // reg is 1 byte
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> > TXBUF0 = 0x00; // Set disable burnout and set gain to 1
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> >
> >
> > //adc_time = 0;
> >
> > while(adc24_2_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> >
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> >
> >
> > read_try=0;
> >
> > tosc=0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > if (tosc>50) {
> >
> >
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> >
> >
> > //adc_time = 0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=1) {
> >
> > if (read_try==15) return(0);
> >
> > if (read_try==5) {
> >
> > TXBUF0 = 0xFE; // Reset the ADC
> >
> > tosc=0;
> >
> > while(tosc<1);
> >
> > TXBUF0 = 0xF0; // Do self cal
> >
> > while(adc24_drdy==0);
> >
> > while(adc24_drdy==1);
> >
> > while(adc24_drdy==0);
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> > }
> >
> > read_try++;
> >
> > // Issue a read command to the 24bit DAC
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x01;
> >
> > }
> >
> > // adc_time=0;
> >
> > // }
> >
> >
> >
> > }
> >
> >
> >
> > }
> >
> > }
> >
> > IFG1 &= ~URXIFG0;
> >
> > dummy_char = U0RXBUF;
> >
> > read_try=0;
> >
> >
> >
> > // Wait for 50 clk cycles
> >
> > tosc=0;
> >
> > while(tosc<50);
> >
> >
> >
> > //adc_time=0;
> >
> > while(adc24_2_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // Read the most significant byte from the ADC
> >
> > // We need to send a "dummy" bytes to the ADC to generate a clock pulse
> >
> > // to clock out the data
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x02;
> >
> > }
> >
> > //adc_time=0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > // if (adc_time>=10) return (0);
> >
> > while (adc24_2_drdy == 1);// return (0);
> >
> > }
> >
> > while (adc24_2_drdy == 1);// return (0);
> >
> > IFG1 &= ~URXIFG0;
> >
> >
> >
> > value = U0RXBUF;
> >
> >
> >
> > value <<= 8;
> >
> >
> >
> > //adc_time=0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // adc_time = 0;
> >
> > while(adc24_2_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // Read the middle byte
> >
> >
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x03;
> >
> > }
> >
> >
> >
> > // adc_time = 0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > //if (adc_time>=10) return (0);
> >
> > while (adc24_2_drdy == 1);// return (0);
> >
> > }
> >
> >
> >
> > while (adc24_2_drdy == 1);// return (0);
> >
> >
> >
> > IFG1 &= ~URXIFG0;
> >
> >
> >
> > value |= U0RXBUF;
> >
> >
> >
> > value <<= 8;
> >
> >
> >
> > //adc_time = 0;
> >
> > while((U0TCTL & TXEPT) == 0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > // Read the least significant byte
> >
> > //adc_time = 0;
> >
> > while(adc24_2_drdy==1) {
> >
> > // if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > if ((U0TCTL & TXEPT) == 1) {
> >
> > TXBUF0 = 0x04;
> >
> > }
> >
> >
> >
> > //adc_time = 0;
> >
> > while(!(IFG1 & URXIFG0)) {
> >
> > //if (adc_time>=10) return (0);
> >
> > while (adc24_2_drdy == 1);// return (0);
> >
> > }
> >
> >
> >
> > // if (adc24_drdy == 1) return (0);
> >
> >
> >
> > IFG1 &= ~URXIFG0;
> >
> > value |= U0RXBUF;
> >
> >
> >
> > tosc=0;
> >
> > // while(tosc<50);
> >
> >
> >
> > adc_2_CS = 1;
> >
> >
> >
> >
> >
> > tosc=0;
> >
> > // while(tosc<50);
> >
> > return value;
> >
> > }
> >
> >
> >
> > void set_channel_1(short channel)
> >
> > {
> >
> > adc_CS = 0;
> >
> >
> >
> > U0TCTL_bit.CKPL = 1;
> >
> >
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> >
> >
> > TXBUF0 = 0x51; // Write to reg 10h (MUX)
> >
> > while((U0TCTL & TXEPT) == 0);
> >
> > tosc=0;
> >
> > while(tosc<50);
> >
> > TXBUF0 = 0x00; // reg is 1 byte
> >
> > while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
> >
> > tosc=0;
> >
> > while(tosc<50);
> >
> > TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel
> >
> > while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
> >
> >
> >
> >
> >
> > tosc=0;
> >
> > while(tosc<50);
> >
> >
> >
> > //adc_time = 0;
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==0) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > while(adc24_drdy==1) {
> >
> > //if (adc_time>=10) return (0);
> >
> > }
> >
> > adc_CS = 1;
> >
> > }
>

------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - ajellisuk - Aug 26 6:58:59 2009

Hi,

After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.

I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.

Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?

I have pasted the code for accessing the digital pot below.

Kind regards

Andrew

// Sets the "pot" wiper position to "position"
void set_digi_pot(char pot, int position)
{
char data[3] = {0};

// Change the phase of the SPI clock for the digipot
U0TCTL_bit.CKPH = 1;
U0TCTL_bit.CKPL = 0;

if (pot == 0)
data[0] = 0xB0;

if (pot == 1)
data[0] = 0xB1;

data[1] = position >> 8;
data[2] = position;

digipot_cs = 0; // cs low
spi_write(3, (unsigned char*)data);
digipot_cs = 1; // cs high

// Change the phase for the ADC
U0TCTL_bit.CKPH = 0;
U0TCTL_bit.CKPL = 0;

}
--- In m...@yahoogroups.com, "ajellisuk" wrote:
>
> Hi Michael & OCY
>
> Thanks you for your replies and advice.
>
> I will get my head down and read through the MSP430 documentation and some example SPI code before proceeding with my project.
>
> Kind regards
>
> Andrew
>
> --- In m...@yahoogroups.com, "tintronic" wrote:
> >
> > A couple of remarks:
> > > if ((U0TCTL & TXEPT) == 1)
> > Conceptually, this doesn't make any sense. It will only work if TXEPT is defines as 1. Given that case you should use either
> > if ((U0TCTL & 1) == 1)
> > or
> > if ((U0TCTL & TXEPT) == TXEPT)
> >
> > Which is better written as just
> > if (U0TCTL & TXEPT)
> >
> > Similarly, when testing TXEPT == 0, use
> > if (!(U0TCTL & TXEPT))
> >
> > I don't know if you realize that for each byte sent, one byte is received, which automatically sets U0RXIFG. The code you posted has so many blank lines and commented code that it makes it very hard to follow. Also I'd say it's very disorderly written. What I can gather from your code is that you don't understand much about how the SPI hardware works. Take the time to read the SPI chapter COMPLETELY from top to bottom before continuing.
> >
> > You think you're missing the msb, but I think you might be missing the lsb. Think about it: if you don't receive the last bit, each bit has half its weight, but if you miss the msb it would have double the value, not half of it. As OCY said, it might be a problem with the polarity. It's not always easy to match the MSP SPI graph with the SPI devices graph. There are many SPI communication examples in the web and in this forum. Search for a couple of them and compare them with your code. It doesn't matter that it is a different device like an EEPROM or RF chip, just compare the way the SPI communication is handled.
> >
> > Regards,
> > Michael K.
> >
> > --- In m...@yahoogroups.com, "ajellisuk" wrote:
> > >
> > > Hi
> > >
> > > I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.
> > >
> > > I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I'm expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I'm confident that they are ok. It would appear that the MSB is being lost in some SPI communications.
> > >
> > > Has anyone else experienced problems like this? And if so how did you solve them?
> > >
> > > I have pasted the relevent functions below.
> > >
> > > Kind regards
> > >
> > > Andrew
> > >
> > > void init_spi0()
> > > {
> > > P3SEL |= 0x0E; // Setup P3 for SPI mode
> > > P3DIR |= 0xE2; // P3.5 P3.1 for slave initialization
> > > U0CTL |= SWRST;
> > > ME1 |= USPIE0; // Module enable
> > > U0CTL |= CHAR + SYNC + MM; // 8-bit, SPI, Master
> > >
> > > U0TCTL_bit.STC = 1; // 3 pin SPI mode
> > > U0TCTL_bit.SSEL1 = 1; // SMCLK
> > > U0TCTL_bit.CKPH = 1;
> > > U0TCTL_bit.CKPL = 1;
> > >
> > > U0BR0 = 0x6b & 0xff; // SPICLK = SMCLK/40
> > > U0BR1 = 0x00;
> > > U0MCTL = 0x00; // No modulation
> > > U0CTL &= ~SWRST; // SPI enable
> > > }
> > >
> > > unsigned long read_ADC24_1()
> > >
> > > {
> > >
> > > unsigned long int value = 0;
> > >
> > > char dummy_char = 0;
> > >
> > >
> > >
> > > U0TCTL_bit.CKPL = 1;
> > >
> > >
> > >
> > > adc_CS = 1;
> > >
> > > read_try=0;
> > >
> > > adc_CS = 0;
> > >
> > >
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > >
> > >
> > > read_try=0;
> > >
> > > tosc=0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > if (tosc>50) {
> > >
> > >
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=1) {
> > >
> > > if (read_try==15) return(0);
> > >
> > > if (read_try==5) {
> > >
> > > TXBUF0 = 0xFE; // Reset the ADC
> > >
> > > tosc=0;
> > >
> > > while(tosc<1);
> > >
> > > TXBUF0 = 0xF0; // Do self cal
> > >
> > > while(adc24_drdy==0);
> > >
> > > while(adc24_drdy==1);
> > >
> > > while(adc24_drdy==0);
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > > }
> > >
> > > read_try++;
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > > // adc_time=0;
> > >
> > > // }
> > >
> > >
> > >
> > > }
> > >
> > >
> > >
> > > }
> > >
> > > }
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > > dummy_char = U0RXBUF;
> > >
> > > read_try=0;
> > >
> > >
> > >
> > > // Wait for 50 clk cycles
> > >
> > > tosc=0;
> > >
> > > while(tosc<50);
> > >
> > >
> > >
> > > //adc_time=0;
> > >
> > > while(adc24_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > >
> > >
> > > // Read the most significant byte from the ADC
> > >
> > > // We need to send a "dummy" bytes to the ADC to generate a clock pulse
> > >
> > > // to clock out the data
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x02;
> > >
> > > }
> > >
> > > //adc_time=0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > while (adc24_drdy == 1);// return (0);
> > >
> > > }
> > >
> > > while (adc24_drdy == 1);// return (0);
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > >
> > >
> > > value = U0RXBUF;
> > >
> > >
> > >
> > > value <<= 8;
> > >
> > >
> > >
> > > //adc_time=0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // adc_time = 0;
> > >
> > > while(adc24_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > >
> > >
> > > // Read the middle byte
> > >
> > >
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x03;
> > >
> > > }
> > >
> > >
> > >
> > > // adc_time = 0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > while (adc24_drdy == 1);// return (0);
> > >
> > > }
> > >
> > >
> > >
> > > while (adc24_drdy == 1);// return (0);
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > >
> > >
> > > value |= U0RXBUF;
> > >
> > >
> > >
> > > value <<= 8;
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // Read the least significant byte
> > >
> > > //adc_time = 0;
> > >
> > > while(adc24_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > >
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x04;
> > >
> > > }
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > while (adc24_drdy == 1);// return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // if (adc24_drdy == 1) return (0);
> > >
> > >
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > > value |= U0RXBUF;
> > >
> > >
> > >
> > > adc_CS = 1;
> > >
> > >
> > >
> > > return value;
> > >
> > > }
> > >
> > >
> > >
> > > unsigned long read_ADC24_2()
> > >
> > > {
> > >
> > > unsigned long int value = 0;
> > >
> > > char dummy_char = 0;
> > >
> > > adc_2_CS = 1;
> > >
> > > read_try=0;
> > >
> > > adc_2_CS = 0;
> > >
> > >
> > >
> > > tosc=0;
> > >
> > >
> > >
> > > U0TCTL_bit.CKPL = 1;
> > >
> > >
> > >
> > > //while(tosc<500);
> > >
> > >
> > >
> > > TXBUF0 = 0x50; // Write to reg 00h (setup reg)
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > > TXBUF0 = 0x00; // reg is 1 byte
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > > TXBUF0 = 0x00; // Set disable burnout and set gain to 1
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while(adc24_2_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > >
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > >
> > >
> > > read_try=0;
> > >
> > > tosc=0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > if (tosc>50) {
> > >
> > >
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=1) {
> > >
> > > if (read_try==15) return(0);
> > >
> > > if (read_try==5) {
> > >
> > > TXBUF0 = 0xFE; // Reset the ADC
> > >
> > > tosc=0;
> > >
> > > while(tosc<1);
> > >
> > > TXBUF0 = 0xF0; // Do self cal
> > >
> > > while(adc24_drdy==0);
> > >
> > > while(adc24_drdy==1);
> > >
> > > while(adc24_drdy==0);
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > > }
> > >
> > > read_try++;
> > >
> > > // Issue a read command to the 24bit DAC
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x01;
> > >
> > > }
> > >
> > > // adc_time=0;
> > >
> > > // }
> > >
> > >
> > >
> > > }
> > >
> > >
> > >
> > > }
> > >
> > > }
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > > dummy_char = U0RXBUF;
> > >
> > > read_try=0;
> > >
> > >
> > >
> > > // Wait for 50 clk cycles
> > >
> > > tosc=0;
> > >
> > > while(tosc<50);
> > >
> > >
> > >
> > > //adc_time=0;
> > >
> > > while(adc24_2_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // Read the most significant byte from the ADC
> > >
> > > // We need to send a "dummy" bytes to the ADC to generate a clock pulse
> > >
> > > // to clock out the data
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x02;
> > >
> > > }
> > >
> > > //adc_time=0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > while (adc24_2_drdy == 1);// return (0);
> > >
> > > }
> > >
> > > while (adc24_2_drdy == 1);// return (0);
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > >
> > >
> > > value = U0RXBUF;
> > >
> > >
> > >
> > > value <<= 8;
> > >
> > >
> > >
> > > //adc_time=0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // adc_time = 0;
> > >
> > > while(adc24_2_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // Read the middle byte
> > >
> > >
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x03;
> > >
> > > }
> > >
> > >
> > >
> > > // adc_time = 0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > while (adc24_2_drdy == 1);// return (0);
> > >
> > > }
> > >
> > >
> > >
> > > while (adc24_2_drdy == 1);// return (0);
> > >
> > >
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > >
> > >
> > > value |= U0RXBUF;
> > >
> > >
> > >
> > > value <<= 8;
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while((U0TCTL & TXEPT) == 0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // Read the least significant byte
> > >
> > > //adc_time = 0;
> > >
> > > while(adc24_2_drdy==1) {
> > >
> > > // if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > if ((U0TCTL & TXEPT) == 1) {
> > >
> > > TXBUF0 = 0x04;
> > >
> > > }
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while(!(IFG1 & URXIFG0)) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > while (adc24_2_drdy == 1);// return (0);
> > >
> > > }
> > >
> > >
> > >
> > > // if (adc24_drdy == 1) return (0);
> > >
> > >
> > >
> > > IFG1 &= ~URXIFG0;
> > >
> > > value |= U0RXBUF;
> > >
> > >
> > >
> > > tosc=0;
> > >
> > > // while(tosc<50);
> > >
> > >
> > >
> > > adc_2_CS = 1;
> > >
> > >
> > >
> > >
> > >
> > > tosc=0;
> > >
> > > // while(tosc<50);
> > >
> > > return value;
> > >
> > > }
> > >
> > >
> > >
> > > void set_channel_1(short channel)
> > >
> > > {
> > >
> > > adc_CS = 0;
> > >
> > >
> > >
> > > U0TCTL_bit.CKPL = 1;
> > >
> > >
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > >
> > >
> > > TXBUF0 = 0x51; // Write to reg 10h (MUX)
> > >
> > > while((U0TCTL & TXEPT) == 0);
> > >
> > > tosc=0;
> > >
> > > while(tosc<50);
> > >
> > > TXBUF0 = 0x00; // reg is 1 byte
> > >
> > > while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
> > >
> > > tosc=0;
> > >
> > > while(tosc<50);
> > >
> > > TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel
> > >
> > > while((U0TCTL & TXEPT) == 0);////////////////////////////////////////
> > >
> > >
> > >
> > >
> > >
> > > tosc=0;
> > >
> > > while(tosc<50);
> > >
> > >
> > >
> > > //adc_time = 0;
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==0) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > while(adc24_drdy==1) {
> > >
> > > //if (adc_time>=10) return (0);
> > >
> > > }
> > >
> > > adc_CS = 1;
> > >
> > > }
> > >
>

------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - tintronic - Aug 26 10:06:59 2009

Andrew,
You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.

The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).

In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.

I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
Not that it matters much, but what compiler are you using?

I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)

Regards,
Michael K.

--- In m...@yahoogroups.com, "ajellisuk" wrote:
>
> Hi,
>
> After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
>
> I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
>
> Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
>
> I have pasted the code for accessing the digital pot below.
>
> Kind regards
>
> Andrew
>
> // Sets the "pot" wiper position to "position"
> void set_digi_pot(char pot, int position)
> {
> char data[3] = {0};
>
> // Change the phase of the SPI clock for the digipot
> U0TCTL_bit.CKPH = 1;
> U0TCTL_bit.CKPL = 0;
>
> if (pot == 0)
> data[0] = 0xB0;
>
> if (pot == 1)
> data[0] = 0xB1;
>
> data[1] = position >> 8;
> data[2] = position;
>
> digipot_cs = 0; // cs low
> spi_write(3, (unsigned char*)data);
> digipot_cs = 1; // cs high
>
> // Change the phase for the ADC
> U0TCTL_bit.CKPH = 0;
> U0TCTL_bit.CKPL = 0;
>
> }
------------------------------------

______________________________
Stellaris® MCU Family: New Parts, New Package, New Price.


(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - ajellisuk - Aug 26 11:56:47 2009

Hi Michael

Thank you for your reply.

I'm a little confused with the digital pot I'm using. The data sheet clearly states that the device works with mode 0 or 3, but in reality it doesn't work with either! It only works with mode 1. I'll look into the timing issue tomorrow.

I have posted the code for my SPI write function below.

Kind regards

Andrew

void spi_write(char num_bytes, unsigned char *data)
{
do {
TXBUF0 = *data++;
while (!(U0TCTL & TXEPT));
} while (--num_bytes);
}

--- In m...@yahoogroups.com, "tintronic" wrote:
>
> Andrew,
> You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.
>
> The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).
>
> In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.
>
> I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
> Not that it matters much, but what compiler are you using?
>
> I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)
>
> Regards,
> Michael K.
>
> --- In m...@yahoogroups.com, "ajellisuk" wrote:
> >
> > Hi,
> >
> > After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
> >
> > I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
> >
> > Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
> >
> > I have pasted the code for accessing the digital pot below.
> >
> > Kind regards
> >
> > Andrew
> >
> > // Sets the "pot" wiper position to "position"
> > void set_digi_pot(char pot, int position)
> > {
> > char data[3] = {0};
> >
> > // Change the phase of the SPI clock for the digipot
> > U0TCTL_bit.CKPH = 1;
> > U0TCTL_bit.CKPL = 0;
> >
> > if (pot == 0)
> > data[0] = 0xB0;
> >
> > if (pot == 1)
> > data[0] = 0xB1;
> >
> > data[1] = position >> 8;
> > data[2] = position;
> >
> > digipot_cs = 0; // cs low
> > spi_write(3, (unsigned char*)data);
> > digipot_cs = 1; // cs high
> >
> > // Change the phase for the ADC
> > U0TCTL_bit.CKPH = 0;
> > U0TCTL_bit.CKPL = 0;
> >
> > }
>
------------------------------------

______________________________
Stellaris® MCU Family: New Parts, New Package, New Price.


(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - tintronic - Aug 26 12:45:10 2009

As I suspected, your problem is right there on your spi_write() and is related to the #CS handling. You're disabling the slave right after writing the last byte to the SPI hardware buffer. Depending on the speed you set up for the SPI, you might be gettenig the byte before last throught, but no way you're getting the last byte throught.

On another note, check the behaviour of U0TXIFG and TXEPT. Your SPI transfer will be faster of you use:
while (!(IFGx & U0TXIFG)); // IFG1 or IFG2 depending on the MSP model
// you're using
instead of
while (!(U0TCTL & TXEPT));
That means you only wait for the buffer to be empty, not the shift register to be empty. This way the next byte is transferred immediatel after the previous one, without wasting time for the buffer to be written and then transferred to the shift register.

As I mentioned previously, check for TXEPT before exiting the function, and then check for SCLK bit status so disabling #CS. That way you have made sure SPI communication finished before disabling the slave.

Regards,
Michael K.

--- In m...@yahoogroups.com, "ajellisuk" wrote:
>
> Hi Michael
>
> Thank you for your reply.
>
> I'm a little confused with the digital pot I'm using. The data sheet clearly states that the device works with mode 0 or 3, but in reality it doesn't work with either! It only works with mode 1. I'll look into the timing issue tomorrow.
>
> I have posted the code for my SPI write function below.
>
> Kind regards
>
> Andrew
>
> void spi_write(char num_bytes, unsigned char *data)
> {
> do {
> TXBUF0 = *data++;
> while (!(U0TCTL & TXEPT));
> } while (--num_bytes);
> }
>
> --- In m...@yahoogroups.com, "tintronic" wrote:
> >
> > Andrew,
> > You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.
> >
> > The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).
> >
> > In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.
> >
> > I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
> > Not that it matters much, but what compiler are you using?
> >
> > I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)
> >
> > Regards,
> > Michael K.
> >
> > --- In m...@yahoogroups.com, "ajellisuk" wrote:
> > >
> > > Hi,
> > >
> > > After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
> > >
> > > I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
> > >
> > > Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
> > >
> > > I have pasted the code for accessing the digital pot below.
> > >
> > > Kind regards
> > >
> > > Andrew
> > >
> > > // Sets the "pot" wiper position to "position"
> > > void set_digi_pot(char pot, int position)
> > > {
> > > char data[3] = {0};
> > >
> > > // Change the phase of the SPI clock for the digipot
> > > U0TCTL_bit.CKPH = 1;
> > > U0TCTL_bit.CKPL = 0;
> > >
> > > if (pot == 0)
> > > data[0] = 0xB0;
> > >
> > > if (pot == 1)
> > > data[0] = 0xB1;
> > >
> > > data[1] = position >> 8;
> > > data[2] = position;
> > >
> > > digipot_cs = 0; // cs low
> > > spi_write(3, (unsigned char*)data);
> > > digipot_cs = 1; // cs high
> > >
> > > // Change the phase for the ADC
> > > U0TCTL_bit.CKPH = 0;
> > > U0TCTL_bit.CKPL = 0;
> > >
> > > }
>

------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - ajellisuk - Sep 2 4:58:04 2009

Hi,

After taking a few days out from this problem and re reading the documentation I have solved my problem.

After re reading the MSP430F4xx manual I stumbled accross this section, and I quote:

"18.2.1 USART Initialization and Reset

The USART is reset by a PUC or by the SWRST bit. After a PUC, the SWRST
bit is automatically set, keeping the USART in a reset condition. When set, the
SWRST bit resets the URXIEx, UTXIEx, URXIFGx, OE, and FE bits and sets
the UTXIFGx flag. The USPIEx bit is not altered by SWRST. Clearing SWRST
releases the USART for operation. See also chapter 17.

Note: Initializing or Reconfiguring the USART Module
The required USART initialization/reconfiguration process is:
1) Set SWRST (BIS.B #SWRST,&UxCTL)
2) Initialize all USART registers with SWRST=1 (including UxCTL)
3) Enable USART module via the MEx SFRs (USPIEx)
4) Clear SWRST via software (BIC.B #SWRST,&UxCTL)
5) Enable interrupts (optional) via the IEx SFRs (URXIEx and/or UTXIEx)
Failure to follow this process may result in unpredictable USART behavior."

I was not carrying out the above steps when I was changing the clock polarity and phase, and therefore getting the unpredictable behaviour as the documentation warned me! I think I have learnt the hard way why one should read the documentation several times and carefully. I now feel a little sheepish.

Michael I would like to thank you for your advice. I have taken it on board and I have been careful to ensure the timing is correct when communicating with peripherals.

Kind regards

Andrew

--- In m...@yahoogroups.com, "tintronic" wrote:
>
> As I suspected, your problem is right there on your spi_write() and is related to the #CS handling. You're disabling the slave right after writing the last byte to the SPI hardware buffer. Depending on the speed you set up for the SPI, you might be gettenig the byte before last throught, but no way you're getting the last byte throught.
>
> On another note, check the behaviour of U0TXIFG and TXEPT. Your SPI transfer will be faster of you use:
> while (!(IFGx & U0TXIFG)); // IFG1 or IFG2 depending on the MSP model
> // you're using
> instead of
> while (!(U0TCTL & TXEPT));
> That means you only wait for the buffer to be empty, not the shift register to be empty. This way the next byte is transferred immediatel after the previous one, without wasting time for the buffer to be written and then transferred to the shift register.
>
> As I mentioned previously, check for TXEPT before exiting the function, and then check for SCLK bit status so disabling #CS. That way you have made sure SPI communication finished before disabling the slave.
>
> Regards,
> Michael K.
>
> --- In m...@yahoogroups.com, "ajellisuk" wrote:
> >
> > Hi Michael
> >
> > Thank you for your reply.
> >
> > I'm a little confused with the digital pot I'm using. The data sheet clearly states that the device works with mode 0 or 3, but in reality it doesn't work with either! It only works with mode 1. I'll look into the timing issue tomorrow.
> >
> > I have posted the code for my SPI write function below.
> >
> > Kind regards
> >
> > Andrew
> >
> > void spi_write(char num_bytes, unsigned char *data)
> > {
> > do {
> > TXBUF0 = *data++;
> > while (!(U0TCTL & TXEPT));
> > } while (--num_bytes);
> > }
> >
> > --- In m...@yahoogroups.com, "tintronic" wrote:
> > >
> > > Andrew,
> > > You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.
> > >
> > > The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).
> > >
> > > In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.
> > >
> > > I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
> > > Not that it matters much, but what compiler are you using?
> > >
> > > I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)
> > >
> > > Regards,
> > > Michael K.
> > >
> > > --- In m...@yahoogroups.com, "ajellisuk" wrote:
> > > >
> > > > Hi,
> > > >
> > > > After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
> > > >
> > > > I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
> > > >
> > > > Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
> > > >
> > > > I have pasted the code for accessing the digital pot below.
> > > >
> > > > Kind regards
> > > >
> > > > Andrew
> > > >
> > > > // Sets the "pot" wiper position to "position"
> > > > void set_digi_pot(char pot, int position)
> > > > {
> > > > char data[3] = {0};
> > > >
> > > > // Change the phase of the SPI clock for the digipot
> > > > U0TCTL_bit.CKPH = 1;
> > > > U0TCTL_bit.CKPL = 0;
> > > >
> > > > if (pot == 0)
> > > > data[0] = 0xB0;
> > > >
> > > > if (pot == 1)
> > > > data[0] = 0xB1;
> > > >
> > > > data[1] = position >> 8;
> > > > data[2] = position;
> > > >
> > > > digipot_cs = 0; // cs low
> > > > spi_write(3, (unsigned char*)data);
> > > > digipot_cs = 1; // cs high
> > > >
> > > > // Change the phase for the ADC
> > > > U0TCTL_bit.CKPH = 0;
> > > > U0TCTL_bit.CKPL = 0;
> > > >
> > > > }
> > >
>

------------------------------------

______________________________
Stellaris® MCU Family: New Parts, New Package, New Price.


(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: Re: SPI communcations appears to be losing a BIT - OneStone - Sep 2 5:38:24 2009

Perhaps if you left the sheep alone and concentrated on your work? ;@}

Glad you figured it out. We can never say it enough, RTFM

Al

ajellisuk wrote:
> Hi,
>
> After taking a few days out from this problem and re reading the documentation I have solved my problem.
>
> After re reading the MSP430F4xx manual I stumbled accross this section, and I quote:
>
> "18.2.1 USART Initialization and Reset
>
> The USART is reset by a PUC or by the SWRST bit. After a PUC, the SWRST
> bit is automatically set, keeping the USART in a reset condition. When set, the
> SWRST bit resets the URXIEx, UTXIEx, URXIFGx, OE, and FE bits and sets
> the UTXIFGx flag. The USPIEx bit is not altered by SWRST. Clearing SWRST
> releases the USART for operation. See also chapter 17.
>
> Note: Initializing or Reconfiguring the USART Module
> The required USART initialization/reconfiguration process is:
> 1) Set SWRST (BIS.B #SWRST,&UxCTL)
> 2) Initialize all USART registers with SWRST=1 (including UxCTL)
> 3) Enable USART module via the MEx SFRs (USPIEx)
> 4) Clear SWRST via software (BIC.B #SWRST,&UxCTL)
> 5) Enable interrupts (optional) via the IEx SFRs (URXIEx and/or UTXIEx)
> Failure to follow this process may result in unpredictable USART behavior."
>
> I was not carrying out the above steps when I was changing the clock polarity and phase, and therefore getting the unpredictable behaviour as the documentation warned me! I think I have learnt the hard way why one should read the documentation several times and carefully. I now feel a little sheepish.
>
> Michael I would like to thank you for your advice. I have taken it on board and I have been careful to ensure the timing is correct when communicating with peripherals.
>
> Kind regards
>
> Andrew
>
> --- In m...@yahoogroups.com, "tintronic" wrote:
>> As I suspected, your problem is right there on your spi_write() and is related to the #CS handling. You're disabling the slave right after writing the last byte to the SPI hardware buffer. Depending on the speed you set up for the SPI, you might be gettenig the byte before last throught, but no way you're getting the last byte throught.
>>
>> On another note, check the behaviour of U0TXIFG and TXEPT. Your SPI transfer will be faster of you use:
>> while (!(IFGx & U0TXIFG)); // IFG1 or IFG2 depending on the MSP model
>> // you're using
>> instead of
>> while (!(U0TCTL & TXEPT));
>> That means you only wait for the buffer to be empty, not the shift register to be empty. This way the next byte is transferred immediatel after the previous one, without wasting time for the buffer to be written and then transferred to the shift register.
>>
>> As I mentioned previously, check for TXEPT before exiting the function, and then check for SCLK bit status so disabling #CS. That way you have made sure SPI communication finished before disabling the slave.
>>
>> Regards,
>> Michael K.
>>
>> --- In m...@yahoogroups.com, "ajellisuk" wrote:
>>> Hi Michael
>>>
>>> Thank you for your reply.
>>>
>>> I'm a little confused with the digital pot I'm using. The data sheet clearly states that the device works with mode 0 or 3, but in reality it doesn't work with either! It only works with mode 1. I'll look into the timing issue tomorrow.
>>>
>>> I have posted the code for my SPI write function below.
>>>
>>> Kind regards
>>>
>>> Andrew
>>>
>>> void spi_write(char num_bytes, unsigned char *data)
>>> {
>>> do {
>>> TXBUF0 = *data++;
>>> while (!(U0TCTL & TXEPT));
>>> } while (--num_bytes);
>>> }
>>>
>>> --- In m...@yahoogroups.com, "tintronic" wrote:
>>>> Andrew,
>>>> You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.
>>>>
>>>> The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).
>>>>
>>>> In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.
>>>>
>>>> I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
>>>> Not that it matters much, but what compiler are you using?
>>>>
>>>> I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)
>>>>
>>>> Regards,
>>>> Michael K.
>>>>
>>>> --- In m...@yahoogroups.com, "ajellisuk" wrote:
>>>>> Hi,
>>>>>
>>>>> After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
>>>>>
>>>>> I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
>>>>>
>>>>> Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
>>>>>
>>>>> I have pasted the code for accessing the digital pot below.
>>>>>
>>>>> Kind regards
>>>>>
>>>>> Andrew
>>>>>
>>>>> // Sets the "pot" wiper position to "position"
>>>>> void set_digi_pot(char pot, int position)
>>>>> {
>>>>> char data[3] = {0};
>>>>>
>>>>> // Change the phase of the SPI clock for the digipot
>>>>> U0TCTL_bit.CKPH = 1;
>>>>> U0TCTL_bit.CKPL = 0;
>>>>>
>>>>> if (pot == 0)
>>>>> data[0] = 0xB0;
>>>>>
>>>>> if (pot == 1)
>>>>> data[0] = 0xB1;
>>>>>
>>>>> data[1] = position >> 8;
>>>>> data[2] = position;
>>>>>
>>>>> digipot_cs = 0; // cs low
>>>>> spi_write(3, (unsigned char*)data);
>>>>> digipot_cs = 1; // cs high
>>>>>
>>>>> // Change the phase for the ADC
>>>>> U0TCTL_bit.CKPH = 0;
>>>>> U0TCTL_bit.CKPL = 0;
>>>>>
>>>>> }
> ------------------------------------



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )

Re: SPI communcations appears to be losing a BIT - tintronic - Sep 3 20:22:20 2009

> Glad you figured it out. We can never say it enough, RTFM
But the thing is, we don't say it very often, do we? Instead we spend a lot of time trying to explain something that doesn't even make sense if you haven't RTFM. There are a lot of post we should reply with:
"RTFM. Then STFW and STFF. If still in doubt, come back with a specific question asked in a smart way. (Hint: google 'smart forum question')"

> > Note: Initializing or Reconfiguring the USART Module
> > The required USART initialization/reconfiguration process is:
> > 1) Set SWRST (BIS.B #SWRST,&UxCTL)
> > 2) Initialize all USART registers with SWRST=1 (including UxCTL)
> > 3) Enable USART module via the MEx SFRs (USPIEx)
> > 4) Clear SWRST via software (BIC.B #SWRST,&UxCTL)
> > 5) Enable interrupts (optional) via the IEx SFRs (URXIEx and/or
> > UTXIEx)
> >
> > Failure to follow this process may result in unpredictable USART
> > behavior."

This is one of those parts in the datasheet that is lazy written and unclear. What do they mean by:
" 2) Initialize all USART registers with SWRST=1 (including UxCTL)"
What are 'all USART registers' and why whould one think UxCTL wasn't part of all registers?
Then you go on to read 3) and 5) and go "Wait, MEx and IEx registers weren't part of 'all USART registers'?"
Never missed the PIC16 datasheets more than when I tryed to run the MSP430 USART for the first time.

> > When set, the SWRST bit resets the URXIEx, UTXIEx, URXIFGx, OE,
> > and FE bits and sets the UTXIFGx flag. The USPIEx bit is not
> > altered by SWRST.
Keep a close look on this, I now recall it caused me quite some headache when I builded a device that needed to automatically change the RS-232 baude rate on runtime.

> > Michael I would like to thank you for your advice. I have taken
> > it on board and I have been careful to ensure the timing is
> > correct when communicating with peripherals.
Glad to have been of help. The most common mistake is to search the User's Guide for certain information, instead of reading the entire chapter, or at the very least from the top untill reaching the needed information.

Honeslty, I couldn't make the SPI work the first time I used an MSP (I was used to the wonderful babystep-written datasheets of the PIC16 devices), finally I searched the web for a sample code to compare my code to.

The thing is I myself have to remember to RTFM more often. Just this week I've spent several hours to debug a recently build and programmed testing device because I didn't RTFM to make sure if this particular MSP model TimerA Capture module used the same signals as I remembered the model I used before used. Why aren't the damned TACCR1/TACCR2 captures working propperly? It turned out pin P2.3/TA1/A3/Vref- of MSP430F1232 can be used for both capture input and compare output, but P2.4/TA2A4Vref+ can only be used for compare mode output, NOT CAPTURE INPUT. Damned thing made me have to solder a cable on the otherwise beautiful circuit. Those 60 seconds I saved by not RTFM before etching the PCB cost me several hours. But as tempted as I was to ask away on the forum, I knew there was something I was overlooking and knew better than to ask without RTFM first. And then do a forum and google search. For me, asking the forum should always be a last resort.

Best Regards,
Michael

--- In m...@yahoogroups.com, OneStone wrote:
>
> Perhaps if you left the sheep alone and concentrated on your work? ;@}
>
> Glad you figured it out. We can never say it enough, RTFM
>
> Al
>
> ajellisuk wrote:
> > Hi,
> >
> > After taking a few days out from this problem and re reading the documentation I have solved my problem.
> >
> > After re reading the MSP430F4xx manual I stumbled accross this section, and I quote:
> >
> > "18.2.1 USART Initialization and Reset
> >
> > The USART is reset by a PUC or by the SWRST bit. After a PUC, the SWRST
> > bit is automatically set, keeping the USART in a reset condition. When set, the
> > SWRST bit resets the URXIEx, UTXIEx, URXIFGx, OE, and FE bits and sets
> > the UTXIFGx flag. The USPIEx bit is not altered by SWRST. Clearing SWRST
> > releases the USART for operation. See also chapter 17.
> >
> > Note: Initializing or Reconfiguring the USART Module
> > The required USART initialization/reconfiguration process is:
> > 1) Set SWRST (BIS.B #SWRST,&UxCTL)
> > 2) Initialize all USART registers with SWRST=1 (including UxCTL)
> > 3) Enable USART module via the MEx SFRs (USPIEx)
> > 4) Clear SWRST via software (BIC.B #SWRST,&UxCTL)
> > 5) Enable interrupts (optional) via the IEx SFRs (URXIEx and/or UTXIEx)
> > Failure to follow this process may result in unpredictable USART behavior."
> >
> > I was not carrying out the above steps when I was changing the clock polarity and phase, and therefore getting the unpredictable behaviour as the documentation warned me! I think I have learnt the hard way why one should read the documentation several times and carefully. I now feel a little sheepish.
> >
> > Michael I would like to thank you for your advice. I have taken it on board and I have been careful to ensure the timing is correct when communicating with peripherals.
> >
> > Kind regards
> >
> > Andrew
> >
> > --- In m...@yahoogroups.com, "tintronic" wrote:
> >> As I suspected, your problem is right there on your spi_write() and is related to the #CS handling. You're disabling the slave right after writing the last byte to the SPI hardware buffer. Depending on the speed you set up for the SPI, you might be gettenig the byte before last throught, but no way you're getting the last byte throught.
> >>
> >> On another note, check the behaviour of U0TXIFG and TXEPT. Your SPI transfer will be faster of you use:
> >> while (!(IFGx & U0TXIFG)); // IFG1 or IFG2 depending on the MSP model
> >> // you're using
> >> instead of
> >> while (!(U0TCTL & TXEPT));
> >> That means you only wait for the buffer to be empty, not the shift register to be empty. This way the next byte is transferred immediatel after the previous one, without wasting time for the buffer to be written and then transferred to the shift register.
> >>
> >> As I mentioned previously, check for TXEPT before exiting the function, and then check for SCLK bit status so disabling #CS. That way you have made sure SPI communication finished before disabling the slave.
> >>
> >> Regards,
> >> Michael K.
> >>
> >> --- In m...@yahoogroups.com, "ajellisuk" wrote:
> >>> Hi Michael
> >>>
> >>> Thank you for your reply.
> >>>
> >>> I'm a little confused with the digital pot I'm using. The data sheet clearly states that the device works with mode 0 or 3, but in reality it doesn't work with either! It only works with mode 1. I'll look into the timing issue tomorrow.
> >>>
> >>> I have posted the code for my SPI write function below.
> >>>
> >>> Kind regards
> >>>
> >>> Andrew
> >>>
> >>> void spi_write(char num_bytes, unsigned char *data)
> >>> {
> >>> do {
> >>> TXBUF0 = *data++;
> >>> while (!(U0TCTL & TXEPT));
> >>> } while (--num_bytes);
> >>> }
> >>>
> >>> --- In m...@yahoogroups.com, "tintronic" wrote:
> >>>> Andrew,
> >>>> You didn't post the code for your spi_write() routine. I suspect the problem is there. Obviously I can't tell you what's wrong without looking at it, but I can venture a guess based on the problably most recurrent mistake people make when using the USART's SPI: Deselecting the #CS bit.
> >>>>
> >>>> The problem is that, as far as I can tell (and no one in this forum has ever said the contrary), TXEPT sets on the same edge on which the last bit is shifted out, which is before the following edge which the slave uses to shift the data in. This means if you disable the #CS right after TXEPT sets, the slave sees the disabled #CS before the last bit is shifted in. What happens on the slave depends on its design, but it will most likely either ignore the last byte or discard the whole command (all the bytes received since last #CS enable).
> >>>>
> >>>> In your case, it would all depend on when your spi_write() routine returns. The best solution is to check that the SPI clock pin(thought the corresponding PxIN & BITy) is in its idle state after TXEPT is set, prior to deselecting the #CS. Depending on the SPI configuration difference between both devices, SPI clock signal might have opposite idle values.
> >>>>
> >>>> I'm curious: what are the 2 devices SPI configurations? As I can remember, all SPI devices I've worked with can work in SPI mode 1 AND 3, or only mode 3. I've never needed to change the SPI mode when using more than one device, but then again I've never used digital potentiometers nor digital temperature sensors.
> >>>> Not that it matters much, but what compiler are you using?
> >>>>
> >>>> I'm supposing you already made sure you're no violating any timing parameter of the slave (For example #CS select to first clock edge and last clock edge to deselecting #CS, which might require some extra NOPs after the last clock edge)
> >>>>
> >>>> Regards,
> >>>> Michael K.
> >>>>
> >>>> --- In m...@yahoogroups.com, "ajellisuk" wrote:
> >>>>> Hi,
> >>>>>
> >>>>> After spending a while reading through the MSP430 manual's chapter about SPI I have revisited my project. I was using the wrong polarity and phase.
> >>>>>
> >>>>> I have now stumbled accross another problem. I have a digital pot (AD5235) on the same SPI bus as the ADC. The digital pot requires a different phase to the ADC. If I change the phase temporally for the digital pot, the device works correctly each and every time I use it. However it messes up the ADC for some reason. I have checked the relevent chip select lines and I'm confident that the ADC is disabled whilst I'm communicating with the digital pot, and I'm certain that clock polarity is set correctly for each device.
> >>>>>
> >>>>> Are there any known issues with changing the SPI buses clock polarity and phase on the fly which I may have missed? Does anyone have any ideas as to what could be going wrong please?
> >>>>>
> >>>>> I have pasted the code for accessing the digital pot below.
> >>>>>
> >>>>> Kind regards
> >>>>>
> >>>>> Andrew
> >>>>>
> >>>>> // Sets the "pot" wiper position to "position"
> >>>>> void set_digi_pot(char pot, int position)
> >>>>> {
> >>>>> char data[3] = {0};
> >>>>>
> >>>>> // Change the phase of the SPI clock for the digipot
> >>>>> U0TCTL_bit.CKPH = 1;
> >>>>> U0TCTL_bit.CKPL = 0;
> >>>>>
> >>>>> if (pot == 0)
> >>>>> data[0] = 0xB0;
> >>>>>
> >>>>> if (pot == 1)
> >>>>> data[0] = 0xB1;
> >>>>>
> >>>>> data[1] = position >> 8;
> >>>>> data[2] = position;
> >>>>>
> >>>>> digipot_cs = 0; // cs low
> >>>>> spi_write(3, (unsigned char*)data);
> >>>>> digipot_cs = 1; // cs high
> >>>>>
> >>>>> // Change the phase for the ADC
> >>>>> U0TCTL_bit.CKPH = 0;
> >>>>> U0TCTL_bit.CKPL = 0;
> >>>>>
> >>>>> }
> >
> >
> >
> >
> > ------------------------------------
> >
> >
> >
> >



(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )