Below is a part of the code I wrote to interface ADS1256 with MSP430F5438A. I am using msp430 at frequency of 16 MHz. the interfacing is done using spi interface. and I am using
smclk/4 for spi Sclk. I am not able to read back the registers of ads, when initializing the adc in the adc_spi_init routine. The Smclk after boosting up to 16 MHz not of a good
shape. but I need to use this high freq for MCLK for carrying out some filtering on the incoming data. So I do not want a lesser frequency for SPI comm. Can anyone suggest
help me out with this. as SPI interface is not working.
int i=0;int ADC_init_flag=0;int first_data=0;char test;void MCU_USB_init();void ADC_spi_init();void main(void){ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer// P1.0 LED for signalling P1DIR |= 0x03; // Set P1.0 to output direction // P!.4 enabled to recieve interrupt from DRDY of ads1256 P1OUT|=0X10; P1REN |= 0x10; // Enable P1.4 internal resistance// setting up clock to operate at 16 MHz P1IE |= 0x10; // P1.4 interrupt enabled P1IES |= 0x10; // P1.4 Hi/Lo edge P1IFG &= ~0x10; // P1.4 IFG cleared P1SEL |=0x40; //ACLK = ~32.768kHz, MCLK = SMCLK = DCO ~ 16MHz. BRCLK = SMCLK/2 P11DIR |= 0x07; // ACLK, MCLK, SMCLK set out to pins P11SEL |= 0x07; // P11.0,1,2 for debugging purposes.UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFOUCSCTL4 |= SELA_2; // Set ACLK = REFO __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_5; // Select DCO range 24MHz operation UCSCTL2 = FLLD_1 + 488; // Set DCO Multiplier for 12MHz // (N + 1) * FLLRef = Fdco // (366 + 1) * 32768 = 12MHz // Set FLL Div = fDCOCLK/2 UCSCTL5 |= DIVA_1; // ACLK=16/2= 8MHz __bic_SR_register(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle __delay_cycles(500000); // Loop until XT1,XT2 & DCO fault flag is cleared do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag ADC_spi_init(); // USB/UART interface with hyperterminal MCU_USB_init(); __bis_SR_register(GIE); // Enter w/interrupt while(1);}// MSP430_UART interface initvoid MCU_USB_init(){// WDTCTL = WDTPW + WDTHOLD; // Stop WDT P10SEL = 0x30; // P10.4,5 = USCI_A3 TXD/RXD UCA3CTL1 |= UCSWRST; // **Put state machine in reset** UCA3CTL1 |= UCSSEL_1; // CLK = ACLK UCA3BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide) UCA3BR1 = 0x00; // UCA3MCTL = UCBRS_3+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0 UCA3CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA3IE |= UCRXIE; // Enable USCI_A0 RX interrupt __delay_cycles(100); // Wait for slave to initialize}// ADC_MSP430 SPI interface initializationvoid ADC_spi_init(){ // SPI interface between ADC and MSP using port A0 (port 3) //ACLK =8 MHz MCLK = SMCLK = DCO ~ 16MHz. BRCLK = SMCLK/4=4Mhz P10DIR|=0x03; // for reset and chip select P10OUT|=0x03; __delay_cycles(100); // reset pulse of atleast 4 cycles P10OUT =0x00; __delay_cycles(100); // reset pulse of atleast 4 cyclesP10OUT|=0x02; __delay_cycles(100); // reset pulse of atleast 4 cycles P3SEL |= 0x31; // P3.5,4,0 option select UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCMST+UCSYNC+UCMSB+UCCKPL; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 0x04; // /4 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt// setting parameters of ADC i=100;// while (i>0) // {//P1OUT^= BIT1;//i--; // } __delay_cycles(100); // reset pulse of atleast 4 cyclesADC_init_flag=1; UCA0TXBUF=0x50; //WREG to ADC while(!(UCA0IFG&UCRXIFG)); // Wait for transmission UCA0TXBUF=0x04; //5 Registers to be written(4+1) __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x01; // Status reg MSB first __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x01; // MUX AIN0 Pos and AIN1 Neg i/p __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x00; //ADCON all default __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0xB0; //Drate 2KHz __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x00; //GPIO all default __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0xF0; //GPIO all default __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x10; // read reg status __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); UCA0TXBUF=0x00; // read 1 reg __delay_cycles(50000); while(!(UCA0IFG&UCRXIFG)); test=UCA0RXBUF; __delay_cycles(50000); // Wait for slave to initialize // Minimum 2ms.}
Hi Kedar,
Welcome back! How did you make out with the ADS1224? Part of the problem you are having with this current ADS1256 setup may be related to the SPI settings you are using with the MSP430F5438. You are setting the UCCKPL bit which will make the SCLK dwell high. You are also leaving the UCCKPH bit cleared, which means data is strobed on the rising SCLK edge. If you look at Figure 1 in the ADS1256 data sheet, you'll notice that the clock polarity and phase requirement is opposite from your current MSP430 setup. Try removing the '+ UCCKPL" in your SPI setup and let us know if you get better results.
UCA0CTL0 |= UCMST+UCSYNC+UCMSB; // remove this to keep the SCLK dwelling low +UCCKPL;
Regards,
Tom
Hi Tom,
Thank you for you reply. The replacement for ads1224 worked very well, thanks for that as well. I am now working on ADS1256. I made the changes as you said. Following is the routine with some changes, but I am still not able to read any registers. I checked the SCLK and SIMO wave forms on oscilloscope and also on watch window, and it is right from MSP430 side but the SOMI is still all zeros with some noise. Can you suggest something? Do you think I can check some testpoints on ads1256EVM?
void ADC_spi_init(){ // SPI interface between ADC and MSP using port A0 (port 3) //ACLK =8 MHz MCLK = SMCLK = DCO ~ 16MHz. BRCLK = SMCLK/4=4Mhz P10DIR=0x02; // for reset and chip select P10OUT|=0x02; __delay_cycles(100); // reset pulse of atleast 4 cycles P10OUT =0x00; __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cyclesP10OUT|=0x02; __delay_cycles(100); // reset pulse of atleast 4 cycles P3SEL |= 0x31; // P3.5,4,0 option select UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCMST+UCSYNC+UCMSB+UCCKPH; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 |= UCSSEL_1; // ACLK UCA0BR0 = 0x01; // 1 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE+UCTXIE; // Enable USCI_A0 RX interrupt// setting parameters of ADC i=100;// while (i>0) // {//P1OUT^= BIT1;//i--; // } __delay_cycles(100); // reset pulse of atleast 4 cyclesADC_init_flag=1;while(1){//status UCA0TXBUF=0x50; //WREG to ADC while(!(UCA0IFG&UCTXIFG)); // Wait for transmission UCA0TXBUF=0x00; //5 Registers to be written(4+1) __delay_cycles(50000); while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF=0x01; // Status reg MSB first __delay_cycles(50000); UCA0TXBUF=0x10; // read reg status __delay_cycles(50000); while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG)); __delay_cycles(200); // 50 Tclkin for adc cycles delay UCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG)); __delay_cycles(200); // 50 Tclkin for adc cycles delay //test2=UCA0RXBUF; test1=UCA0RXBUF; // MUX UCA0TXBUF=0x53; //WREG to ADC while(!(UCA0IFG&UCTXIFG)); // Wait for transmission UCA0TXBUF=0x00; //5 Registers to be written(4+1) __delay_cycles(50000); while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF=0xB0; // MUX AIN0 Pos and AIN1 Neg i/p __delay_cycles(50000); while(!(UCA0IFG&UCTXIFG));UCA0TXBUF=0x13; // read reg status __delay_cycles(50000); while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG)); __delay_cycles(200); // 50 Tclkin for adc cycles delay UCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG));// __delay_cycles(200); // 50 Tclkin for adc cycles delay test2=UCA0RXBUF; }}
Can you send some screen shots along? I suspect you have things wired between the two EVAL boards again, have you double checked you connections?
Hi, followings is the scope shot with sclk and simo, where you can see green sclk and yellow simo. Here I am having some issues, as you can see the delay between the two sclks for different data bytes is 200us, while in code, I am giving delay of 5000 cycle with mclk 16MHz, so it should have been close to 300us. also the scope plot below this is with somi. where you can see th noise. I verified the connections, and attached the copy of my connection diagram0334.3659_001.pdf and my code snippet
void ADC_spi_init(){ // SPI interface between ADC and MSP using port A0 (port 3) //ACLK =8 MHz MCLK = SMCLK = DCO ~ 16MHz. BRCLK = SMCLK/4=4Mhz P10DIR=0x02; // for reset and chip select P10OUT|=0x02; __delay_cycles(100); // reset pulse of atleast 4 cycles P10OUT =0x00; __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cycles __delay_cycles(10000); // reset pulse of atleast 4 cyclesP10OUT|=0x02; __delay_cycles(100); // reset pulse of atleast 4 cycles P3SEL |= 0x31; // P3.5,4,0 option select UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0=0x00; UCA0CTL0 |= UCMST+UCSYNC+UCMSB+UCCKPH; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 |= UCSSEL_1; // ACLK UCA0BR0 = 0x01; // 1 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE+UCTXIE; // Enable USCI_A0 RX interrupt// setting parameters of ADC i=100;// while (i>0) // {//P1OUT^= BIT1;//i--; // } __delay_cycles(100); // reset pulse of atleast 4 cyclesADC_init_flag=1;while(1){//status UCA0TXBUF=0x50; //WREG to ADC while(!(UCA0IFG&UCTXIFG)); // Wait for transmission __delay_cycles(5000); UCA0TXBUF=0x00; //5 Registers to be written(4+1)while(!(UCA0IFG&UCTXIFG));__delay_cycles(5000);UCA0TXBUF=0x01; // Status reg MSB firstwhile(!(UCA0IFG&UCTXIFG));__delay_cycles(5000); UCA0TXBUF=0x10; // read reg statuswhile(!(UCA0IFG&UCTXIFG)); __delay_cycles(5000); UCA0TXBUF=0x00; // read 1 regwhile(!(UCA0IFG&UCTXIFG));__delay_cycles(5000); // 50 Tclkin for adc cycles delayUCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG));__delay_cycles(50000); // 50 Tclkin for adc cycles delay //test2=UCA0RXBUF; test1=UCA0RXBUF; // MUXUCA0TXBUF=0x53; //WREG to ADC while(!(UCA0IFG&UCTXIFG)); // Wait for transmission __delay_cycles(5000);UCA0TXBUF=0x00; //5 Registers to be written(4+1) while(!(UCA0IFG&UCTXIFG)); __delay_cycles(5000); UCA0TXBUF=0xB0; // MUX AIN0 Pos and AIN1 Neg i/pwhile(!(UCA0IFG&UCTXIFG)); __delay_cycles(5000); UCA0TXBUF=0x13; // read reg statuswhile(!(UCA0IFG&UCTXIFG));__delay_cycles(5000); UCA0TXBUF=0x00; // read 1 regwhile(!(UCA0IFG&UCTXIFG));__delay_cycles(5000); // 50 Tclkin for adc cycles delayUCA0TXBUF=0x00; // read 1 reg while(!(UCA0IFG&UCTXIFG));__delay_cycles(50000); // 50 Tclkin for adc cycles delay test2=UCA0RXBUF; }}
Now the clock phasing is off. The MSP430 is a little different in the way it defines CKPH from other processors. It looks like you changed UCCKPL to UCCKPH, so now the data is valid on the rising SCLK edge by your screen shot - it need to be valid on the falling.
Change this: UCA0CTL0 |= UCMST+UCSYNC+UCMSB+UCCKPH;
To this: UCA0CTL0 |= UCMST+UCSYNC+UCMSB; and let us know if that clears up the issues you are having.
I am sorry, I sent you the wrong code. UCCKPH is off
that line is :
UCA0CTL0 |= UCMST+UCSYNC+UCMSB;
I edited the code, and now the waveforms are correct by clock edge, where I am sending the data on rising edge, but still there is no data on somi.
also I wanted to know about the clock. Right now I am using SCLK at 32,768Hz and I want to increase it, but before that, The MCLK and SMCLK generated by the system are very poor at 16 MHz, the shape is far worse than a sqaure wave, is there any way to improve that?
I solved the problem, The problem was with some connections and after I modified them, I got it working. While running the code I observed some weird behavior with ADS1256. Reading the values from the DRATE register in a while(1) loop for debugging gave some erratic values. Even though a single value was written to it. and on reset the default value of status register I get is 0x30 rather that 0xX1, what can be the reason?