/** * \brief Application entry point for PWM PDC example. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint32_t i; uint8_t uc_key; uint8_t c_numkey; /* Initialize the SAM system */ sysclk_init(); board_init(); /* Configure the console uart for debug infomation */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Enable PWM peripheral clock */ pmc_enable_periph_clk(ID_PWM); /* Disable PWM channel of LED1 and LED0 */ pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL); pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL); /* * In PWM synchronisation mode the channel0 is used as reference channel, * so it is necessary to disable, configure and enable it. */ if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) { pwm_channel_disable(PWM, 0); } /* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */ pwm_clock_t clock_setting = { .ul_clka = PWM_FREQUENCY * PERIOD_VALUE, .ul_clkb = 0, .ul_mck = sysclk_get_cpu_hz() }; pwm_init(PWM, &clock_setting); /* Initialize PWM channels outputs */ pwm_output_t channel_output = { /* Disable override PWMH outputs */ .b_override_pwmh = false, /* Disable override PWML outputs */ .b_override_pwml = false, /* Set override PWMH output level as HIGH */ .override_level_pwmh = PWM_HIGH, /* Set override PWML output level as LOW */ .override_level_pwml = PWM_LOW }; /* Initialize PWM synchronous channels */ pwm_channel_t sync_channel = { /* Use PWM clock A as source clock */ .ul_prescaler = PWM_CMR_CPRE_CLKA, /* Period value of output waveform */ .ul_period = PERIOD_VALUE, /* Duty cycle value of output waveform */ .ul_duty = INIT_DUTY_VALUE, /* Set it as a synchronous channel */ .b_sync_ch = true, /* Enable dead-time generator */ .b_deadtime_generator = true, /* Dead-time value for PWMH output */ .us_deadtime_pwmh = INIT_DEAD_TIME, /* Dead-time value for PWML output */ .us_deadtime_pwml = INIT_DEAD_TIME, /* Disable override PWMH outputs */ .output_selection.b_override_pwmh = false, /* Disable override PWML outputs */ .output_selection.b_override_pwml = false }; /* * In PWM synchronisation mode the channel0 is used as reference channel, * so it is necessary to disable, configure and enable it. */ if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) { sync_channel.channel = 0; pwm_channel_init(PWM, &sync_channel); } /* Initialize PWM channel of LED1 */ sync_channel.channel = PIN_PWM_LED1_CHANNEL; pwm_channel_init(PWM, &sync_channel); /* Initialize PWM channel of LED2 */ sync_channel.channel = PIN_PWM_LED0_CHANNEL; pwm_channel_init(PWM, &sync_channel); /* * Initialize PWM synchronous channels * Synchronous Update Mode: Automatic update duty cycle value by the PDC * and automatic update of synchronous channels. The update occurs when * the Update Period elapses (MODE 2). * Synchronous Update Period = MAX_SYNC_UPDATE_PERIOD. */ pwm_sync_init(PWM, PWM_SYNC_UPDATE_MODE_2, MAX_SYNC_UPDATE_PERIOD); /* * Request PDC transfer as soon as the synchronous update period elapses * (comparison unit is ignored). */ pwm_pdc_set_request_mode(PWM, PWM_PDC_UPDATE_PERIOD_ELAPSED, (1 << 0)); /* Configure interrupt for PDC transfer */ NVIC_DisableIRQ(PWM_IRQn); NVIC_ClearPendingIRQ(PWM_IRQn); NVIC_SetPriority(PWM_IRQn, 0); NVIC_EnableIRQ(PWM_IRQn); pwm_pdc_enable_interrupt(PWM, PWM_PDC_TX_END); /* Fill duty cycle buffer for channel #0 and #1 */ /* * For PWM channel 0 and 1, duty cycle ranges from * MIN_DUTY_CYCLE to MAX_DUTY_CYCLE */ for (i = 0; i < (DUTY_BUFFER_LENGTH / 3); i++) { g_us_duty_buffer[i * 3] = (i + INIT_DUTY_VALUE); g_us_duty_buffer[i * 3 + 1] = (i + INIT_DUTY_VALUE); g_us_duty_buffer[i * 3 + 2] = (i + INIT_DUTY_VALUE); } /* Configure the PDC transfer packet and enable PDC transfer */ g_pdc_tx_packet.ul_addr = (uint32_t) (&(g_us_duty_buffer[0])); g_pdc_tx_packet.ul_size = DUTY_BUFFER_LENGTH; pdc_tx_init(PDC_PWM, &g_pdc_tx_packet, 0); pdc_enable_transfer(PDC_PWM, PERIPH_PTCR_TXTEN); /* Enable all synchronous channels by enabling channel 0 */ /* * In PWM synchronisation mode the channel0 is used as reference channel, * so it is necessary to disable, configure and enable it. */ if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) { pwm_channel_enable(PWM, 0); } pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL); pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL); while (1) { display_menu(); while (uart_read(CONSOLE_UART, &uc_key)); switch (uc_key) { case 'u': case 'U': printf("Input update period must be between 0 and %d.\r\n", (int)MAX_SYNC_UPDATE_PERIOD); c_numkey = get_num_value(); if (c_numkey <= MAX_SYNC_UPDATE_PERIOD) { /* Set new synchronous update period value */ pwm_sync_change_period(PWM, c_numkey); printf("Synchronous update period has been changed to %d.\r\n", (int)c_numkey); } else { printf("Wrong value, expected value must be one of 0 to %d!\r\n", (int)MAX_SYNC_UPDATE_PERIOD); } break; case 'd': case 'D': printf("Input dead time for channel #0 must be between %d and %d.\r\n", INIT_DUTY_VALUE, PERIOD_VALUE); c_numkey = get_num_value(); if (c_numkey <= PERIOD_VALUE) { /* Set new dead time value for channel 0 */ pwm_channel_update_dead_time(PWM, &sync_channel, c_numkey, c_numkey); /* Update all synchronous channels */ pwm_sync_unlock_update(PWM); printf("Dead time has been changed to %d.\r\n", (int)c_numkey); } else { printf("Wrong value, expected value must be one of %d to %d!\r\n", INIT_DUTY_VALUE, PERIOD_VALUE); } break; case 'o': case 'O': if (channel_output.b_override_pwmh && channel_output.b_override_pwml) { /* Disable override outputs of channel 0 synchronously */ channel_output.b_override_pwmh = false; channel_output.b_override_pwml = false; pwm_channel_update_output(PWM, &sync_channel, &channel_output, true); puts("PWM Channel #0 output override has been disabled.\r\n"); } else { /* Enable override outputs of channel 0 synchronously */ channel_output.b_override_pwmh = true; channel_output.b_override_pwml = true; pwm_channel_update_output(PWM, &sync_channel, &channel_output, true); puts("PWM Channel #0 output has been overridden.\r\n"); } break; default: puts("Unknown input!\r\n"); break; } } }
/** * \brief Application entry point for PWM PDC example. * * \return Unused (ANSI-C compatibility). */ int main(void) { /* Initialize the SAM system */ sysclk_init(); board_init(); /* Configure the console uart for debug infomation */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Enable PWM peripheral clock */ pmc_enable_periph_clk(ID_PWM); /*A Disable PWM channels - Register: PWM_DIS (PWM Disable) - Kanal 0: Motor1_X - Kanal 1: Motor1_Y - Kanal 2: Motor1_Z - Kanal 3: Referenzsignals */ pwm_channel_disable(PWM, PWM_CHANNEL_0); pwm_channel_disable(PWM, PWM_CHANNEL_1); pwm_channel_disable(PWM, PWM_CHANNEL_2); pwm_channel_disable(PWM, PWM_CHANNEL_3); /*A PWM-Leitungen (C.2 - C.9) im Prozessor vom PIO-Controller trennen und auf peripheral Funktion B setzen */ for (int pinId = 2; pinId <= 9; pinId++) { pio_set_peripheral(PIOC, PIO_TYPE_PIO_PERIPH_B, (1u << pinId)); } /*A Clock einstellen - Set PWM clock A for all channels, clock B not used */ pwm_clock_t clock_setting = { .ul_clka = PWM_FREQUENCY * PERIOD_VALUE, .ul_clkb = 0, .ul_mck = sysclk_get_cpu_hz() // diese Funktion gibt 84 Mhz zurück! }; pwm_init(PWM, &clock_setting); /*A Kanäle 0,1,2 als synchron festlegen */ // zunächst die generellen Eigenschaften der synchronen Channels initialisieren pwm_channel_t sync_channel = { /* die Motor Kanäle sollen alle Center aligned sein */ .alignment = PWM_ALIGN_CENTER, /* die Motor Kanäle sollen mit Low Polarität starten */ .polarity = PWM_LOW, /* Alle Motor Kanäle sollen Clock A verwenden, da sie mit doppelter Basisfrequenz getaktet werden müssen wegen Center aligned */ .ul_prescaler = PWM_CMR_CPRE_CLKA, /* Periode einstellen */ .ul_period = PERIOD_VALUE, /* Duty cycle initial setzen */ .ul_duty = INIT_DUTY_VALUE, /* der channel soll synchron sein */ .b_sync_ch = true, .b_deadtime_generator = true, .us_deadtime_pwmh = 1, .us_deadtime_pwml = 1 }; /* als erstes dann den Channel 0 initialisieren, indem nur das Channel Attribut in der Struktur von oben neu gesetzt wird, der REst bleibt gleich... */ sync_channel.channel = PWM_CHANNEL_0; pwm_channel_init(PWM, &sync_channel); // das gleiche dann mit den beiden anderen zu synchronisierenden Channels sync_channel.channel = PWM_CHANNEL_1; pwm_channel_init(PWM, &sync_channel); sync_channel.channel = PWM_CHANNEL_2; pwm_channel_init(PWM, &sync_channel); /* * Initialize PWM synchronous channels * Synchronous Update Mode: Automatic update duty cycle value by the PDC * and automatic update of synchronous channels. The update occurs when * the Update Period elapses (MODE 2 --> Vorsicht vor Verwirrung: dies entspricht der "Methode 3" aus dem Datasheet!). * Synchronous Update Period = MAX_SYNC_UPDATE_PERIOD. */ pwm_sync_init(PWM, PWM_SYNC_UPDATE_MODE_2, MAX_SYNC_UPDATE_PERIOD); /* * Request PDC transfer as soon as the synchronous update period elapses */ pwm_pdc_set_request_mode(PWM, PWM_PDC_UPDATE_PERIOD_ELAPSED, (1 << 0)); /* Aktiviere alle synchronen channel durch aktivieren von channel 0, channel 1 und 2 werden automatisch synchron mit gestartet zusätzlich noch den Refernzchannel "synchron" mitstarten die ASF funktion channel_enable erlaubt leider nur die Übergabe eines Kanals, also müssen wir hier wohl mit direktem Zugriff auf das Register arbeiten */ pwm_channel_enable(PWM, PWM_CHANNEL_0); // ref channel funktioniert noch nicht, muss noch debugged werden pwm_channel_enable(PWM, PWM_CHANNEL_3); pmc_enable_periph_clk(ID_PIOA); pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE); int angle = 0; int up = 1; float sinus = 0; float a; while (1) { pio_set(PIOA, PIO_PA23); for (int i = 0; i < 1000; i++) { sinus = sin(0.343543); a = sinus; } pio_clear(PIOA, PIO_PA23); delay_us(4); /*display_menu(); uint32_t angle = get_num_value(); struct SV pwm = get_vector_for_angle(angle); SVPWM(pwm.u, pwm.v, pwm.w); printf("The angle is %i degrees.", angle); for (int i = 0; i <= 360; i++) { struct SV pwm = get_vector_for_angle(i); SVPWM(pwm.u, pwm.v, pwm.w); printf("%i Grad\r\n", i); delay_ms(40); } for (int i = 360; i >= 0; i--) { struct SV pwm = get_vector_for_angle(i); SVPWM(pwm.u, pwm.v, pwm.w); printf("%i Grad\r\n", i); delay_ms(40); }*/ } }