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 )