This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

unable to transmit i2c data continously while using other peripherals

hi, 

i am using a c2000 launchpad f28027. i am trying to transmit data via i2c and sample adc value, these two process happen sequentially. adc values are sampled for one second using a timer and everyone second data is transmitted via i2c(here the timer,adc interrupts are disabled and i2c interrupts are enabled). after transferring 20 characters(indicates the end of the string) the i2c interrupts are disabled and timer, adc interrupts are enabled. This loop continues. However, when i try this the i2c data is transmitted only once. It also happens everytime i reset the m/c once. This login works fine when i dont have the adc sampling process included.

i suspect the PIE is responsible for this.Please help me with. 

Thank you.

here is the code i am using

//###########################################################################
//
// FILE: Example_i2c_master.c
//
// TITLE: DSP280x I2C MASTER EXAMPLE
//
// ASSUMPTIONS:
//
// This program requires the DSP280x header files.
// As supplied, this project is configured for "boot to SARAM" operation.
//
// This program will allow the I2C to act as a master. External
// connections must be made to the I2C Clock and Data pins.
//
// Signal 2808 Pin eZdsp Pin
// I2C Clock GPIO33 (pin 5) P8-38
// I2C Data GPIO32 (pin 100) P8-36
// Ground Vss (pin 2) P8-40
//
// DESCRIPTION:
//
// This program will communicate to 6 read/write locations in the Slave 2808 RAM.
// It will allow communications with those registers by the following I2C commands:
//
// I2C Write (from host)
//
// S ADDR W A DATA A DATA A DATA A P
//
// S = Start bit
// ADDR = Device Address (7 bits - to this 2808)
// W = Write
// A = Acknowledge (from 2808 to host)
// DATA = location number (0 - 5)
// A = Acknowledge (from 2808)
// DATA = High byte of word to be stored
// A = Ack
// DATA = Low byte of word to be stored
// A = Ack
// P = Stop bit
//
//
// I2C Read (from host)
//
// S ADDR W A DATA A S ADDR R A DATA A DATA A P
//
// S = Start bit
// ADDR = Device Address (7 bits - to this 2808)
// W = Write
// A = Acknowledge (from 2808 to host)
// DATA = location number (0 - 5)
// A = Acknowledge (from 2808)
//
// S = Repeated Start Bit
// ADDR = Device Address (7 bits - to this 2808)
// R = Read
// A = Acknowlege (from 2808)
// DATA = High byte of word to be read
// A = Ack (from host)
// DATA = Low byte of word to be read
// A = (N)Ack (from host)
// P = Stop bit
//
//###########################################################################
// Author: Todd Anderson
//
// October, 2006
//###########################################################################
// Change Log
//---------------------------------------------------------------------------
// Date Change
//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------

#include "DSP28x_Project.h" // DSP280x Headerfile Include File
#include "f2802x_common/include/adc.h"
#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/wdog.h"
#include "f2802x_common/include/timer.h"
#include<float.h>
#include<math.h>
// Prototype statements for functions found within this file.
interrupt void adc_isr(void);
void Adc_Config(void);
interrupt void cpu_timer0_isr(void);
interrupt void cpu_timer1_isr(void);
unsigned long timer0IntCount;
unsigned long time;

// Global variables used in this example:
uint8_t LoopCount,check=4;
uint16_t ConversionCount,c=0;
float anologVoltage;
float VoltageFroI,energy=0,powerfactor[4];
float current[4],voltage=0,v=0,v2=0,i;
float p=0,power=0,powr[4],root=0;

ADC_Handle myAdc;
CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
PWM_Handle myPwm;
TIMER_Handle myTimer0, myTimer1;
CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;

// Prototype statements for functions found within this file.
void I2CA_Init(void);
interrupt void i2c_int1a_isr(void);


struct FLAGREG_BITS
{
volatile unsigned int Rsvd:15; //bits 0-14
volatile unsigned int DataReady:1; // Bit 15
};
union FLAG_REG
{
volatile unsigned int all;
struct FLAGREG_BITS bit;
}Flags;

