/************************************************************************** * Esempio di controllo PWM su ogni uscita o pin * * Realizzato da Giorgio Evangelista il 02/11/2020 * * Impostare la scheda Arduino/Genuino Zero (Native USB Port) *************************************************************************/ #include "gevino_opto_npn_io.h" #define PWM_speed 20000 // in hertz * 100 byte Speed; void setup() { SerialUSB.begin(115200); gevino_io_setup(); SetupTimer(); // Avvio il timer SerialUSB.println("Inizio"); } void loop () { Speed = 30; } void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 { // Check for overflow (OVF) interrupt if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) { // PWM static unsigned char pwm; if(++pwm>100) pwm = 0; if ( pwm < Speed ) setOut1; else resOut1; REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag } } // Set timer TC4 to call the TC4_Handler every second void SetupTimer() { // The code puts timer TC4 into match frequency (MFRQ) mode. In this mode the timer counts up to the value in the CC0 register before overflowing and resetting the timer back to 0. // I've set the generic clock 4 (GCLK4) to 48MHz and the timer prescaler to 1024. Therefore the timer's being clocked at 46.875kHz. // Using the formula: // timer frequency = generic clock frequency / (N * (CC0 + 1)) // where: // N = timer prescaler // CC0 = value in the CC0 register // ...we can calculate CC0 for a timer frequency of 1Hz. // So, // CC0 = (48MHz / 1024) - 1 = 46874 = 0xB71A (hex) // This will cause the timer to overflow every second. // Set up the generic clock (GCLK4) used to clock timers REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW GCLK_GENCTRL_GENEN | // Enable GCLK4 GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source GCLK_GENCTRL_ID(4); // Select GCLK4 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization // Feed GCLK4 to TC4 and TC5 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization REG_TC4_COUNT16_CC0 = 0xB71A / PWM_speed; // Set the TC4 CC0 register as the TOP value in match frequency mode (1 secondo) while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization //NVIC_DisableIRQ(TC4_IRQn); //NVIC_ClearPendingIRQ(TC4_IRQn); NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) REG_TC4_INTFLAG |= TC_INTFLAG_OVF; // Clear the interrupt flags REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 interrupts // REG_TC4_INTENCLR = TC_INTENCLR_OVF; // Disable TC4 interrupts REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode TC_CTRLA_ENABLE; // Enable TC4 while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization }