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.