Other Parts Discussed in Thread: ADS7142,
Hello,
In light of being unsuccessful with utilizing the polling method to configure the ADS7142 and get it sampling, I have moved to utilizing the interrupt method for communication with the device. Here is my code so far:
//*****************************************************************************
//
// ADS7142_ManualMode_CH0Scan.c - Example demonstrating a simple I2C
// transmission and reception.
//
// Copyright (c) 2010-2016 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// 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.
//
// This is part of revision 2.1.3.156 of the Tiva Firmware Development Package.
//
//*****************************************************************************
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/i2c.c"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "ADS7142registermap.h"
#include "ocf_includes.h"
#include "driverlib/interrupt.h"
#include "driverlib/interrupt.c"
//*****************************************************************************
//
//! \addtogroup i2c_examples_list
//!
//!
//! This example shows how to configure the I2C8 module for connection/communication
//! with the ADS7142 Boosterpack.
//! This includes setting up the master and slave module. Loopback mode
//! internally connects the master and slave data and clock lines together. This example
//! does not use loopback mode is communication is being performed with an external device
//! to the TM4C1294NCPDT microcontroller.
//! The address of the slave module is set in order to read data from the
//! master. Then the data is checked to make sure the received data matches
//! the data that was transmitted. This example uses a polling method for
//! sending and receiving data.
//!
//! This example uses the following peripherals and I/O signals. You must
//! review these and change as needed for your own board:
//! - I2C8 peripheral
//! - GPIO Port A peripheral (for I2C8 pins)
//! - I2C8SCL - PA2
//! - I2C8SDA - PA3
//!
//! 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.
//! - None.
//
//*****************************************************************************
//*****************************************************************************
//
// 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. The slave address of
// the ADS7142 in this example is set by hardware on the ADS7142boosterpack
//
//*****************************************************************************
typedef enum
{
STATE_IDLE = 0,
STATE_WRITE_NEXT = 1,
STATE_WRITE_FINAL = 2,
STATE_WAIT_ACK = 3,
STATE_SEND_ACK = 4,
STATE_READ_ONE = 5,
STATE_READ_FIRST = 6,
STATE_READ_NEXT = 7,
STATE_READ_FINAL = 8,
STATE_READ_WAIT = 9
} STATE;
//*****************************************************************************
//
// The current state of the interrupt handler state machine.
//
//*****************************************************************************
static volatile STATE TM4C1294_State = STATE_IDLE;
//*****************************************************************************
//
// The variables that track the data to be transmitted or received.
//
//*****************************************************************************
static unsigned long *i2cdata = 0;
static unsigned long count = 0;
void SetState(STATE state)
{
TM4C1294_State = state;
}
void
I2C8Handler() // Maps to the Tiva I2C8 module
{
//
// Clear the I2C interrupt.
//
I2CMasterIntClear(I2C8_BASE);
//
// Determine what to do based on the current state.
//
switch(TM4C1294_State)
{
//
// The idle state.
//
case STATE_IDLE:
{
// AtState();
//
// There is nothing to be done.
//
break;
}
//
// The state for the middle of a burst write.
//
case STATE_WRITE_NEXT:
{
// AtState();
//
// Write the next byte to the data register.
//
I2CMasterDataPut(I2C8_BASE, *i2cdata++);
count--;
//
// Continue the burst write.
//
I2CMasterControl(I2C8_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
//
// If there is one byte left, set the next state to the final write
// state.
//
if(count == 1)
{
SetState(STATE_WRITE_FINAL);
}
//
// This state is done.
//
break;
}
//
// The state for the final write of a burst sequence.
//
case STATE_WRITE_FINAL:
{
// AtState();
//
// Write the final byte to the data register.
//
I2CMasterDataPut(I2C8_BASE, 0);
count--;
//
// Finish the burst write.
//
I2CMasterControl(I2C8_BASE,
I2C_MASTER_CMD_BURST_SEND_FINISH);
//
// The next state is to wait for the burst write to complete.
//
SetState(STATE_SEND_ACK);
//
// This state is done.
//
break;
}
//
// Wait for an ACK on the read after a write.
//
case STATE_WAIT_ACK:
{
// AtState();
//
// See if there was an error on the previously issued read.
//
if(I2CMasterErr(I2C8_BASE) == I2C_MASTER_ERR_NONE)
{
//
// Read the byte received.
//
I2CMasterDataGet(I2C8_BASE);
//
// There was no error, so the state machine is now idle.
//
SetState(STATE_IDLE);
//
// This state is done.
//
break;
}
//
// Fall through to STATE_SEND_ACK.
//
}
//
// Send a read request, looking for the ACK to indicate that the write
// is done.
//
case STATE_SEND_ACK:
{
// AtState();
//
// Put the I2C master into receive mode.
//
I2CMasterSlaveAddrSet(I2C8_BASE, ADS7142_I2C_ADDRESS, true);
//
// Perform a single byte read.
//
I2CMasterControl(I2C8_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//
// The next state is the wait for the ack.
//
SetState(STATE_WAIT_ACK);
//
// This state is done.
//
break;
}
//
// The state for a single byte read.
//
case STATE_READ_ONE:
{
// AtState();
//
// Put the I2C master into receive mode.
//
I2CMasterSlaveAddrSet(I2C8_BASE, ADS7142_I2C_ADDRESS, true);
//
// Perform a single byte read.
//
I2CMasterControl(I2C8_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//
// The next state is the wait for final read state.
//
SetState(STATE_READ_WAIT);
//
// This state is done.
//
break;
}
//
// The state for the start of a burst read.
//
case STATE_READ_FIRST:
{
// AtState();
//
// Put the I2C master into receive mode.
//
I2CMasterSlaveAddrSet(I2C8_BASE, ADS7142_I2C_ADDRESS, true);
//
// Start the burst receive.
//
I2CMasterControl(I2C8_BASE,
I2C_MASTER_CMD_BURST_RECEIVE_START);
//
// The next state is the middle of the burst read.
//
SetState(STATE_READ_NEXT);
//
// This state is done.
//
break;
}
//
// The state for the middle of a burst read.
//
case STATE_READ_NEXT:
{
//
// Read the received character.
//
*i2cdata++ = I2CMasterDataGet(I2C8_BASE);
count--;
//
// Continue the burst read.
//
I2CMasterControl(I2C8_BASE,
I2C_MASTER_CMD_BURST_RECEIVE_CONT);
//
// If there are two characters left to be read, make the next
// state be the end of burst read state.
//
if(count == 2)
{
SetState(STATE_READ_FINAL);
}
//
// This state is done.
//
break;
}
//
// The state for the end of a burst read.
//
case STATE_READ_FINAL:
{
//
// Read the received character.
//
*i2cdata++ = I2CMasterDataGet(I2C8_BASE);
count--;
//
// Finish the burst read.
//
I2CMasterControl(I2C8_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//
// The next state is the wait for final read state.
//
SetState(STATE_READ_WAIT);
//
// This state is done.
//
break;
}
//
// This state is for the final read of a single or burst read.
//
case STATE_READ_WAIT:
{
//
// Read the received character.
//
*i2cdata++ = I2CMasterDataGet(I2C8_BASE);
count--;
//
// The state machine is now idle.
//
SetState(STATE_IDLE);
//
// This state is done.
//
break;
}
}
}
void
ADS7142SingleRegisterWrite(uint8_t RegisterAddress, uint8_t RegisterData)
{
//
// Save the data buffer to be written.
//
i2cdata[0] = SINGLE_WRITE;
i2cdata[1] = RegisterAddress;
i2cdata[2] = RegisterData;
count = 3;
//
// Set the next state of the interrupt state machine based on the number of
// bytes to write.
//
if(count != 1)
{
SetState(STATE_WRITE_NEXT);
}
else
{
SetState(STATE_WRITE_FINAL);
}
//
// Set the slave address and setup for a transmit operation.
//
I2CMasterSlaveAddrSet(I2C8_BASE, ADS7142_I2C_ADDRESS, false);
//
// Place the address to be written in the data register.
//
I2CMasterDataPut(I2C8_BASE, i2cdata[0]);
//
// Start the burst cycle, writing the address as the first byte.
//
I2CMasterControl(I2C8_BASE, I2C_MASTER_CMD_BURST_SEND_START);
//
// Wait until the I2C interrupt state machine is idle.
//
while(TM4C1294_State != STATE_IDLE)
{
}
}
void
TM4C1294Init(void)
{
//*****************************************************************************
//
// Configure the I2C8 master and slave and connect them to the ADS7142 Boosterpack
//
//*****************************************************************************
#if defined(TARGET_IS_TM4C129_RA0) || \
defined(TARGET_IS_TM4C129_RA1) || \
defined(TARGET_IS_TM4C129_RA2)
uint32_t ui32SysClock;
#endif
//
// Set the clocking to run directly from the external crystal/oscillator.
// TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
// crystal on your board.
//
#if defined(TARGET_IS_TM4C129_RA0) || \
defined(TARGET_IS_TM4C129_RA1) || \
defined(TARGET_IS_TM4C129_RA2)
ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_OSC), 25000000);
#else
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
#endif
//
// The I2C8 peripheral must be enabled before use.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C8);
//
// For this example I2C8 is used with PortA[3:2]. The actual port and
// pins used may be different on your part, consult the data sheet for
// more information. GPIO port A needs to be enabled so these pins can
// be used.
// TODO: change this to whichever GPIO port you are using.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Configure the pin muxing for I2C8 functions on port A2 and A3.
// This step is not necessary if your part does not support pin muxing.
// TODO: change this to select the port/pin you are using.
//
GPIOPinConfigure(GPIO_PA2_I2C8SCL);
GPIOPinConfigure(GPIO_PA3_I2C8SDA);
//
// Select the I2C function for these pins. This function will also
// configure the GPIO pins pins for I2C operation, setting them to
// open-drain operation with weak pull-ups. Consult the data sheet
// to see which functions are allocated per pin.
// TODO: change this to select the port/pin you are using.
//
GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_3);
//
//Enable master interrupts. This function will enable all interrupts
//available to the I2C Master.
// I2CMasterIntEnable(I2C8_BASE);
// I2CSlaveIntEnable(I2C8_BASE);
#if defined(TARGET_IS_TM4C129_RA0) || \
defined(TARGET_IS_TM4C129_RA1) || \
defined(TARGET_IS_TM4C129_RA2)
I2CMasterInitExpClk(I2C8_BASE, ui32SysClock, false);
#else
I2CMasterInitExpClk(I2C8_BASE, SysCtlClockGet(), false);
#endif
//Enable the I2C Master
I2CMasterEnable(I2C8_BASE);
//
// Enable processor interrupts.
//
IntMasterEnable();
// Enable the I2C interrupt.
IntEnable(INT_I2C8_TM4C129);
//Register the I2C8Handler to handle I2C8 module interrupts
IntRegister(INT_I2C8_TM4C129, I2C8Handler);
//
// Enable the I2C master interrupts
//
I2CMasterIntEnable(I2C8_BASE);
}
int
main(void)
{
//Initialize the Master MCU
TM4C1294Init();
//Let's put the ADS7142 into Manual Mode (I2C Command Mode) with a Single Channel enabled in Single-Ended Configuration
////Select the channel input configuration
ADS7142SingleRegisterWrite(ADS7142_REG_CHANNEL_INPUT_CFG, ADS7142_VAL_CHANNEL_INPUT_CFG_1_CHANNEL_SINGLE_ENDED);
//
////Confirm the input channel configuration
//ADS7142SingleRegisterRead(ADS7142_REG_CHANNEL_INPUT_CFG);
//
////Select the operation mode of the device
//ADS7142SingleRegisterWrite(ADS7142_REG_OPMODE_SEL, ADS7142_VAL_OPMODE_SEL_I2C_CMD_MODE_W_CHANNEL_0);
//
////Confirm the operation mode selection
//ADS7142SingleRegisterRead(ADS7142_REG_OPMODE_SEL);
//
////Begin manual mode operation
////Start Sampling Ch0
//StartSampling();
return(0);
}
I enable the interrupts that I think are pertinent to this application (Processor interrupts, I2C interrupts, and I2C master interrupts) but a fault ISR is being called when I make my first function call after initialization in main. Within ADS7142SingleRegisterWrite(), I initialize the three pieces of i2cdata to write but a fault ISR gets called after initializing the second piece of data after which it loops infinitely and does not respond. What might be causing the fault ISR?
Regards,
Will