Other Parts Discussed in Thread: ADS7142, TM4C1294NCPDT
Hello All
I want to interface ADS7142 ADC IC with MSP430Fr5969
I took reference of ADS7142 with TM4C1294ncpdt example :
https://www.ti.com/lit/an/sbaa288a/sbaa288a.pdf
I tried to port the code from TM4C series to MSP430Fr series
I am not getting any response from External ADC ADS7142 and on debugging following is found :
After sending the Start bit it is waiting for transmit interrupt flag to get set
I have attached my code
Let me know if anyone has tried interfacing ADS7142 with MSP430Fr series controller and had any success
With Regards,
Aalakh Devari
/* --COPYRIGHT--,BSD
* Copyright (c) 2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
#include "driverlib.h"
//*****************************************************************************
//! This example shows how to configure the I2C module as a master for
//! single byte transmission in interrupt mode. The address of the slave
//! module that the master is communicating with also set in this example.
//!
//! Demo - EUSCI_B0 I2C Master TX single bytes to MSP430 Slave
//!
//! Description: This demo connects two MSP430's via the I2C bus. The master
//! transmits to the slave. This is the master code. It continuously
//! transmits 00h, 01h, ..., 0ffh and demonstrates how to implement an I2C
//! master transmitter sending a single byte using the USCI_B0 TX interrupt.
//! ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
//!
//! /|\ /|\
//! MSP430FR5969 10k 10k MSP430FR5969
//! slave | | master
//! ----------------- | | -----------------
//! -|XIN P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA XIN|-
//! | | | | |
//! -|XOUT | | | XOUT|-
//! | P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL |
//! | | | |
//!
//! This example uses the following peripherals and I/O signals. You must
//! review these and change as needed for your own board:
//! - I2C peripheral
//! - GPIO Port peripheral (for I2C pins)
//! - SCL2
//! - SDA
//!
//! This example uses the following interrupt handlers. To use this example
//! in your own application you must add these interrupt handlers to your
//! vector table.
//! - USCI_B0_VECTOR.
//!
//
//*****************************************************************************
//*****************************************************************************
//
//Set the address for slave module. This is a 7-bit address sent in the
//following format:
//[A6:A5:A4:A3:A2:A1:A0:RS]
//
//A zero in the "RS" position of the first byte means that the master
//transmits (sends) data to the selected slave, and a one in this position
//means that the master receives data from the slave.
//
//*****************************************************************************
#include <ADS7142RegisterMap.h>
#include "driverlib.h"
int
ADS7142SingleRegisterWrite (uint8_t RegisterAddress, uint8_t RegisterData)
{
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, ADS7142_I2C_ADDRESS );
EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE,SINGLE_REG_WRITE ); /* Send write Opcode */
EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, RegisterAddress); /* Send the Register Address */
EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B0_BASE, RegisterData); /* send the Register Data */
return 0;
}
int
ADS7142SingleRegisterRead (uint8_t RegisterAddress, uint32_t *read)
{
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, ADS7142_I2C_ADDRESS );
EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE,SINGLE_REG_READ ); /* Send write Opcode */
EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B0_BASE, RegisterAddress); /* Send the Register Address */
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, ADS7142_I2C_ADDRESS );
read[0] = EUSCI_B_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);
return 0;
}
int
ADS7142Calibrate(void)
{
//This function aborts the present conversion sequence and triggers offset calibration
//Abort the present sequence
ADS7142SingleRegisterWrite(ADS7142_REG_ABORT_SEQUENCE, ADS7142_VAL_ABORT_SEQUENCE);
//Perform Offset Calibration
ADS7142SingleRegisterWrite(ADS7142_REG_OFFSET_CAL, ADS7142_VAL_TRIG_OFFCAL);
//Return no errors
return 0;
}
int
ADS7142Reset(void)
{
//This function resets the ADS7142
//Open the Reset Key to get reset access
ADS7142SingleRegisterWrite(ADS7142_REG_WKEY, ADS7142_VAL_WKEY_DEVICE_RESET);
//Reset the ADS7142
ADS7142SingleRegisterWrite(ADS7142_REG_DEVICE_RESET, ADS7142_VAL_DEVICE_RESET_RESET);
//Prevent erroneous reset
ADS7142SingleRegisterWrite(ADS7142_REG_WKEY, ADS7142_VAL_WKEY_RESET);
//Return no errors
return 0;
}
void main (void)
{
WDT_A_hold(WDT_A_BASE);
//Set DCO frequency to 1MHz
CS_setDCOFreq(CS_DCORSEL_0,CS_DCOFSEL_0);
//Set ACLK = VLO with frequency divider of 1
CS_initClockSignal(CS_ACLK,CS_VLOCLK_SELECT,CS_CLOCK_DIVIDER_1);
//Set SMCLK = DCO with frequency divider of 1
CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
//Set MCLK = DCO with frequency divider of 1
CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN6);
GPIO_setAsInputPin(GPIO_PORT_P1, GPIO_PIN4 + GPIO_PIN5);
GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4 + GPIO_PIN5);
/*
* Select Port 1
* Set Pin 6, 7 to input Secondary Module Function, (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
*/
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION);
/*
* Disable the GPIO power-on default high-impedance mode to activate
* previously configured port settings
*/
PMM_unlockLPM5();
GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN6);
_delay_cycles(1000);
GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN6);
//Initialize Master
EUSCI_B_I2C_initMasterParam param = {0};
param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk = CS_getSMCLK();
param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
param.byteCounterThreshold = 1;
param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m);
//Set in transmit mode
EUSCI_B_I2C_setMode(EUSCI_B0_BASE,
EUSCI_B_I2C_TRANSMIT_MODE
);
//Enable I2C Module to start operations
EUSCI_B_I2C_enable(EUSCI_B0_BASE);
//Calibrate out the offset from the ADS7142
ADS7142Calibrate();
//Let's put the ADS7142 into Autonomous Mode with both Channels enabled in Single-Ended Configuration
//Select the channel input configuration
ADS7142SingleRegisterWrite(ADS7142_REG_CHANNEL_INPUT_CFG, ADS7142_VAL_CHANNEL_INPUT_CFG_2_CHANNEL_SINGLE_ENDED);
//Confirm the input channel configuration
uint32_t channelconfig;
ADS7142SingleRegisterRead(ADS7142_REG_CHANNEL_INPUT_CFG, &channelconfig);
//Select the operation mode of the device
ADS7142SingleRegisterWrite(ADS7142_REG_OPMODE_SEL, ADS7142_VAL_OPMODE_SEL_AUTONOMOUS_MONITORING_MODE);
//Confirm the operation mode selection
uint32_t opmodeselconfig;
ADS7142SingleRegisterRead(ADS7142_REG_OPMODE_SEL, &opmodeselconfig);
//Set the I2C Mode to High Speed (optional)
//ADS7142HighSpeedEnable(ADS7142_VAL_OPMODE_I2CMODE_HS_1);
//Check the I2C Mode Status
uint32_t opmodei2cconfig;
ADS7142SingleRegisterRead(ADS7142_REG_OPMODE_I2CMODE_STATUS, &opmodei2cconfig);
//Select both channels for AUTO Sequencing
ADS7142SingleRegisterWrite(ADS7142_REG_AUTO_SEQ_CHEN, ADS7142_VAL_AUTO_SEQ_CHENAUTO_SEQ_CH0_CH1);
//Confirm Auto Sequencing is enabled
uint32_t autoseqchenconfig;
ADS7142SingleRegisterRead(ADS7142_REG_AUTO_SEQ_CHEN, &autoseqchenconfig);
//Select the Low Power or High Speed Oscillator
ADS7142SingleRegisterWrite(ADS7142_REG_OSC_SEL, ADS7142_VAL_OSC_SEL_HSZ_HSO);
//Confirm the oscillator selection
uint32_t oscconfig;
ADS7142SingleRegisterRead(ADS7142_REG_OSC_SEL, &oscconfig);
//Set the minimum nCLK value for one conversion to maximize sampling speed
ADS7142SingleRegisterWrite(ADS7142_REG_nCLK_SEL, 21);
//Confirm the nCLK selection
uint32_t nCLKconfig;
ADS7142SingleRegisterRead(ADS7142_REG_nCLK_SEL, &nCLKconfig);
//Select the Data Buffer output data Configuration
ADS7142SingleRegisterWrite(ADS7142_REG_DOUT_FORMAT_CFG, ADS7142_VAL_DOUT_FORMAT_CFG_DOUT_FORMAT2);
//Select the Data Buffer opmode for Pre-Alert mode
ADS7142SingleRegisterWrite(ADS7142_REG_DATA_BUFFER_OPMODE, ADS7142_VAL_DATA_BUFFER_STARTSTOP_CNTRL_PREALERT);
//Configure CH0 High Threshold MSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HTH_CH0_MSB, 0x90);
//Configure CH0 High Threshold LSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HTH_CH0_LSB, 0x00);
//Configure CH0 Low Threshold MSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_LTH_CH0_MSB, 0x00);
//Configure CH0 Low Threshold LSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_LTH_CH0_LSB, 0x00);
//Set the Hysteresis for CH0
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HYS_CH0, 0x00);
//Configure CH1 High Threshold MSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HTH_CH1_MSB, 0xE0);
//Configure CH1 High Threshold LSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HTH_CH1_LSB, 0x00);
//Configure CH1 Low Threshold MSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_LTH_CH1_MSB, 0x00);
//Configure CH1 Low Threshold LSB
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_LTH_CH1_LSB, 0x00);
//Set the Hysteresis for CH1
ADS7142SingleRegisterWrite(ADS7142_REG_DWC_HYS_CH1, 0x00);
//Set the Pre-Alert Event Counter
ADS7142SingleRegisterWrite(ADS7142_REG_PRE_ALERT_EVENT_COUNT, ADS7142_VAL_PRE_ALERT_EVENT_COUNT4);
//Confirm the Pre-Alert Event Counter setting
uint32_t eventcount;
ADS7142SingleRegisterRead(ADS7142_REG_PRE_ALERT_EVENT_COUNT, &eventcount);
//Enable Alerts
ADS7142SingleRegisterWrite(ADS7142_REG_ALERT_CHEN, ADS7142_VAL_ALERT_EN_CH0_CH1);
//Enable the digital window comparator block
ADS7142SingleRegisterWrite(ADS7142_REG_ALERT_DWC_EN, ADS7142_VAL_ALERT_DWC_BLOCK_ENABLE);
//Set the SEQ_START Bit to begin the sampling sequence
ADS7142SingleRegisterWrite(ADS7142_REG_START_SEQUENCE, ADS7142_VAL_START_SEQUENCE);
while(1)
{
__no_operation();
__bis_SR_register(LPM4_bits + GIE);
}
return 0;
}
//******************************************************************************
//
//This is the PORT1_VECTOR interrupt vector service routine
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT1_VECTOR)))
#endif
void Port_1 (void)
{
//Reset the alert flags
ADS7142SingleRegisterWrite(ADS7142_REG_ALERT_HIGH_FLAGS, 0x03);
ADS7142SingleRegisterWrite(ADS7142_REG_ALERT_LOW_FLAGS, 0x03);
//Restart the sequence
ADS7142SingleRegisterWrite(ADS7142_REG_START_SEQUENCE, ADS7142_VAL_START_SEQUENCE);
}