//****************************************************************************** // // Description: SPI master (MSP430F5529) communicates to 3 ADS1118 slaves // // MSP430F5529 // ----------------- // | (See below)|-> Slave Chip Select (GPIO) // | | // | | // | | // | P3.3|-> Data Out (UCA0SIMO/DIN) // | | // | P3.4|<- Data In (UCA0SOMI/DOUT) // | | // | P2.7|-> Serial Clock Out (UCA0CLK) // | | // | | // //CSB_ADC1 = P1.2; CSB_ADC2 = P1.3 ; CSB_ADC3 = P1.4 // // //****************************************************************************** #include #include #include #define DUMMY 0x00 #define CSB_M1_OUT P1OUT #define CSB_M1_DIR P1DIR #define CSB_M1_PIN BIT2 #define CSB_M2_OUT P1OUT #define CSB_M2_DIR P1DIR #define CSB_M2_PIN BIT3 #define CSB_M3_OUT P1OUT #define CSB_M3_DIR P1DIR #define CSB_M3_PIN BIT4 #define LENGTH_ONE 1 #define LENGTH_TWO 2 #define LENGTH_SIX 6 #define MAX_BUFFER_SIZE 20 #define ADS1118_REG_ADDR_CONFIG_REG_MSB_def 0x8F //1000_1110 //8: MODE = 0 for continuous conversion mode; 1 = power down mode //11:9: VREF = 111 for FSR = +/-0.256V //14:12: MUX = 000 for AIN0 = (+ve) and AIN1 = (-ve) //15: Single shot conversion start = 0 for no effect; 1 = start single conversion typedef enum SPI_ModeEnum{ IDLE_MODE, TX_REG_ADDRESS_MODE, RX_REG_ADDRESS_MODE, TX_DATA_MODE, RX_DATA_MODE, WRITE_READ_MODE, TIMEOUT_MODE } SPI_Mode; uint8_t ADS1118_REG_ADDR_CONFIG_REG_LSB[LENGTH_ONE] = {0xEB}; //1110_1010 //0: Reserved //2:1: NOOP = 01 (Valid data) //3: PULL-UP EN = When /CSB is high, this pulls up the DOUT pin //4: TS_MODE = 0 (ADC) or 1 (Temp Sensor) //7:5: DR = 111 (860 SPS) uint8_t CopyDestBuffer[LENGTH_SIX] = {0}; SPI_Mode MasterMode = IDLE_MODE; uint8_t TransmitRegAddr = 0; uint8_t TransmitDataMSB = 0; uint8_t TransmitDataLSB = 0; uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0; uint8_t sensor_number = 0; uint8_t num_accels = 5; int sensorno; int mymode = 0; uint8_t mydata = 0; void SendUCA0Data(uint8_t val); //****************************************************************************** // CopyArray******************************************************************** //****************************************************************************** void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) { uint8_t copyIndex = 0; for (copyIndex = 0; copyIndex < count; copyIndex++) { dest[copyIndex] = source[copyIndex]; } } //****************************************************************************** // Master write to slave******************************************************* //****************************************************************************** SPI_Mode SPI_Master_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count, int senNum, int mode); SPI_Mode SPI_Master_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count, int senNum, int mode) { sensor_number = senNum; MasterMode = TX_REG_ADDRESS_MODE; TransmitRegAddr = reg_addr; //Copy register data to TransmitBuffer CopyArray(reg_data, TransmitBuffer, count); TXByteCtr = count; RXByteCtr = 0; ReceiveIndex = 0; TransmitIndex = 0; mymode = mode; if (sensor_number == 6){ CSB_M1_OUT &= ~(CSB_M1_PIN); } else if (sensor_number == 7){ CSB_M2_OUT &= ~(CSB_M2_PIN); } else if (sensor_number == 8){ CSB_M3_OUT &= ~(CSB_M3_PIN); } SendUCA0Data(TransmitRegAddr); __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts if (sensor_number == 6){ CSB_M1_OUT |= CSB_M1_PIN; } else if (sensor_number == 7){ CSB_M2_OUT |= CSB_M2_PIN; } else if (sensor_number == 8){ CSB_M3_OUT |= CSB_M3_PIN; } return MasterMode; } //****************************************************************************** // Master reads from Slave****************************************************** //****************************************************************************** SPI_Mode SPI_Master_ReadReg(uint8_t reg_addr, uint8_t count, int senNum); SPI_Mode SPI_Master_ReadReg(uint8_t reg_addr, uint8_t count, int senNum) { sensor_number = senNum; MasterMode = TX_REG_ADDRESS_MODE; TransmitRegAddr = reg_addr; RXByteCtr = count; TXByteCtr = 0; ReceiveIndex = 0; TransmitIndex = 0; if (sensor_number == 6){ CSB_M1_OUT &= ~(CSB_M1_PIN); } else if (sensor_number == 7){ CSB_M2_OUT &= ~(CSB_M2_PIN); } else if (sensor_number == 8){ CSB_M3_OUT &= ~(CSB_M3_PIN); } __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts if (sensor_number == 6){ CSB_M1_OUT |= CSB_M1_PIN; } else if (sensor_number == 7){ CSB_M2_OUT |= CSB_M2_PIN; } else if (sensor_number == 8){ CSB_M3_OUT |= CSB_M3_PIN; } return MasterMode; } //****************************************************************************** //Send Data********************************************************************* //****************************************************************************** void SendUCA0Data(uint8_t val) { while (!(UCA0IFG & UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = val; } //****************************************************************************** // Set CLOCK to 16MHz* //****************************************************************************** void initClockTo16MHz() { UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO UCSCTL4 |= 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 16MHz operation UCSCTL2 = FLLD_0 + 487; // Set DCO Multiplier for 16MHz // (N + 1) * FLLRef = Fdco // (487 + 1) * 32768 = 16MHz // Set FLL Div = fDCOCLK __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 + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag } //****************************************************************************** // INIT GPIO //****************************************************************************** void initGPIO() { //The following for GPIOs for CSB: //CSB_A1 = P2.0; CSB_A2 = P2.2; CSB_A3 = P2.4; CSB_A4 = P2.5; CSB_A5 = P1.5 //CSB_M1 = P1.2; CSB_M2 = P1.3 ; CSB_M3 = P1.4 P4DIR |= BIT7; P4OUT &= ~(BIT7); //SPI Pins P3SEL |= BIT3 + BIT4; // P3.3 = SIMO; P3.4 = SOMI P2SEL |= BIT7; // P2.7 = SCLK //UART P4SEL |= BIT4 + BIT5; // P4.4 = UART TXD; P4.5 = UART RXD /* //Button to initiate transfer P2DIR &= ~BIT6; // Set P2.1 to inpput direction P2REN |= BIT6; // Enable P2.1 internal resistance P2OUT |= BIT6; // Set P2.1 as pull-Up resistance P2IES |= BIT6; // P2.1 Hi/Lo edge P2IFG &= ~BIT6; // P2.1 IFG cleared P2IE |= BIT6; // P2.1 interrupt enabled */ } //****************************************************************************** // INIT SPI //****************************************************************************** void initSPI(int sensorno) { UCA0CTL0 &= 0; //clear this register UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCMSB + UCMST + UCSYNC; /*UCCKPH = clock phase select = 0 according to ADS1118 SPI timing diagram UCCKPL = clock polarity select = 0 according to ADS1118 SPI timing diagram UCMSB = MSB first UCMST = MSP430F5528 is the master, MC3672 and ADS1118 = slaves UCSYNC = synchronous*/ UCA0CTL1 |= UCSSEL_2; // clock = SMCLK UCA0BR0 |= 0x20; // Bit rate UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation must be cleared for SPI UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI0 RX interrupt CSB_M1_DIR |= CSB_M1_PIN; CSB_M1_OUT |= CSB_M1_PIN; CSB_M2_DIR |= CSB_M2_PIN; CSB_M2_OUT |= CSB_M2_PIN; CSB_M3_DIR |= CSB_M3_PIN; CSB_M3_OUT |= CSB_M3_PIN; } //****************************************************************************** // Main ************************************************************************ // Send and receive three messages containing the example commands ************* //****************************************************************************** int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer initClockTo16MHz(); initGPIO(); while(1) { initSPI(1); //Initialize SPI for ADS1118 SPI_Master_WriteReg(ADS1118_REG_ADDR_CONFIG_REG_MSB_def, ADS1118_REG_ADDR_CONFIG_REG_LSB, LENGTH_ONE, 6, 1); //Write to and read from ADS1118 }//end while }//end main //****************************************************************************** // SPI Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void) #else #error Compiler not supported! #endif { uint8_t uca0_rx_val = 0; switch(__even_in_range(UCA0IV,4)) { case 0:break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG uca0_rx_val = UCA0RXBUF; switch (MasterMode) { //---Always starts with this--- case TX_REG_ADDRESS_MODE: if (RXByteCtr) //If Master reading from slave { MasterMode = RX_DATA_MODE; // Need to start receiving now //Send Dummy To Start __delay_cycles(75); SendUCA0Data(DUMMY); } else if (TXByteCtr) //If Master writing to slave { MasterMode = TX_DATA_MODE; // Send the register address first SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; } break; case TX_DATA_MODE: //If Master writing to slave if (TXByteCtr) //Send the data { SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; } else { if (mymode==1){ uca0_rx_val = UCA0RXBUF; ReceiveBuffer[0] = uca0_rx_val; uca0_rx_val = UCA0RXBUF; ReceiveBuffer[1] = uca0_rx_val; uca0_rx_val = UCA0RXBUF; ReceiveBuffer[2] = uca0_rx_val; } //Done with transmission MasterMode = IDLE_MODE; __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } break; case RX_DATA_MODE: //If Master reading from slave if (RXByteCtr) { ReceiveBuffer[ReceiveIndex++] = uca0_rx_val; //Read the data from slave //Transmit a dummy RXByteCtr--; } if (RXByteCtr == 0) { MasterMode = IDLE_MODE; __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } else { SendUCA0Data(DUMMY); } break; default: __no_operation(); break; } __delay_cycles(1); //100 is ~20us break between Master Writes break; case 4:break; // Vector 4 - TXIFG default: break; } }