Uint16 Register;
Uint16 InData[3];
char OutData[20]={"visiongrid000000000"};
Uint16 I2cIndex;

void main(void)
{

// Initialize all the handles needed for this application
myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
myPwm = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
myTimer0 = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj));
myTimer1 = TIMER_init((void *)TIMER1_BASE_ADDR, sizeof(TIMER_Obj));
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP280x_SysCtrl.c file.
InitSysCtrl();

// Perform basic system initialization
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();

//Select the internal oscillator 1 as the clock source
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
PLL_setup(myPll, PLL_Multiplier_10, PLL_DivideSelect_ClkIn_by_2);

// Disable the PIE and all interrupts
PIE_disable(myPie);
PIE_disableAllInts(myPie);
InitPieCtrl();
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);

// If running from flash copy RAM only functions to RAM
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

// Setup a debug vector table and enable the PIE
PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);

// Register interrupt handlers in the PIE vector table
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr);
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_7, (intVec_t)&cpu_timer0_isr);
PIE_registerSystemIntHandler(myPie, PIE_SystemInterrupts_TINT1, (intVec_t)&cpu_timer1_isr);
EDIS;

// Initialize the ADC
ADC_enableBandGap(myAdc);
ADC_enableRefBuffers(myAdc);
ADC_powerUp(myAdc);
ADC_enable(myAdc);
ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);

// Enable ADCINT1 in PIE
PIE_enableAdcInt(myPie, ADC_IntNumber_1);
// Enable CPU Interrupt 1
CPU_enableInt(myCpu, CPU_IntNumber_10);
// Enable Global interrupt INTM
CPU_enableGlobalInts(myCpu);
// Enable Global realtime interrupt DBGM
CPU_enableDebugInt(myCpu);

LoopCount = 0;
ConversionCount = 0;
TIMER_stop(myTimer0);
TIMER_stop(myTimer1);

GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
GPIO_setMode(myGpio, GPIO_Number_1, GPIO_0_Mode_GeneralPurpose);
GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output);
GPIO_setHigh(myGpio, GPIO_Number_0);
GPIO_setHigh(myGpio, GPIO_Number_1);

// Configure ADC
//Note: Channel ADCINA4 will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata
ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior); //ADCINT1 trips after AdcResults latch
ADC_enableInt(myAdc, ADC_IntNumber_1); //Enabled ADCINT1
ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag); //Disable ADCINT1 Continuous mode
ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC2); //setup EOC2 to trigger ADCINT1 to fire
ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4); //set SOC0 channel select to ADCINA4 on j1.6
ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A2); //set SOC1 channel select to ADCINA2 on j1.8
ADC_setSocChanNumber (myAdc, ADC_SocNumber_2, ADC_SocChanNumber_A3); //set SOC2 channel select to ADCINA3 on j5.4
ADC_setSocChanNumber (myAdc, ADC_SocNumber_3, ADC_SocChanNumber_A0); //set SOC2 channel select to ADCINA0 on j5.6
ADC_setSocChanNumber (myAdc, ADC_SocNumber_4, ADC_SocChanNumber_A1); //set SOC2 channel select to ADCINA1 on j5.5
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_3, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_4, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_2, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC2 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles); //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_7_cycles); //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_2, ADC_SocSampleWindow_7_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_3, ADC_SocSampleWindow_7_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_4, ADC_SocSampleWindow_7_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)

// Enable PWM clock
CLK_enablePwmClock(myClk, PWM_Number_1);
CLK_enableTbClockSync(myClk);

