Ejemplo n.º 1
0
/**
 * \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;
		}
	}
}
Ejemplo n.º 2
0
/**
 * \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);
			
		}*/
	}
}