dear
i have xmega256A3u . i have to operate 16 ultrasonic Hcsr04 directly to the MCU, where i am using the TC0 timers (TCC0,TCD0,TCE0,TCF0).in each of them i use the four capture channel CCA,CCB,CCC,CCD in normal mode with Pulse-Width capture,
the 16 Hcsr04 sensors are divided into 4 groups, each group have 4 sensor and each sensor use one capture channel of the related timer, so the for first two sensor group(8 sensor) i use TCC0 and TCD0, with selection of the event channel 0 to event channel 7 connected to PORTA which receive the echo signals, but for the second-tow sensor group(8 sensor) i am trying to change the source of the event channel to operate another 8 echo which the are connected to PORTD, below some parts of my code, i use TCC1 for timer out for 30 ms , for the first two group i use "init_event_system(&ECHO_PORT1)", and for the secon i use init_event_system(&ECHO_PORT2);
#define TIME_OUT_TIMER TCC1 #define FIRST_LAYER_TIMER TCC0 #define SECOND_LAYER_TIMER TCD0 #define THIRD_LAYER_TIMER TCE0 #define FORTH_LAYER_TIMER TCF0 #define FIRST_SONAR_LAYER 1 #define SECOND_SONAR_LAYER 2 #define THIRD_SONAR_LAYER 3 #define FOURTH_SONAR_LAYER 4 #define ECHO_PORT1 PORTA #define ECHO_PORT2 PORTD #define TRIGG_PORT1 PORTB #define TRIGG_PORT2 PORTC void init_TC1_normal_mode(TC1_t *t) { t->CTRLA = TC_CLKSEL_OFF_gc; t->CTRLB=(0<<TC0_CCDEN_bp) | (0<<TC0_CCCEN_bp) | (0<<TC0_CCBEN_bp) | (0<<TC0_CCAEN_bp) | TC_WGMODE_NORMAL_gc; t->CTRLD=TC_EVACT_OFF_gc | TC_EVSEL_OFF_gc; t->CTRLE=TC_BYTEM_NORMAL_gc; t->INTCTRLA=TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_LO_gc; t->INTCTRLB = TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc; HIRESF.CTRLA &= ~HIRES_HREN0_bm; t->INTFLAGS=TCF0.INTFLAGS; t->CNT=0x0000; t->PER=0xEA5F;//oxEE47;30 ms t->CCA=0x0000; t->CCB=0x0000; SREG=s; } void init_TC0_capture_input(TC0_t *timer) { timer_0_disable(timer); timer->CTRLB = TC0_CCAEN_bm | TC0_CCBEN_bm | TC0_CCCEN_bm | TC0_CCDEN_bm| TC_WGMODE_NORMAL_gc; timer->CTRLA = TC_CLKSEL_DIV8_gc; timer->INTCTRLB = TC_CCAINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCDINTLVL_OFF_gc; timer->INTFLAGS = timer->INTFLAGS; if((timer == &FIRST_LAYER_TIMER) | (timer == &THIRD_LAYER_TIMER)) timer->CTRLD = TC_EVACT_PW_gc | TC_EVSEL_CH0_gc; else timer->CTRLD = TC_EVACT_PW_gc | TC_EVSEL_CH4_gc; } void init_event_system(PORT_t* _port) { if(_port == &ECHO_PORT1) { EVSYS.CH0MUX = EVSYS_CHMUX_PORTA_PIN0_gc; EVSYS.CH1MUX = EVSYS_CHMUX_PORTA_PIN1_gc; EVSYS.CH2MUX = EVSYS_CHMUX_PORTA_PIN2_gc; EVSYS.CH3MUX = EVSYS_CHMUX_PORTA_PIN3_gc; EVSYS.CH4MUX = EVSYS_CHMUX_PORTA_PIN4_gc; EVSYS.CH5MUX = EVSYS_CHMUX_PORTA_PIN5_gc; EVSYS.CH6MUX = EVSYS_CHMUX_PORTA_PIN6_gc; EVSYS.CH7MUX = EVSYS_CHMUX_PORTA_PIN7_gc; } if(_port == &ECHO_PORT2) { EVSYS.CH0MUX = EVSYS_CHMUX_PORTD_PIN0_gc; EVSYS.CH1MUX = EVSYS_CHMUX_PORTD_PIN1_gc; EVSYS.CH2MUX = EVSYS_CHMUX_PORTD_PIN2_gc; EVSYS.CH3MUX = EVSYS_CHMUX_PORTD_PIN3_gc; EVSYS.CH4MUX = EVSYS_CHMUX_PORTD_PIN4_gc; EVSYS.CH5MUX = EVSYS_CHMUX_PORTD_PIN5_gc; EVSYS.CH6MUX = EVSYS_CHMUX_PORTD_PIN6_gc; EVSYS.CH7MUX = EVSYS_CHMUX_PORTD_PIN7_gc; } } void init_ports() { //***************** Ultrasonic PORTs **************************************** /* TRIG PORT ...PORTB, PORTC */ PORTB.DIRCLR = 0xFF; PORTC.DIRCLR = 0xFF; PORTA.PIN0CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc; PORTA.PIN1CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc ; PORTA.PIN2CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTA.PIN3CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTA.PIN4CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTA.PIN5CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTA.PIN6CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTA.PIN7CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; PORTB.PIN0CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN1CTRL = PORT_OPC_PULLDOWN_gc ; PORTB.PIN2CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN3CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN4CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN5CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN6CTRL = PORT_OPC_PULLDOWN_gc; PORTB.PIN7CTRL = PORT_OPC_PULLDOWN_gc; } int main(void) { init_TC0_capture_input(&FIRST_LAYER_TIMER); init_TC0_capture_input(&SECOND_LAYER_TIMER); init_TC0_capture_input(&THIRD_LAYER_TIMER); init_TC0_capture_input(&FORTH_LAYER_TIMER); init_TC1_normal_mode(&TIME_OUT_TIMER); init_ports() } void startup_scan_process(bool _scanDirection) { myStepper.currentDirection = _scanDirection; for(uint8_t i = 0; i< myStepper.numberOfActivLayer; i++) { if(i >(uint8_t)FIRST_SONAR_LAYER) { init_event_system(&ECHO_PORT2); measure_distance(&sonarVector[i],_scanDirection); } else { init_event_system(&ECHO_PORT1); measure_distance(&sonarVector[i],_scanDirection); } } _delay_ms(100); transmitt_acqusition_block_data(sonarVector,myStepper.currentDirection); stepper_action(sonarVector,myStepper.currentDirection,false); _delay_ms(500); } void measure_distance(HCSR04* _sensorGroup ,uint8_t _scanDirection) { TIME_OUT_TIMER.CTRLA |= TC_CLKSEL_OFF_gc; for(uint8_t u = 0; u < _sensorGroup->sensorCount; u++) { TIME_OUT_TIMER.CNT = 0; _sensorGroup->trig(_sensorGroup->layerSensorGroup[u],_sensorGroup->sideNumber); TIME_OUT_TIMER.CTRLA |= TC_CLKSEL_DIV8_gc; while(!sonarEchoFlag & !sonarTimeoutFlag); TIME_OUT_TIMER.CTRLA=(TIME_OUT_TIMER.CTRLA & (~TC1_CLKSEL_gm)) | TC_CLKSEL_OFF_gc; if(sonarTimeoutFlag) { if(_sensorGroup->sideNumber == 2) { if(u == 3 ) { PORTF.OUTTGL = PIN0_bm; sonarTimeoutFlag = false; _sensorGroup->SonarRangUnion.measurmentPulse[u]=0; _sensorGroup->SonarAngleUnion.measurmentAngel[u] = _sensorGroup->sonarOrintation[u]; } } } else { if(sonarEchoFlag) { _sensorGroup->calculateDistance(_sensorGroup->layerSensorGroup[u],_sensorGroup); sonarEchoFlag = false; } } sonarTimeoutFlag = false; } } oid HCSR04::calculateDistance(uint8_t trigPin, HCSR04* _sensorGroup) { uint16_t pulseWidth = 0; uint8_t counter = 0; uint8_t _whichSide = _sensorGroup->sideNumber; switch(_whichSide) { case FIRST_SONAR_LAYER: switch(trigPin) { case SONAR1: pulseWidth = TC_GetCaptureA(&FIRST_LAYER_TIMER); counter = 0; break; case SONAR2: pulseWidth = TC_GetCaptureB(&FIRST_LAYER_TIMER); counter = 1; break; case SONAR3: pulseWidth = TC_GetCaptureC(&FIRST_LAYER_TIMER); counter = 2; break; case SONAR4: pulseWidth = TC_GetCaptureD(&FIRST_LAYER_TIMER); counter = 3; break; } break; case SECOND_SONAR_LAYER: switch(trigPin) { case SONAR5: pulseWidth = TC_GetCaptureA(&SECOND_LAYER_TIMER); counter = 0; break; case SONAR6: pulseWidth = TC_GetCaptureB(&SECOND_LAYER_TIMER); counter = 1; break; case SONAR7: pulseWidth = TC_GetCaptureC(&SECOND_LAYER_TIMER); counter = 2; break; case SONAR8: pulseWidth = TC_GetCaptureD(&SECOND_LAYER_TIMER); counter = 3; break; } break; case THIRD_SONAR_LAYER: switch(trigPin) { case SONAR1: pulseWidth = TC_GetCaptureA(&THIRD_LAYER_TIMER); counter = 0; break; case SONAR2: pulseWidth = TC_GetCaptureB(&THIRD_LAYER_TIMER); counter = 1; break; case SONAR3: pulseWidth = TC_GetCaptureC(&THIRD_LAYER_TIMER); counter = 2; break; case SONAR4: pulseWidth = TC_GetCaptureD(&THIRD_LAYER_TIMER); counter = 3; break; } break; case FOURTH_SONAR_LAYER: switch(trigPin) { case SONAR5: pulseWidth = TC_GetCaptureA(&FORTH_LAYER_TIMER); counter = 0; break; case SONAR6: pulseWidth = TC_GetCaptureB(&FORTH_LAYER_TIMER); counter = 1; break; case SONAR7: pulseWidth = TC_GetCaptureC(&FORTH_LAYER_TIMER); counter = 2; break; case SONAR8: pulseWidth = TC_GetCaptureD(&FORTH_LAYER_TIMER); counter = 3; break; } break; } _sensorGroup->SonarRangUnion.measurmentPulse[counter] = ((pulseWidth > this->sensorMaxRang )||((pulseWidth < this->sensorMinRang))?0:pulseWidth); _sensorGroup->SonarAngleUnion.measurmentAngel[counter] = _sensorGroup->sonarOrintation[counter];
the "measure_distance" function just round for each sensor and trig it for 12us and th MCU wait for TCC1 overFlow or for TCC0 input captuer, at the ISR i just rise a flage and disable the timer
//----------------------------------------------------- Timer TCCO Interrupt ISR------------------------------------- ISR(TCC0_CCA_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FIRST_LAYER_TIMER.INTCTRLB = TC_CCAINTLVL_OFF_gc ; } ISR(TCC0_CCB_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FIRST_LAYER_TIMER.INTCTRLB = TC_CCBINTLVL_OFF_gc ; } ISR(TCC0_CCC_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FIRST_LAYER_TIMER.INTCTRLB = TC_CCCINTLVL_OFF_gc ; } ISR(TCC0_CCD_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FIRST_LAYER_TIMER.INTCTRLB = TC_CCDINTLVL_OFF_gc ; } //----------------------------------------------------- Timer TCDO Interrupt ISR------------------------------------- ISR(TCD0_CCA_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; SECOND_LAYER_TIMER.INTCTRLB = TC_CCAINTLVL_OFF_gc ; } ISR(TCD0_CCB_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; SECOND_LAYER_TIMER.INTCTRLB = TC_CCBINTLVL_OFF_gc ; } ISR(TCD0_CCC_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; SECOND_LAYER_TIMER.INTCTRLB = TC_CCCINTLVL_OFF_gc ; } ISR(TCD0_CCD_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; SECOND_LAYER_TIMER.INTCTRLB = TC_CCDINTLVL_OFF_gc ; } //------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------- Timer TCEO Interrupt ISR------------------------------------- ISR(TCE0_CCA_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; THIRD_LAYER_TIMER.INTCTRLB = TC_CCAINTLVL_OFF_gc ; } ISR(TCE0_CCB_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; THIRD_LAYER_TIMER.INTCTRLB = TC_CCBINTLVL_OFF_gc ; } ISR(TCE0_CCC_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; THIRD_LAYER_TIMER.INTCTRLB = TC_CCCINTLVL_OFF_gc ; } ISR(TCE0_CCD_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; THIRD_LAYER_TIMER.INTCTRLB = TC_CCDINTLVL_OFF_gc ; } //----------------------------------------------------- Timer TCFO Interrupt ISR------------------------------------- ISR(TCF0_CCA_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FORTH_LAYER_TIMER.INTCTRLB = TC_CCAINTLVL_OFF_gc ; } ISR(TCF0_CCB_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FORTH_LAYER_TIMER.INTCTRLB = TC_CCBINTLVL_OFF_gc ; } ISR(TCF0_CCC_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FORTH_LAYER_TIMER.INTCTRLB = TC_CCCINTLVL_OFF_gc ; } ISR(TCF0_CCD_vect) { if(!sonarEchoFlag) sonarEchoFlag = true ; FORTH_LAYER_TIMER.INTCTRLB = TC_CCDINTLVL_OFF_gc ; } ISR(TCC1_OVF_vect) { sonarTimeoutFlag = true; TIME_OUT_TIMER.CTRLA=(TIME_OUT_TIMER.CTRLA & (~TC1_CLKSEL_gm)) | TC_CLKSEL_OFF_gc;}
i dont know if i can dynamically change the input (source) of event channel, i get some wrong data i some times get value from disconnected sensor, so i need your experince to ensure the validation of this approach