Hi there
My hardware is SAM3X8E, Arduino DUE board.
Im trying to use the pwm synchronous channel to control 3 pwm channels.
It works so far with two channels in agood way. Each time I try to add a third channel to it. It just dosent work I get like morge signals at the same pwm channel can any one please tell me what is the problem
This is my code
Code:
#include "asf.h"
#include "conf_board.h"
#include "SinewaveTable.h"
#include "Calculate_Sinus_Amplitude.h"
//--------------------------------------------------------------------------------------
//################################################################################################################
// **Global variables and macros****Global variables and macros****Global variables and macros**
//################################################################################################################
/** PWM frequency in Hz */
#define PWM_FREQUENCY 1000
/** PWM period value */
#define PERIOD_VALUE 4095 // 2^12 = 4096
/** Initial duty cycle value */
#define INIT_DUTY_VALUE 0
/** Initial dead time value */
#define INIT_DEAD_TIME 5
//Sine wave amplitude in Volt. max. 3,3. Bei einer späteren UART kommunikation soll eine Überprüfung bezüglich der maximalen und minmalen Spannung erfolgen
double p_desired_sine_amplitude_volt = 1.65 ; // Desierd sine wave amplitude in Volt
/** Maximum synchronous update period */
#define MAX_SYNC_UPDATE_PERIOD PWM_SCUP_UPR_Msk
/** Duty cycle buffer length for three channels */
#define DUTY_BUFFER_LENGTH 360//((PERIOD_VALUE - INIT_DUTY_VALUE + 1)*3)
/** Duty cycle buffer for PDC transfer */
uint16_t g_us_duty_buffer[DUTY_BUFFER_LENGTH];
//################################################################################################################
// **Function declartion****Function declartion****Function declartion****Function declartion***
//################################################################################################################
// Calculate the division factor for the amplitude of the sine wave signal
double CALCULATE_SINUS_AMPLITUDE_H ( double desired_sine_amplitude)
{
double max_voltage_amplitude= 3.3 ;
double Teilerfaktor = max_voltage_amplitude/desired_sine_amplitude ;
return Teilerfaktor ;
}
/**
* \brief Interrupt handler for the PWM controller.
*/
void PWM_Handler(void)
{
uint32_t pdc_status = pwm_get_interrupt_status(PWM);
if ((pdc_status & PWM_PDC_TX_END) == PWM_PDC_TX_END) { // PWM_PDC_TX_END is an indicator for the transfer interrupt
/* Set up the PDC controller */
g_pdc_tx_packet.ul_addr = (uint32_t) (&g_us_duty_buffer[0]);
g_pdc_tx_packet.ul_size = DUTY_BUFFER_LENGTH;
/* Initialize the PDC transfer */
pdc_tx_init(PDC_PWM, &g_pdc_tx_packet, 0);
/* Send the PWM value */
pdc_enable_transfer(PDC_PWM, PERIPH_PTCR_TXTEN);
}
}
// ******MAIN MENU*************************MAIN MENU*******************************MAIN MENU***************
int main(void)
{
uint32_t i;// for the loop which overlay the sine wave to the PWM signal
/* Initialize the SAM system */
sysclk_init();
board_init();
/* 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); // @ Arduino DUE Board = PWM 8
pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL); // @Arduino DUE Board = PWM 9
/*
* 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, // Clock B is not used
.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; // Channel Zero is the refrence channel for the pwm synchronisation. In that case it is PIN_PWM_LED0 this is PIN 8 in Arduino DUE
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);
sync_channel.channel = 0;
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
*/
// Buffer the Sine wave signal to the PWM signal
for (i = 0; i < (120);i++) {
g_us_duty_buffer[i * 3] = (sine[(i+80)%120]/ CALCULATE_SINUS_AMPLITUDE_H(p_desired_sine_amplitude_volt) ); // Signal 3 , 120 degree phase shift to signal 2
g_us_duty_buffer[i * 3 + 1] = (sine[(i+40)%120]/ CALCULATE_SINUS_AMPLITUDE_H(p_desired_sine_amplitude_volt)); // Signal 2, 120 degree phase shift to signal 1
g_us_duty_buffer[i * 3 + 2] = (sine[i]/ CALCULATE_SINUS_AMPLITUDE_H(p_desired_sine_amplitude_volt));// signal 1
}
/* 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);
pwm_channel_enable(PWM, 0);
//###########################################################################################################
// ******MAIN LOOP*************************MAIN LOOP*******************************MAIN LOOP***************
//###########################################################################################################
while (1) {
}
}