Hello,
I am trying to implement an algorithm that calculates area under a curve and sends that result over SPI to a SPI slave.
ADC SOC is triggered by ePWM1, and gated by an external interrupt i.e. only when the interrupt is high, the ADC value is read and stored in an array. Once the interrupt is low, the values in the array are read and accumulated. Once the entire array has been read and processed, the sum is sent over SPI where F28027 is configured as a SPI Master.
However, I am running into a strange issue. I am spitting out right-justified data on the SPI slave end and it seems to be shifted by 4b/8b etc. every time I flash the same code. It seems very strange to me. As of now, I am simply throwing a value of 1 in the array and summing it before sending it over the SPI. Do you think it is an issue with left-justification?! How do I determine how many bits to shift by if the value is always changing?
Please find the code below:
uint16_t count = 1; void system_init(void) { volatile int status = FALSE; volatile FILE *fid; // 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)); mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj)); myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj)); mySpi = SPI_init((void *)SPIA_BASE_ADDR, sizeof(SPI_Obj)); myComp = COMP_init((void *)COMP2_BASE_ADDR, sizeof(COMP_Obj)); myCap = CAP_init((void *)CAPA_BASE_ADDR, sizeof(CAP_Obj)); myPwm = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj)); // Perform basic system initialization WDOG_disable(myWDog); // Enable clocks CLK_enableAdcClock(myClk); //CLK_enableTbClockSync(myClk); //CLK_enableHrPwmClock(myClk); CLK_enablePwmClock(myClk, PWM_Number_1); (*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_12, PLL_DivideSelect_ClkIn_by_2); //--- Enable clock to peripherals // Disable the PIE and all interrupts PIE_disable(myPie); PIE_disableAllInts(myPie); 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 // Initalize GPIO // Enable XCLOCKOUT to allow monitoring of oscillator 1 GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT); CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_1); // Setup a debug vector table and enable the PIE PIE_setDebugIntVectorTable(myPie); PIE_enable(myPie); // GPI05 Interrupt (DSP_INTn) PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_4, (intVec_t)&xint_isr); // TODO ADC ePWM PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr); // TODO ADC ePWM // Register interrupt handlers in the PIE vector table //PIE_registerPieIntHandler(myPie, PIE_GroupNumber_3, PIE_SubGroupNumber_1, (intVec_t)&epwm1_isr); // Initalize GPIO gpio_init(); EALLOW; GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 12; // Configure GPIO as XINT1 EDIS; // Initialize the ADC adc_init(); // Initialize the PWM // TODO ADC ePWM pwm_init(); // Initialize SPI spi_init(); // Initialize SPI FIFO spi_fifo_init(); // Configure GPIO12 as XINT1 in Delta DSP #ifdef DELTADSP GPIO_setMode(myGpio, GPIO_Number_12, GPIO_12_Mode_GeneralPurpose); GPIO_setDirection(myGpio, GPIO_Number_12, GPIO_Direction_Input); GPIO_setPullUp(myGpio, GPIO_Number_12, GPIO_PullUp_Enable); GPIO_setExtInt(myGpio, GPIO_Number_12, CPU_ExtIntNumber_1); #endif // Enable PIE - XINT1 PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1); // Enable PIE - ADCINT1 // TODO DEBUG PIE_enableInt(myPie, PIE_GroupNumber_10, PIE_InterruptSource_ADCINT_10_1); // Enable CPU - INT1 CPU_enableInt(myCpu, CPU_IntNumber_1); // Enable CPU - INT10 CPU_enableInt(myCpu, CPU_IntNumber_10); // Enable EPWM - INT1 CPU_enableInt(myCpu, CPU_IntNumber_3); // Enable global interrupts and higher priority real-time debug events CPU_enableGlobalInts(myCpu); CPU_enableDebugInt(myCpu); // Set the interrupt polarity PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingAndFallingEdge); // Enable XINT1 PIE_enableExtInt(myPie, CPU_ExtIntNumber_1); // TODO ADC ePWM PIE_enablePwmInt(myPie, PWM_Number_1); // Set the flash OTP wait-states to minimum. This is important // for the performance of the temperature conversion function. FLASH_setup(myFlash); //Redirect STDOUT to SCI status = add_device("scia", _SSA, SCI_open, SCI_close, SCI_read, SCI_write, SCI_lseek, SCI_unlink, SCI_rename); fid = fopen("scia","w"); freopen("scia:", "w", stdout); setvbuf(stdout, NULL, _IONBF, 0); } void adc_init() { ADC_enableBandGap(myAdc); ADC_enableRefBuffers(myAdc); ADC_powerUp(myAdc); ADC_enable(myAdc); ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int); EALLOW; //AdcRegs.ADCCTL1.bit.ADCBGPWD = TRUE; // Enabled band gap in ADC AdcRegs.ADCCTL1.bit.INTPULSEPOS = TRUE; // EOC Interrupt triggers 1 cycle prior to completion AdcRegs.ADCSOC0CTL.bit.CHSEL = 4; //Set SOC0 to sample A4 AdcRegs.ADCSOC1CTL.bit.CHSEL = 4; //Set SOC1 to sample A4 AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; //Set SOC0 ACQPS to 7 ADCCLK AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; //Set SOC1 ACQPS to 7 ADCCLK // TODO DEBUG AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // 0: SW; 1: CPUTimer0; 5: PWM1. Trigger source set to EPWM1 AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; // 0: SW; 1: CPUTimer0; 5: PWM1. Trigger source set to EPWM1 AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //Connect ADCINT1 to EOC1 AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enable ADCINT1 AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Clear flag ADCINT1 //AdcRegs.INTSEL1N2.bit.INT2SEL = 1; //Connect ADCINT1 to EOC1 //AdcRegs.INTSEL1N2.bit.INT2E = 1; //Enable ADCINT1 //AdcRegs.INTSEL1N2.bit.INT2CONT = 0; //Clear flag ADCINT1 //AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // 0: No ADCINT will trigger SOCx. TRIGSEL will trigger SOCx 1: ADCINT1 EDIS; } void pwm_init() { CLK_disableTbClockSync(myClk); // Setup PWM PWM_setSyncMode(myPwm, PWM_SyncMode_CounterEqualZero); PWM_setPeriod(myPwm, EPWM_PRD); // Set period for ePWM1 PWM_setCounterMode(myPwm, PWM_CounterMode_Up); // count up and start PWM_setCmpA(myPwm, EPWM_PRD/2); // Set compare A value 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_enableInt(myPwm); CLK_enableTbClockSync(myClk); } void spi_init() { CLK_enableSpiaClock(myClk); // Reset on, rising edge, 16-bit char bits // TODO AREA SPI_setCharLength(mySpi, SPI_CharLength_16_Bits); // Enable master mode, normal phase, // enable talk, and SPI int disabled. // SPI_setMode(mySpi, SPI_Mode_Slave); // TODO DSP SPI MASTER SPI_setMode(mySpi, SPI_Mode_Master); SPI_enableTx(mySpi); // Rising edge without delay: POL = 0; PHA = 0 // Rising edge with delay: POL = 0; PHA = 1 // Falling edge without delay: POL = 1; PHA = 0 // Falling edge with delay: POL = 1; PHA = 1 SPI_setClkPolarity(mySpi, 0); SPI_setClkPhase(mySpi, 0); SPI_setBaudRate(mySpi, SPI_BaudRate_1_MBaud); SPI_setSteInv(mySpi, SPI_SteInv_ActiveLow); SPI_setTriWire(mySpi, SPI_TriWire_NormalFourWire); // Relinquish SPI from Reset SPI_disableLoopBack(mySpi); SPI_enableInt(mySpi); SPI_enable(mySpi); // Set so breakpoints don't disturb xmission SPI_setPriority(mySpi, SPI_Priority_FreeRun); } void spi_fifo_init() { // Initialize SPI FIFO registers SPI_enableChannels(mySpi); SPI_enableFifoEnh(mySpi); SPI_resetTxFifo(mySpi); SPI_clearTxFifoInt(mySpi); SPI_setTxFifoIntLevel(mySpi, SPI_FifoLevel_1_Word); SPI_enableTxFifoInt(mySpi); SPI_resetRxFifo(mySpi); SPI_clearRxFifoInt(mySpi); //SPI_setRxFifoIntLevel(mySpi, SPI_FifoLevel_1_Word); //SPI_enableRxFifoInt(mySpi); } interrupt void xint_isr(void) { if(GpioDataRegs.GPADAT.bit.GPIO12 == TRUE) { // Set above threshold flag is_above_thrsh = TRUE; // Increment above_thrsh counter count_above_thrsh++; } if(GpioDataRegs.GPADAT.bit.GPIO12 == FALSE) { // Un-set above threshold flag is_above_thrsh = FALSE; // Increment below thrsh counter count_below_thrsh++; } // Clear PIE - XINT1 Interrupt PIE_clearInt(myPie, PIE_GroupNumber_1); } interrupt void adc_isr(void) { if(is_above_thrsh == TRUE) { pulse_ampl_wr = ADC_readResult(myAdc, ADC_ResultNumber_0); pulse_ampl_wr = ADC_readResult(myAdc, ADC_ResultNumber_1); if(no_of_samples < ISR_PULSE_BUFFER_LEN) { pulse_ampl[no_of_samples] = count; no_of_samples++; } } if(is_above_thrsh == FALSE) is_fifo_processed = TRUE; // Clear ADCINT1 ADC_clearIntFlag(myAdc, ADC_IntNumber_1); // Acknowledge the interrupt to PIE PIE_clearInt(myPie, PIE_GroupNumber_10); } void main() { int i = 0; // System init system_init(); // Initialize ADC buffer adc_buffer_init(); // Delay system DSP28x_usDelay(1000); //Main program loop - continually sample temperature for(;;) { // Main loop if(is_fifo_processed == TRUE) { for(i = no_of_samples; i > 0; i--) { sum_adc_pulse_val = sum_adc_pulse_val + pulse_ampl[i]; pulse_ampl[i] = FALSE; } // SPI Transfer //GPIO_setLow(myGpio, GPIO_Number_19); //pulse_ampl_rd = SPI_read(mySpi); sum_adc_16b_val = sum_adc_pulse_val; SPI_write(mySpi, sum_adc_16b_val << 4); //GPIO_setHigh(myGpio, GPIO_Number_19); // Reset all the state flags sum_adc_pulse_val = FALSE; is_fifo_processed = FALSE; no_of_samples = FALSE; is_above_thrsh = -1; } } }