void tcdelay( int cycles) { int i; for(i = 0; i < cycles; i++) { while(0 == TC_GetOverflowFlag( &TCC0 )); TC_GetOverflowFlag( &TCC0 ); } return; }
int main( void ) { /* To change the duty cycle for the PWM for the LED control, use a variable to increase/decrease the * CCx registers once for each period */ int16_t pwm_delta = 300; // Add code to select a Single Slope PWM as Waveform Generation mode. // This is done by setting the WGM bits,in the CTRLB register for the TC. /* Add code to enable the CC channels we wish to use. Each channel must be separately enabled * by setting the corresponding CCxEN bits in the CTRLB register for the TC. * Code for enabling CCA is already added, but add code to enable CCB, CCC and CCD */ TCE0.CTRLB |= TC0_CCAEN_bm; //Insert code to enable CC for the other channels, B, C and D. /* The corresponding port pins MUST be ouput for the Waveform to be visible * on the pin. For TCE0 the corresponding port is PORTE, and pin 0 to 3 for * CC channel A to D */ PORTE.DIRSET = 0x0F; /* Note how the inverted signal is always controlled from the Port pin configuration in XMEGA * This can be used with all other peripherals connected to the pin to have inverted output. * Below is example code on how you can set inverted ouput on a pin using the Pin Control Register*/ //PORTE.PIN0CTRL &= ~PORT_INVEN_bm; /* Set a compare value for each compare channel, just as in task2. * The compare value decide the PWM duty cycle for the waveform. * * Code for CC channel A is added, add code for channel B, C, and D * with the compare value 3000 */ TC_SetCompareA(&TCE0, 3000); //Insert function calls to set the other compare values /* Using the TC_driver we set the Period and * start the timer with no prescaling */ TC_SetPeriod(&TCE0, 60000); TC0_ConfigClockSource(&TCE0, TC_CLKSEL_DIV1_gc); while(1) { /* The code check if the overflow flag is set, * if so it clears the flag and sets a new duty cycle for all * CC channels */ /* Check if overflow flag (OVFIF) is set, * clear flag and set a new duty cycle */ if(TC_GetOverflowFlag(&TCE0) != 0) { TC_ClearOverflowFlag(&TCE0); //Clear the IF by writing a logical 1 to the flag if(TCE0.CCA >= 59000) { //Some "random" values above 0 and below TOP is selected pwm_delta = -300; //for the PWM changes, and make the LED look ok. } else if(TCE0.CCA <= 5000) { pwm_delta = +300; } TCE0.CCABUF += pwm_delta; //Change the compare value to change duty cycle TCE0.CCBBUF += pwm_delta; TCE0.CCCBUF += pwm_delta; TCE0.CCDBUF += pwm_delta; } } }
int main( void ) { /* These variables are used to keep track og index 0 to 3) and the pattern to output * for the different indexes. */ volatile uint8_t pattern_index=0; volatile uint8_t new_pattern=0; /* To change the duty cycle for the PWM for the LED control, use a variable to increase/decrease the * CCx registers once for each period */ volatile int16_t pwm_delta = 300; /* To use the AWeX it need to be set in the correct mode. * For this task we will use the AWEX in Common Waveform Channel Mode (CWCM) and * Pattern Generation Mode (PGM) */ /*The CWCM mode is enabled by setting the CWCM bit the the AWEX.CTRL register */ //Add code here to enable CWCM AWEXE.CTRL |= AWEX_CWCM_bm; /*The PGM mode is enabled by setting the PGM bit the the AWEX.CTRL register */ //Add code here that enable PGM AWEXE.CTRL |= AWEX_PGM_bm; /* Just as for the timer in PWM mode, the ouput channels the AWEX will use must be enabled * In this task we will use all channels */ AWEXE.CTRL |= AWEX_DTICCDEN_bm | AWEX_DTICCCEN_bm | AWEX_DTICCBEN_bm | AWEX_DTICCAEN_bm; /* Just as for TC, the AWEX must set which pins it wish to override * (Remember the pin must still be output) */ AWEXE.OUTOVEN = 0x0F; //Initial override value. TCE0_init(); //init the timer while(1) { /* Check if switch is pressed */ if((SWITCHPORT.IN & 0x01) == 0) { //__delay_cycles(1000000); // About half a second @ default 2 MHz for XMEGA. _delay_ms(500); pattern_index++; pattern_index = (pattern_index & 0x03); //we only use 2 bits for the mask /* in PGM we use the DTI buffer register to set the pattern. The buffer values is copied * into the OUTOVEN register for each UPDATE condition, and this will set a new * pattern for the ouput. This ensure that for BLDC motor control for exmaple, the commutation sequence * can be synchronised with the UPDATE condition for the time */ new_pattern = GetNewPattern(pattern_index); AWEXE.DTLSBUF = new_pattern; } /* Check is overflow flag (OVFIF) is set, * clear flag and set a new duct cycle */ if(TC_GetOverflowFlag(&TCE0) != 0) { TC_ClearOverflowFlag(&TCE0); //Clear the IF by writing a logical 1 to the flag if(TCE0.CCA >= 59000){ //Some "random" values above 0 and below TOP is selected pwm_delta = -300; //for the PWM changes, and make the LED look ok. } else if(TCE0.CCA <= 5000){ pwm_delta = +300; } TCE0.CCABUF += pwm_delta; //Change the compare value to change duty cycle } } }