// Setup PWM
PWM_enableSocAPulse(myPwm); // Enable SOC on A group
PWM_setSocAPulseSrc(myPwm, PWM_SocPulseSrc_CounterEqualCmpAIncr); // Select SOC from from CPMA on upcount
PWM_setSocAPeriod(myPwm, PWM_SocPeriod_FirstEvent); // Generate pulse on 1st event
PWM_setCmpA(myPwm, 0x0080); // Set compare A value
PWM_setPeriod(myPwm, 0x00FF); // Set period for ePWM1
PWM_setCounterMode(myPwm, PWM_CounterMode_Up); // count up and start

// Wait for ADC interrupt

// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 50MHz CPU Freq, 1 second Period (in uSeconds)

// ConfigCpuTimer(&CpuTimer0, 50, 1000000);
TIMER_setPeriod(myTimer0, 1000000); // period = (cpu_clock / freq)
// ConfigCpuTimer(&CpuTimer1, 50, 1000000);
TIMER_setPeriod(myTimer1, 50 * 1000000);
// ConfigCpuTimer(&CpuTimer2, 50, 1000000);
// TIMER_setPeriod(myTimer2, 50 * 1000000);


TIMER_setPreScaler(myTimer0, 0);
TIMER_reload(myTimer0);
TIMER_setEmulationMode(myTimer0, TIMER_EmulationMode_StopAfterNextDecrement);
TIMER_enableInt(myTimer0);

TIMER_setPreScaler(myTimer1, 0);
TIMER_reload(myTimer1);
TIMER_setEmulationMode(myTimer1, TIMER_EmulationMode_StopAfterNextDecrement);
TIMER_enableInt(myTimer1);


// To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any
// of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in F2802x_CpuTimers.h), the
// below settings must also be updated.

// CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
TIMER_start(myTimer0);
// CpuTimer1Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
TIMER_start(myTimer1);

// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2:
// IER |= M_INT1;
CPU_enableInt(myCpu, CPU_IntNumber_1);
// IER |= M_INT13;
CPU_enableInt(myCpu, CPU_IntNumber_13);
// IER |= M_INT14;
CPU_enableInt(myCpu, CPU_IntNumber_14);

// Enable TINT0 in the PIE: Group 1 interrupt 7
// PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PIE_enableTimer0Int(myPie);

// Step 2. Initalize GPIO:
// Setup only the GP I/O only for I2C functionality
InitI2CGpio();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP280x_PieCtrl.c file

// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP280x_DefaultIsr.c.
// This function is found in DSP280x_PieVect.c.
InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.I2CINT1A = &i2c_int1a_isr;
EDIS; // This is needed to disable write to EALLOW protected registers

I2cIndex = 0;
Flags.bit.DataReady = 0;

// Step 4. Initialize all the Device Peripherals:
I2CA_Init();

// Enable interrupts required for this example
// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
// PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

// Enable CPU INT8 which is connected to PIE group 8
IER |= M_INT8;
EINT;

CPU_enableGlobalInts(myCpu);
// ERTM; // Enable Global realtime interrupt DBGM
CPU_enableDebugInt(myCpu);

// Application loop
while(1)
{
if(I2cIndex==20)
{
I2cIndex=0;
PieCtrlRegs.PIEIER8.bit.INTx1 = 0; //disable i2c interrupt
// PIE_enableAdcInt(myPie, ADC_IntNumber_1);
// PIE_enableTimer0Int(myPie);

}
}
} // end of main


void I2CA_Init(void)
{
// Initialize I2C
I2caRegs.I2COAR = 0x0048; // Own address
I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk
I2caRegs.I2CCLKL = 10; // NOTE: must be non zero
I2caRegs.I2CCLKH = 5; // NOTE: must be non zero
I2caRegs.I2CCNT = 1; // Get 1 byte
I2caRegs.I2CIER.all = 0x18; // Clear interrupts (was 0)
I2caRegs.I2CSTR.bit.RRDY = 1; // Clear flag
I2caRegs.I2CSTR.bit.XRDY = 1; //rx ready
I2caRegs.I2CIER.bit.RRDY = 1; // Enable Receive Interrupt
I2caRegs.I2CIER.bit.XRDY = 1;
I2caRegs.I2CEMDR.bit.BCM = 1;

I2caRegs.I2CMDR.all = 0x08A0; // Take I2C out of reset
// Stop I2C when suspended
return;
}


