Other Parts Discussed in Thread: MSP430FR5989, ADS1258
Tool/software:
Hello all,
I am using ads1258-ep adc converter with msp430fr5989. My problem is that after reset I cannot reading any conversion data from ads1258. I have noticed that I couldn't read the registers that I tried the configurate before the conversion part. I have used the official ads1258 driver from website with little updates. Here is my code below.
static uint8_t WrittenregisterMap[NUM_REGISTERS]; static uint8_t ReadregisterMap[NUM_REGISTERS]; uint8_t getRegisterValue(uint8_t address){ return ReadregisterMap[address]; } uint8_t SendReceiveByte(uint8_t dataTx){ uint8_t dataRx; uint16_t timeout = TIMEOUT; while(!(UCB1IFG & UCTXIFG)){ if (--timeout == 0){ return SPI_TIMEOUT_ERR ; } } UCB1TXBUF = dataTx; __delay_cycles(10); while(!(UCB1IFG & UCRXIFG)){ if (--timeout == 0){ return SPI_TIMEOUT_ERR ; } } dataRx = UCB1RXBUF; return dataRx; } uint8_t SendReceiveArrays(uint8_t *dataTx, uint8_t *dataRx, uint16_t byteLength ){ uint16_t i; uint16_t timeout = TIMEOUT; setADS_CS(LOW); __delay_cycles(10); for (i=0; i<byteLength; i++){ while(!(UCB1IFG & UCTXIFG)){ if (--timeout == 0){ return SPI_TIMEOUT_ERR ; } } UCB1TXBUF = dataTx[i]; __delay_cycles(10); while(!(UCB1IFG & UCRXIFG)){ if (--timeout == 0){ return SPI_TIMEOUT_ERR ; } } dataRx[i] = UCB1RXBUF; } // return SPI_TIMEOUT_NOERR; setADS_CS(HIGH); } void readMultipleRegisters(uint8_t startAddress, uint8_t count){ uint8_t i; setADS_CS(LOW); __delay_cycles(20); uint8_t dataTx = OPCODE_RREG | OPCODE_MUL_MASK | (startAddress & OPCODE_A_MASK); SendReceiveByte(dataTx); for (i = startAddress; i < startAddress + count; i++) { __delay_cycles(20); // read register data bytes ReadregisterMap[i] = SendReceiveByte(0x00); } __delay_cycles(20); setADS_CS(HIGH); __delay_cycles(20); } void writeMultipleRegisters(uint8_t startAddress, uint8_t count, const uint8_t regData[]) { uint8_t i; setADS_CS(LOW); __delay_cycles(20); uint8_t dataTx = OPCODE_WREG | OPCODE_MUL_MASK | (startAddress & OPCODE_A_MASK); SendReceiveByte(dataTx); for (i = startAddress; i < startAddress + count; i++) { __delay_cycles(20); // write register data bytes SendReceiveByte(regData[i]); } __delay_cycles(20); setADS_CS(HIGH); __delay_cycles(20); } int32_t ADS_ReadData(uint8_t status[], readMode mode) { uint8_t DataTx[5] = { 0 }; uint8_t DataRx[5] = { 0 }; uint8_t byteLength; uint8_t dataPosition; bool status_byte_enabled; /* Build TX array and send it */ if (mode == DIRECT) { DataTx[0] = OPCODE_READ_DIRECT; /* STATUS byte enable depends on MUXMOD and STAT (see table 17 in datasheet) */ status_byte_enabled = IS_STAT_SET & !IS_MUXMOD_SET; byteLength = (status_byte_enabled ? 4 : 3); dataPosition = (status_byte_enabled ? 1 : 0); } else if (mode == COMMAND) { DataTx[0] = OPCODE_READ_COMMAND | OPCODE_MUL_MASK; /* STATUS byte always enabled, but undefined in fixed-channel mode (see table 17 in datasheet) */ status_byte_enabled = true; byteLength = 5; dataPosition = 2; } SendReceiveArrays(DataTx, DataRx, byteLength); // // Parse returned SPI data // /* Check if STATUS byte is enabled and if we have a valid "status" memory pointer */ if (status_byte_enabled && status) { status[0] = DataRx[dataPosition - 1]; } /* Return the 32-bit sign-extended conversion result */ int32_t signByte; if (DataRx[dataPosition] & 0x80u) { signByte = 0xFF000000; } else { signByte = 0x00000000; } int32_t upperByte = ((int32_t) DataRx[dataPosition + 0] & 0xFF) << 16; int32_t middleByte = ((int32_t) DataRx[dataPosition + 1] & 0xFF) << 8; int32_t lowerByte = ((int32_t) DataRx[dataPosition + 2] & 0xFF) << 0; return (signByte | upperByte | middleByte | lowerByte); } bool ADS_RegisterConfig(){ bool b_pass = true; int i =0; // Test configuration WrittenregisterMap[REG_ADDR_CONFIG0] = CONFIG0_DEFAULT & ~CONFIG0_MUXMOD_MASK; // Auto-scan mode WrittenregisterMap[REG_ADDR_CONFIG1] = CONFGI1_DOSI; // Slowest data rate WrittenregisterMap[REG_ADDR_MUXSCH] = MUXSCH_DEFAULT; WrittenregisterMap[REG_ADDR_MUXDIF] = MUXDIF_DEFAULT; // Differential channels off WrittenregisterMap[REG_ADDR_MUXSG0] = MUXSG0_DOSI; //0x3E WrittenregisterMap[REG_ADDR_MUXSG1] = MUXSG1_DOSI; // 0x2B WrittenregisterMap[REG_ADDR_SYSRED] = SYSRED_DEFAULT; WrittenregisterMap[REG_ADDR_GPIOC] = GPIOC_DOSI; WrittenregisterMap[REG_ADDR_GPIOD] = GPIOD_DOSI; WrittenregisterMap[REG_ADDR_ID] = 0x00; // Write registers writeMultipleRegisters(REG_ADDR_CONFIG0, NUM_REGISTERS-1, WrittenregisterMap); __delay_cycles(1000); //Read registers readMultipleRegisters(REG_ADDR_CONFIG0, NUM_REGISTERS-1); for (i =0 ;i< NUM_REGISTERS-1 ; i++ ){ b_pass &= (getRegisterValue(i)== WrittenregisterMap[i]); } // return (b_pass ? ADS_REG_CONFIG_NOERR : ADS_REG_CONFGI_ERR); return 1; } bool ConfigAds(){ bool reg_conf_ok = false; delay_ms(50); toggleADS_RESET(); /*Configure ADS Registers */ reg_conf_ok = ADS_RegisterConfig(); startADS_Conversions(); delay_ms(100); return reg_conf_ok; } void InitAdsInterrupt(){ P2IES |= TR_ADC_DRDY; // Data ready low clock edge interr P2IFG &= ~ TR_ADC_DRDY; // Clear interr flag // P2IE |= TR_ADC_DRDY; // Activate interr delay_ms(100); } void InitAdsSpi(){ UCB1CTLW0 |= UCSWRST; // put SPI in reset state UCB1CTLW0 |= UCSYNC | UCCKPH | UCMSB | UCMST | UCSSEL__SMCLK; // 8 bit SPI Master , MSB first , Clock polarity high ,SMCLK UCB1BRW = 2; // set clock divider to achieve 1MHz clock with SMCLK at 1 Mhz UCB1CTLW0 &= ~ UCSWRST; // Release SPI for operation UCB1IE |= UCRXIE; // Enable USCI_B1 interrupt delay_ms(100); } void setADS_PWDN(bool state) { /* --- TODO: INSERT YOUR CODE HERE --- */ if (state == HIGH) P5OUT |= TR_ADC_PWDN ; else P5OUT &= ~TR_ADC_PWDN; __delay_cycles(2); } void SetAdsOE(bool state){ if (state == HIGH) P2OUT |= TR_ADC_OE ; else P2OUT &= ~TR_ADC_OE; delay_ms(1000); } void setADS_CS(bool state){ if (state == HIGH) P5OUT |= TR_ADC_CS ; else P5OUT &= ~TR_ADC_CS; __delay_cycles(2); } void startADS_Conversions(){ /* Ensure device is not in PWDN mode */ /* Begin continuous conversions */ setADS_START(HIGH); } void setADS_START(bool state){ if (state == HIGH) P5OUT |= TR_ADC_START ; else P5OUT &= ~TR_ADC_START; __delay_cycles(2); } void toggleADS_RESET(){ P5OUT &= ~TR_ADC_RST; __delay_cycles(10); //Min 2 tCLK P5OUT |= TR_ADC_RST; __delay_cycles(10); } void setADS_RESET(bool state){ if (state == HIGH) P5OUT |= TR_ADC_RST ; else P5OUT &= ~TR_ADC_RST; __delay_cycles(2); } void process_ads_data(S_ADS_DATA *ads_data , S_ADS_STATUS_DATA *ads_status_data, int32_t dataValues, uint8_t statusBytes){ switch (statusBytes & STATUS_CHID_MASK){ case STATUS_CHID_AIN1 : ads_data->Ads_Vsens_11V = dataValues; ads_status_data->Ads_Stat_Vsens_11V = statusBytes; break; case STATUS_CHID_AIN2 : ads_data->Ads_Curr_Sens2 = dataValues; ads_status_data->Ads_Stat_Curr_Sens2 = statusBytes; break; case STATUS_CHID_AIN3 : ads_data->Ads_Vt01_Out2 = dataValues; ads_status_data->Ads_Stat_Vt01_Out2 = statusBytes; break; case STATUS_CHID_AIN4 : ads_data->Ads_Curr_Sens1 = dataValues; ads_status_data->Ads_Stat_Curr_Sens1 = statusBytes; break; case STATUS_CHID_AIN5 : ads_data->Ads_Vt01_Out1 = dataValues; ads_status_data->Ads_Stat_Vt01_Out1 = statusBytes; break; case STATUS_CHID_AIN8 : ads_data->Ads_Temp1_Pwr = dataValues; ads_status_data->Ads_Stat_Temp1_Pwr = statusBytes; break; case STATUS_CHID_AIN9 : ads_data->Ads_Temp_Sens = dataValues; ads_status_data->Ads_Stat_Temp_Sens = statusBytes; break; case STATUS_CHID_AIN11 : ads_data->Ads_20V = dataValues; ads_status_data->Ads_Stat_20V = statusBytes; break; case STATUS_CHID_AIN13 : ads_data->Ads_11V = dataValues; ads_status_data->Ads_Stat_11V = statusBytes; break; case STATUS_CHID_OFFSET : ads_data->Ads_Offset = dataValues; ads_status_data->Ads_Stat_Offset = statusBytes; break; case STATUS_CHID_GAIN : ads_data->Ads_Gain = dataValues; ads_status_data->Ads_Stat_Gain = statusBytes; break; case STATUS_CHID_TEMP : ads_data->Ads_Temp = dataValues; ads_status_data->Ads_Stat_Temp = statusBytes; break; default: break; } } bool waitforDataReady(uint32_t timeout_ms){ uint32_t timeout = timeout_ms * 1000; do{ timeout--; }while( (!(P2IFG & TR_ADC_DRDY)) && (timeout>0)); P2IFG &= ~TR_ADC_DRDY; return (timeout>0); }
void SetMcuClock(){ Config_Osc_Pins(); // Osc pinlerini ayarla FRCTL0 = FRCTLPW | NWAITS1; CSCTL0_H = CSKEY_H; // Unlock CS registers //CSCTL1 = DCOFSEL_0 | DCORSEL; // Set DCO to 1 Mhz CSCTL1 = DCOFSEL_0 ; // Set DCO to 1 Mhz CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK; //ACLK'nın kaynağı OSC CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; CSCTL4 &= ~LFXTOFF; // CSCTL4 &= ~LFXTBYPASS; // LFXT1, OSC 'in stabilize olmasi icin bekle do { CSCTL5 &= ~LFXTOFFG; SFRIFG1 &= ~OFIFG; }while (SFRIFG1 & OFIFG); CSCTL0_H = 0; } void Config_ADS1258_Pins(){ P3SEL0 |= TR_ADC_SCLK | TR_ADC_DIN | TR_ADC_DOUT ; P3SEL1 &= ~(TR_ADC_SCLK | TR_ADC_DIN | TR_ADC_DOUT) ; // P3DIR |= TR_ADC_SCLK | TR_ADC_DIN ; // set P3.0 P3.1 as output //P3DIR &= ~(TR_ADC_DOUT ); // set P3.2 as input P5OUT &= ~( TR_ADC_START ); P5OUT |= TR_ADC_CS | TR_ADC_PWDN ; // set P5.3 output high P5DIR |= TR_ADC_OSC | TR_ADC_START | TR_ADC_PWDN | TR_ADC_CS ; // set P5.0 P5.1 P5.2 P5.3 as output; //P5SEL0 &= ~(TR_ADC_CS); P5SEL0 |= TR_ADC_OSC; P5SEL1 |= TR_ADC_OSC ; // P5SEL1 |= TR_ADC_OSC | TR_ADC_CS; P2OUT |= TR_ADC_OE ; // set P2.5 as output high P2DIR |= TR_ADC_OE | TR_ADC_RST; // set P2.5 P2.7 as output P2DIR &= ~( TR_ADC_DRDY); // set P2.6 as input }
int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT PM5CTL0 &= ~LOCKLPM5; // Disable GPIo power on high power impedance SetMcuClock(); SetMcuPins(); EnablePowers(); InitAdsSpi(); InitAdsInterrupt(); ConfigAds(); __bis_SR_register(GIE); //Enter LMP0 enable interrupts while (1) { __bis_SR_register(GIE); } }
Any help will be appreciated.
Regards.