void freqDmaRun(void) { LDD_TDeviceData *DMAPtr = NULL; LDD_DMA_TTransferDescriptor TransferDesc; volatile bool Completed = FALSE; bool monitorEnable = FALSE; unsigned int uTimerCaptureClock = CAPTURE_CLOCK_HZ; // My local init clearTable(); // Init the DMA TransferDesc = DMA_TRANSFER_DESC_NULL; TP3_ptr = TP3_Init(NULL); TP4_ptr = TP4_Init(NULL); // TINT1Ptr = TINT1_Init(NULL); DMAPtr = DMA0_Init(NULL); /* Initialize transfer descriptor */ // Source TransferDesc.SourceAddress = (LDD_DMA_TAddress)&FTM0_C4V; // (FTM1_C0SC, FTM1_C0V) FTM1_CH0 capture TransferDesc.SourceAddressOffset = (LDD_DMA_TAddressOffset)0; // Single source TransferDesc.SourceTransferSize = (LDD_DMA_TTransferSize)DMA_PDD_16_BIT; // 16-bit value TransferDesc.SourceModuloSize = (LDD_DMA_TModuloSize)0; // non relevant (single source) // Destination TransferDesc.DestinationAddress = (LDD_DMA_TAddress)aDmaCaptureTbl; // Move to Capture table TransferDesc.DestinationAddressOffset = (LDD_DMA_TAddressOffset)sizeof(aDmaCaptureTbl[0]); // Next write offset TransferDesc.DestinationTransferSize = (LDD_DMA_TTransferSize)DMA_PDD_16_BIT; // moving 16-bit data TransferDesc.DestinationModuloSize = (LDD_DMA_TModuloSize)0; // we will set manually a new address // We have Major loop = Move 4 bytes per interrupt and repeat 8 times TransferDesc.TransferMode = LDD_DMA_NESTED_TRANSFERS; TransferDesc.ByteCount = (LDD_DMA_TByteCount)2; TransferDesc.OuterLoopCount = (LDD_DMA_TOuterLoopCount)NBR_DMA_CAPTURE_SAMPLES; // DMA channel TransferDesc.ChannelAutoSelection = FALSE;// TRUE; // Fixed to ch 0 TransferDesc.ChannelNumber = (LDD_DMA_TChannelNumber)0; // Channel 0 in this example // Trigger TransferDesc.TriggerType = LDD_DMA_HW_TRIGGER; // Triggered by Peripheral request // TransferDesc.TriggerSource = (LDD_DMA_TTriggerSource)24; // DMA source Table 3-24 == FTM0_CH4 TransferDesc.Interrupts = TRUE; // we are here We are not going to interrupt on DMA transfer complete TransferDesc.OnComplete = TRUE; // Signal an DMA-done TransferDesc.OnCompleteEventPtr = &TransferComplete; // call this function TransferDesc.UserDataPtr = (LDD_TUserData*)&Completed; // the UserDataPtr to pass data // AFter transfer TransferDesc.AfterTransferComplete = LDD_DMA_ADDRESS_ADJUSTMENT; TransferDesc.DestinationAddressAdjustment = -(2*NBR_DMA_CAPTURE_SAMPLES); /* Start DMA transfer */ DMA0_AllocateChannel(DMAPtr, &TransferDesc); // Still need to call this method even we have a fixed channel DMA0_EnableChannel(DMAPtr, &TransferDesc); // This moves the TransferDesc to the TCD 32 bytes // DMA0_StartChannelTransfer(DMAPtr, &TransferDesc); //============ Using PEX DMA, TCAP Components ========================= // TCAP:TimerUnit_LDD !!! DO not enable in init code and do not Autoninit in PEX properties !! TimerPtr = TCAP_Init(NULL); // Set the desired PEX Properties and get the pointer to static memory // Individually disable Channels FTM0_C0SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH0 interrupt and repeat for other channels FTM0_C4SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH1 interrupt FTM0_C0V = 0x7FFF; // Need to have DMA ready before OVrs // Enable the base Timer Module by selecting the clk source in CLKS[FTM1_SC] TCAP_Enable(TimerPtr); // DONE! to start capturing, enable the Channel capture IE in the App // remove Debug UART buffering (stream i/o) setvbuf(stdout, NULL, _IONBF, 0); // no buffering on stdout - for printf() setvbuf(stdin, NULL, _IONBF, 0); // no buffering on stdin - for getchar() etc printf("Capture FTM1_CH0 at PTA12 - press '1','t' to start, 'm' to monitor\n\r"); printf("\n\r"); unsigned int uLocalCapture=0; // Init Periodic Time Interrupt // TINT1_Enable(TINT1Ptr); // Enable interrupts after we get the pointer to PTA17 int i, ch =0; uCapture = uLocalCapture =0; float fFreq; unsigned int uCtr=0; while(1) { if(uLocalCapture != uCapture) { if(uCapture > 99) uCapture =0; uLocalCapture = uCapture; // PTA17_NegVal(PTA17_ptr); printf("(%2u,%u) ", uCapture, tPeriodIsr); // Isr executed } if( (ch = getchar()) != EOF ) switch(ch) { // Diable all interrupts case '0': FTM0_C0SC &= ~FTM_CnSC_CHIE_MASK; FTM0_C4SC &= ~(FTM_CnSC_CHIE_MASK | FTM_CnSC_DMA_MASK); break; // Enable DMA case '1' : FTM0_C4SC |= (FTM_CnSC_CHIE_MASK | FTM_CnSC_DMA_MASK); // Enable TCAP_CH4 DMA request break; // Enable Isr in Capture case '2' : FTM0_C4SC |= FTM_CnSC_CHIE_MASK; // Test TCAP_CH4 ISR is working break; // Enable (OvfIsr) case 't' : case 'T': FTM0_C0SC |= FTM_CnSC_CHIE_MASK; // Test TCAP_CH0 (OVF) ISR is working break; case '4': monitorEnable = monitorEnable ? 0 :1; break; case 'm': // bDisplay = TRUE; monitorEnable = monitorEnable? FALSE : TRUE; break; case '?': printf("\r\nMon=%d, Clk= %u, type '+'/'-' to inc/dec", monitorEnable, uTimerCaptureClock); if(tFreqInput.uNbrEdges >1 ) fFreq = (float)tFreqInput.uNbrEdges * uTimerCaptureClock/tFreqInput.utCalcPeriod.l; //(saves one multiplication) else fFreq = (float)uTimerCaptureClock/tFreqInput.utCalcPeriod.l; // Output the value printf("%5u %f\r\n", ++uCtr, fFreq); break; case ' ': bDisplay = TRUE; break; case '+': ++uTimerCaptureClock; break; case '-': --uTimerCaptureClock; break; case 'c': case 'C': clearTable(); break; } if(monitorEnable && tFreqInput.fNewFreq) { //TP3_SetVal(TimerPtr); tFreqInput.fNewFreq = FALSE; if(tFreqInput.uNbrEdges >1 ) fFreq = (float)tFreqInput.uNbrEdges * uTimerCaptureClock/tFreqInput.utCalcPeriod.l; //(saves one multiplication) else fFreq = (float)uTimerCaptureClock/tFreqInput.utCalcPeriod.l; // Output the value printf("%5u %f\r\n", ++uCtr, fFreq); //TP3_ClrVal(TimerPtr); } } // DMA_Deinit(DMAPtr); // TIMER_Deinit(TimerPtr); }
/******************************************************* * MAIN function, just setup some inits and loops * "soft" real-time event handlers, defined hereafter ********************************************************/ int main(void) { // configuro l'oscillatore interno che mi fornisce Tcy // Fosc = Fin (M/(N1*N2)) // FCY = Fosc/2 PLLFBD = 39; // M = 40 CLKDIVbits.PLLPOST=0; // N2 = 2 CLKDIVbits.PLLPRE=0; // N1 = 2 RCONbits.SWDTEN = 0; //disabilito il watchdog DataEEInit(); //Init Peripheral Pin Selection (QEI and UART) PPS_Init(); control_flags.first_scan = 1; slow_ticks_limit = SLOW_RATE * (FCY_PWM / 1000) - 1 ; medium_ticks_limit = MEDIUM_RATE * (FCY_PWM / 1000) - 1; mposition1 = zero_pos1;//parto dalla posizione iniziale 90 90 90 mposition2 = zero_pos2; mposition3 = zero_pos3; /*mtheta1 = 0; mtheta2 = 0; mtheta3 = 0; x_cart = 0; y_cart = 0; z_cart = 0;*/ coordinates_actual.x = 0; coordinates_actual.y = 0; coordinates_actual.z = 0; coordinates_temp.x = 0; coordinates_temp.y = 0; coordinates_temp.z = 0; angleJoints_actual.theta1 = 0; angleJoints_actual.theta2 = 0; angleJoints_actual.theta3 = 0; angleJoints_temp.theta1 = 0; angleJoints_temp.theta2 = 0; angleJoints_temp.theta3 = 0; update_params(); direction_flags_prev = direction_flags.word; // UARTs init // no need to set TRISx, they are "Module controlled" UART1_Init(); // Setup control pins and PWM module, // which is needed also to schedule "soft" // real-time tasks w/PWM interrupt tick counts DIR1 = direction_flags.motor1_dir;//0; DIR2 = direction_flags.motor2_dir;//1; DIR3 = direction_flags.motor3_dir; //BRAKE1 = 0; //BRAKE2 = 0; DIR1_TRIS = OUTPUT; DIR2_TRIS = OUTPUT; DIR3_TRIS = OUTPUT; //BRAKE1_TRIS = OUTPUT; //BRAKE2_TRIS = OUTPUT; CURRSENSE1_TRIS = INPUT; CURRSENSE2_TRIS = INPUT; CURRSENSE3_TRIS = INPUT; PWM_Init(); // MUST SETUP ALSO ANALOG PINS AS INPUTS AN0_TRIS = INPUT; AN1_TRIS = INPUT; AN2_TRIS = INPUT; ADC_Init(); DMA0_Init(); // SETUP ENCODER INPUTS // QEI inputs are "module controlled" // -> no need to set TRISx QEI1_Init(); QEI2_Init(); // Timers used to acquire Encoder 3 // corresponding PINS set as inputs T1CK_TRIS = INPUT; T4CK_TRIS = INPUT; Timer1_Init(); Timer2_Init(); Timer4_Init(); // Timer5 used to schedule POSITION loops Timer5_Init(); //Input capture IC1_Init(); IC2_Init(); // TEST PIN TEST_PIN_TRIS = OUTPUT; TEST_PIN = FALSE; while(1)//a ciclo infinito ripeto queste 2 routine { medium_event_handler(); slow_event_handler(); } return 0; //code should never get here }// END MAIN()
void initFreqDma(void) { uint8 i; // DMA channels initialized DMAPtr = DMA0_Init(NULL); for(i=0; i< NBR_FREQ_CHANNELS; ++i) { // Initialize transfer descriptor TransferDesc = DMA_TRANSFER_DESC_NULL; // DMA Source TransferDesc.SourceAddress = aTransferDesc[i].SourceAddress; // (LDD_DMA_TAddress)&FTM0_C4V; TransferDesc.SourceAddressOffset = (LDD_DMA_TAddressOffset)0; // Single source TransferDesc.SourceTransferSize = (LDD_DMA_TTransferSize)DMA_PDD_16_BIT; // 16-bit value TransferDesc.SourceModuloSize = (LDD_DMA_TModuloSize)0; // non relevant (single source) // DMA Destination TransferDesc.DestinationAddress = (LDD_DMA_TAddress)&aDmaCaptureTbl[i]; // Move to Capture table TransferDesc.DestinationAddressOffset = (LDD_DMA_TAddressOffset)sizeof(aDmaCaptureTbl[i][0]); // Next write offset TransferDesc.DestinationTransferSize = (LDD_DMA_TTransferSize)DMA_PDD_16_BIT; // moving 16-bit data TransferDesc.DestinationModuloSize = (LDD_DMA_TModuloSize)0; // we will set manually a new address // We have Major loop = Move 2 bytes per interrupt and repeat NBR_DMA_CAPTURE_SAMPLES times TransferDesc.TransferMode = LDD_DMA_NESTED_TRANSFERS; TransferDesc.ByteCount = (LDD_DMA_TByteCount)2; TransferDesc.OuterLoopCount = (LDD_DMA_TOuterLoopCount)NBR_DMA_CAPTURE_SAMPLES; // DMA channel TransferDesc.ChannelAutoSelection = FALSE;// TRUE; // Fixed to ch 0 TransferDesc.ChannelNumber = aTransferDesc[i].ChannelNumber; // Channel 0,1,2,3 from table above (must match PEX) // Trigger TransferDesc.TriggerType = LDD_DMA_HW_TRIGGER; // Triggered by Peripheral request // TransferDesc.TriggerSource = aTransferDesc[i].TriggerSource; // DMA source Table 3-24 == FTM0_CH4, TransferDesc.Interrupts = TRUE; TransferDesc.OnComplete = TRUE; // FALSE won't interrupt when DMA-done TransferDesc.OnCompleteEventPtr = apfDmaTransferComplete[i]; // call this function TransferDesc.UserDataPtr = (LDD_TUserData*)&afCompleted[i]; // the UserDataPtr to pass data // After transfer TransferDesc.AfterTransferComplete = LDD_DMA_ADDRESS_ADJUSTMENT; TransferDesc.DestinationAddressAdjustment = -(2*NBR_DMA_CAPTURE_SAMPLES); //== Allocate and Enable the DMA channels == if( DMA0_AllocateChannel(DMAPtr, &TransferDesc) != ERR_OK || // (FreqDma_AllocateChannel[i])( DMAPtr[i], &TransferDesc); DMA0_EnableChannel(DMAPtr, &TransferDesc) != ERR_OK ) atFreqIn[i].fDmaChReady = FALSE; else atFreqIn[i].fDmaChReady = TRUE; } // Now setup the Capture Timer //============ Using PEX DMA, TCAP Components ========================= // TCAP:TimerUnit_LDD !!! DO not enable in init code and do not Autoninit in PEX properties !! TimerPtr = TCAP_Init(NULL); // Set the desired PEX Properties and get the pointer to static memory // Individually disable Channels FTM0_C0SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH0 interrupt and repeat for other channels FTM0_C0V = 0x7FFF; // Need to have DMA ready before OVrs FTM0_C4SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH1 interrupt FTM0_C5SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH2 interrupt FTM0_C6SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH3 interrupt FTM0_C7SC &= ~FTM_CnSC_CHIE_MASK; // Disable CH4 interrupt // Enable the base Timer Module by selecting the clk source in CLKS[FTM1_SC] TCAP_Enable(TimerPtr); }