interrupt void i2c_int1a_isr(void) // I2C-A
{
Uint16 IntSource;

// Read interrupt source
IntSource = I2caRegs.I2CISRC.bit.INTCODE & 0x7;

switch(IntSource)
{
case I2C_NO_ISRC: // =0
break;

case I2C_ARB_ISRC: // =1
break;

case I2C_NACK_ISRC: // =2
break;

case I2C_ARDY_ISRC: // =3
break;

case I2C_RX_ISRC: // =4
break;

case I2C_TX_ISRC: // =5
//if (I2cIndex == 0) break; // If reset already, break.
I2caRegs.I2CDXR = OutData[I2cIndex++]; // Output Data to Host

if (I2cIndex ==20) // if index is at 3, we are done.
{
// reset index.
PieCtrlRegs.PIEIER8.bit.INTx1 = 0;
}
break;

case I2C_SCD_ISRC: // =6
break;

case I2C_AAS_ISRC: // =7
break;

default:
asm(" ESTOP0"); // Halt on invalid number.
}

// Enable further I2C (PIE Group 8) interrupts by acknowledging this one.
PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
}

interrupt void adc_isr(void)
{

//discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0
anologVoltage = 336.48*ADC_readResult(myAdc, ADC_ResultNumber_0)*3.3/4096-551.89; //on p1.8
// anologVoltage = ADC_readResult(myAdc, ADC_ResultNumber_1)*3.3/4096;
VoltageFroI = 15.463*ADC_readResult(myAdc, check)*3.3/4096-25.405; //on p1.6
// VoltageFroI = 24*ADC_readResult(myAdc, ADC_ResultNumber_0)*3.3/4096-41.76;

v+= anologVoltage* anologVoltage;
i+=VoltageFroI*VoltageFroI;
p+=anologVoltage*VoltageFroI;

// Clear ADCINT1 flag reinitialize for next SOC
ADC_clearIntFlag(myAdc, ADC_IntNumber_1);
// Acknowledge interrupt to PIE
PIE_clearInt(myPie, PIE_GroupNumber_10);
ConversionCount++;
GPIO_toggle(myGpio, GPIO_Number_1);
return;
}

interrupt void cpu_timer0_isr(void)
{
timer0IntCount++;
powr[check-1]=p/ConversionCount;
voltage= sqrt(v/(ConversionCount));
current[check-1]= sqrt(i/(ConversionCount));
powerfactor[check-1]=powr[check-1]/(voltage*current[check-1]);

v=0;
i=0;
c=ConversionCount;
if(check==4)
check=1;
else
check++;
ConversionCount=0;
p=0;
GPIO_toggle(myGpio, GPIO_Number_0);

// Acknowledge this interrupt to receive more interrupts from group 1
// PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
PIE_clearInt(myPie, PIE_GroupNumber_1);
}

interrupt void cpu_timer1_isr(void)
{

PIE_disableInt(myPie, PIE_GroupNumber_10, PIE_InterruptSource_ADCINT_10_1);
PIE_disableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_TIMER_0);
PieCtrlRegs.PIEIER8.bit.INTx1 = 1; //enable i2c interrupt
}

//===========================================================================
// No more.
//===========================================================================

  • I found that there is a procedure to disable an interrupt specifed in the SPRUFN3d.pdf. However, the problem still persists.

    This is the code snippet:

    asm(" SETC INTM"); //disable global interrupts
    PieCtrlRegs.PIEIER8.bit.INTx1 = 0;
    asm("NOP");
    // asm("NOP");
    PieCtrlRegs.PIEIFR8.all = 0;
    PieCtrlRegs.PIEACK.all = 0;
    asm(" CLRC INTM"); //enable global interrupts

    What am i doing wrong?