示例#1
0
/************************************************************************
Configuration of the Pulse Width Modulation (PWM).
************************************************************************/
void PWMInit(void){
	pmc_enable_periph_clk(ID_PWM);
	pwm_channel_disable(PWM, PWM_CHANNEL_3);
	pwm_channel_disable(PWM, PWM_CHANNEL_2);
	
	pwm_clock_t clock_setting = {
		.ul_clka = 50 * 19999,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);
	
	InitPIN40();
	InitPIN38();
}

/************************************************************************
Initiation of digital pin 40 on the Arduino Due board for PWM.
************************************************************************/
void InitPIN40(void)
{
	PWMPin40.channel = PWM_CHANNEL_3;
	PWMPin40.ul_prescaler = PWM_CMR_CPRE_CLKA;
	PWMPin40.ul_duty = 0;
	PWMPin40.ul_period = 19999;
	pwm_channel_init(PWM, &PWMPin40);
	pio_set_peripheral(PIOC, PIO_PERIPH_B, PIO_PC8B_PWML3);
	pwm_channel_enable(PWM, PWM_CHANNEL_3);
}
示例#2
0
/************************************************************************
Initiation of digital pin 40 on the Arduino Due board for PWM.
************************************************************************/
void InitPIN38(void){
	PWMPin38.channel = PWM_CHANNEL_2;
	PWMPin38.ul_prescaler = PWM_CMR_CPRE_CLKA;
	PWMPin38.ul_duty = 0;
	PWMPin38.ul_period = 19999;
	pwm_channel_init(PWM, &PWMPin38);
	pio_set_peripheral(PIOC, PIO_PERIPH_B, PIO_PC6B_PWML2);
	pwm_channel_enable(PWM, PWM_CHANNEL_2);
}
示例#3
0
/* Funktionen initierar PWM-signalen */
void pwm_setup(void)
{
	pmc_enable_periph_clk(ID_PWM);
	pwm_channel_disable(PWM, PWM_CHANNEL);
	
	pwm_clock_t clock_setting = {
		.ul_clka = PWM_FREQUENCY * PWM_PERIOD,
		.ul_clkb = 0,
		.ul_mck = SYS_CLOCK
	};
	
	pwm_init(PWM, &clock_setting);
	
	pwm_channel_instance.alignment = PWM_ALIGN_LEFT;
	pwm_channel_instance.polarity = PWM_LOW;
	pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
	pwm_channel_instance.ul_period = PWM_PERIOD;
	pwm_channel_instance.ul_duty = PWM_INIT_DUTY_CYCLE;
	pwm_channel_instance.channel = PWM_CHANNEL;
	
	pwm_channel_init(PWM, &pwm_channel_instance);
	pio_set_peripheral(PWM_PIO, PWM_PERIPHERAL, PWM_PIN);
	pwm_channel_enable(PWM, PWM_CHANNEL);
}


/* Funktionen uppdaterar PWM-signalens duty-cycle */
void update_pwm(int ul_duty)
{
	// Kontrollerar så att angiven duty-cycle befinner sig inom rätt område (0-1000).
	if(ul_duty < PWM_MIN_DUTY_CYCLE)
	{
		pwm_channel_update_duty(PWM, &pwm_channel_instance, PWM_MIN_DUTY_CYCLE);
	}
	else if(ul_duty > PWM_MAX_DUTY_CYCLE)
	{
		pwm_channel_update_duty(PWM, &pwm_channel_instance, PWM_MAX_DUTY_CYCLE);
	}
	else
	{
		pwm_channel_update_duty(PWM, &pwm_channel_instance, ul_duty);
	}
}


/* Funktionen initierar motor-shielden */
void motor_shield_setup(void)
{
	ioport_set_pin_dir(PIO_PD8_IDX, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIO_PD8_IDX, IOPORT_PIN_LEVEL_HIGH);
	
	ioport_set_pin_dir(PIO_PC21_IDX, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIO_PC21_IDX, IOPORT_PIN_LEVEL_LOW);
}
示例#4
0
int
up_pwm_servo_init(uint32_t channel_mask)
{
	/* do basic timer initialisation first */
	for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) {
		if (pwm_timers[i].base != 0)
			pwm_timer_init(i);
	}

	/* now init channels */
	for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) {
		/* don't do init for disabled channels; this leaves the pin configs alone */
		if (((1 << i) & channel_mask) && (pwm_channels[i].timer_channel != 0))
			pwm_channel_init(i);
	}

	return OK;
}
示例#5
0
int
pwm_servo_init(const struct pwm_servo_config *config)
{
	/* save a pointer to the configuration */
	cfg = config;

	/* do basic timer initialisation first */
	for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) {
		if (cfg->timers[i].base != 0)
			pwm_timer_init(i);
	}

	/* now init channels */
	for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) {
		if (cfg->channels[i].gpio != 0)
			pwm_channel_init(i);
	}

	/* register the device */
	return register_driver("/dev/pwm_servo", &pwm_servo_fops, 0666, NULL);
}
示例#6
0
int PWM_prog(void) {
	board_init();
	unsigned int channel_id = 3;
	avr32_pwm_channel_t pwm_channel = { .ccnt = 0 }; // One	channel config.

	gpio_enable_module_pin(EXAMPLE_PWM_PIN,
	EXAMPLE_PWM_FUNCTION);
	pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_256; //	Channel prescaler.

	pwm_channel.cdty = 1; // Channel duty cycle, should be <	CPRD.

	pwm_channel.cprd = 20; // Channel period.
	// With these settings, the output waveform period will be :
	// (115200/256)/20 == 22.5Hz == (MCK/prescaler)/period, with	MCK == 115200Hz,

	// prescaler == 256, period == 20.
	pwm_channel_init(channel_id, &pwm_channel); // Set channel	configuration to channel 3.
	pwm_start_channels(1 << channel_id); // Start channel 3.
	while(1){
	}
	return 0;
}
void init_PWM(int velocidad, int direccion){
	int auxiliar;
	switch(velocidad){
		case 9:
			auxiliar = 2;
			break;
		case 8:
			auxiliar = 4;
			break;
		case 7:
			auxiliar = 6;
			break;
		case 6:
			auxiliar = 8;
			break;
		case 5:
			auxiliar = 10;
			break;
		case 4:
			auxiliar = 12;
			break;
		case 3:
			auxiliar = 14;
			break;
		case 2:
			auxiliar = 16;
			break;
		case 1:
			auxiliar = 18;
			break;
	}//SWITCH
	pwm_opt_t pwm_opt =
	{
		.diva = AVR32_PWM_DIVA_CLK_OFF,
		.divb = AVR32_PWM_DIVB_CLK_OFF,
		.prea = AVR32_PWM_PREA_MCK,
		.preb = AVR32_PWM_PREB_MCK
	};
	
	avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };
		pwm_channel.cdty = auxiliar; /* Channel duty cycle, should be < CPRD. */
		pwm_channel.cprd = 20; /* Channel period. */
		pwm_channel.cupd = 0; /* Channel update is not used here. */
		pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; /* Channel mode. */
		pwm_channel.CMR.cpol = PWM_POLARITY_LOW;      /* Channel polarity. */
		pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;        /* Not used the first time. */
		pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_256; /* Channel prescaler. */
		
		gpio_enable_module_pin(PWM_PIN_3, PWM_PIN_Function);
		gpio_enable_module_pin(PWM_PIN_1, PWM_PIN_Function);
		pwm_init(&pwm_opt);
		if(direccion == 1){//FORWARD
			pwm_channel_init(PWM_ID_3, &pwm_channel);
			pwm_start_channels(1 << PWM_ID_3);

		}
		if(direccion == 0){//REVERSE
			pwm_channel_init(PWM_ID_1, &pwm_channel);
			pwm_start_channels(1 << PWM_ID_1);
		}
}
void update_PWM(int velocidad, int direccion){
	int auxiliar;
	switch(velocidad){
		case 9:
		auxiliar = 2;
		break;
		case 8:
		auxiliar = 4;
		break;
		case 7:
		auxiliar = 6;
		break;
		case 6:
		auxiliar = 8;
		break;
		case 5:
		auxiliar = 10;
		break;
		case 4:
		auxiliar = 12;
		break;
		case 3:
		auxiliar = 14;
		break;
		case 2:
		auxiliar = 16;
		break;
		case 1:
		auxiliar = 18;
		break;
	}//SWITCH
		avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };
		pwm_channel.cdty = auxiliar; /* Channel duty cycle, should be < CPRD. */
		pwm_channel.cprd = 20; /* Channel period. */
		pwm_channel.cupd = 0; /* Channel update is not used here. */
		pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; /* Channel mode. */
		pwm_channel.CMR.cpol = PWM_POLARITY_LOW;      /* Channel polarity. */
		pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;        /* Not used the first time. */
		pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_256; /* Channel prescaler. */
	
	if(direccion == 1){//FORWARD
		pwm_stop_channels(1<<PWM_ID_1);
		pwm_stop_channels(1<<PWM_ID_3);
		pwm_channel_init(PWM_ID_3, &pwm_channel);
		pwm_start_channels(1 << PWM_ID_3);
		
	}
	if(direccion == 0){//REVERSE
		pwm_stop_channels(1<<PWM_ID_1);
		pwm_stop_channels(1<<PWM_ID_3);
		pwm_channel_init(PWM_ID_1, &pwm_channel);
		pwm_start_channels(1 << PWM_ID_1);
	}
	bandera = 0;
}
static void handler_interrupt(void){
	if (gpio_get_pin_interrupt_flag(GPIO_JOYSTICK_UP)){
		direccion = 1;
		gpio_clear_pin_interrupt_flag(GPIO_JOYSTICK_UP);
	}
	if (gpio_get_pin_interrupt_flag(GPIO_JOYSTICK_DOWN)){
		direccion = 0;
		gpio_clear_pin_interrupt_flag(GPIO_JOYSTICK_DOWN);
	}
	bandera = 1;
}
void init_INTC(void){
	gpio_enable_pin_interrupt(GPIO_JOYSTICK_UP , GPIO_FALLING_EDGE);
	gpio_enable_pin_interrupt(GPIO_JOYSTICK_DOWN , GPIO_FALLING_EDGE);
	Disable_global_interrupt();
	INTC_init_interrupts();
	  INTC_register_interrupt( &handler_interrupt, AVR32_GPIO_IRQ_0 + (GPIO_JOYSTICK_UP/8), AVR32_INTC_INT1);
	  INTC_register_interrupt( &handler_interrupt, AVR32_GPIO_IRQ_0 + (GPIO_JOYSTICK_DOWN/8), AVR32_INTC_INT1);
	Enable_global_interrupt();
}
示例#8
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;
		}
	}
}
示例#9
0
/**
 * \brief Configure to trigger ADC by PWM Event Line.
 */
static void configure_pwm_trigger(void)
{
	/* PWM frequency in Hz. */
#define PWM_FREQUENCY               2
	/* Maximum duty cycle value. */
#define MAX_DUTY_CYCLE              1000

	/* Enable PWMC peripheral clock. */
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channel 0. */
	pwm_channel_disable(PWM, PWM_CHANNEL_0);

	gpio_configure_pin(PIN_PWMC_PWMH0_TRIG, PIN_PWMC_PWMH0_TRIG_FLAG);

	/* Set clock A to run at PWM_FREQUENCY * MAX_DUTY_CYCLE (clock B is not used). */
	pwm_clock_t pwm_clock_setting = {
		.ul_clka = PWM_FREQUENCY * MAX_DUTY_CYCLE,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &pwm_clock_setting);

	/* Configure PWMC for channel 0 (left-aligned). */
		pwm_channel_t pwm_trigger_channel = {
			.channel = PWM_CHANNEL_0,
			.alignment = PWM_ALIGN_LEFT,
			.polarity = PWM_LOW,
		.ul_prescaler = PWM_CMR_CPRE_CLKA,
		.ul_period = MAX_DUTY_CYCLE,
		.ul_duty = MAX_DUTY_CYCLE / 2
	};
	pwm_channel_init(PWM, &pwm_trigger_channel);

	pwm_cmp_t pwm_comparison_setting = {
		.unit = PWM_CMP_UNIT_0,
		.b_enable = true,
		.ul_value = MAX_DUTY_CYCLE / 2,
		.b_pulse_on_line_0 = true
	};
	pwm_cmp_init(PWM, &pwm_comparison_setting);


	/* Enable PWM channel 0. */
	pwm_channel_enable(PWM, PWM_CHANNEL_0);
	/* Set PWM Event Line 0 trigger. */
#if SAM3S || SAM3XA || SAM4S
	adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0, 0);
#elif SAM3U
#ifdef ADC_12B
	adc12b_configure_trigger(ADC12B, ADC12B_TRIG_PWM_EVENT_LINE_0);
#else
	adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0);
#endif
#endif
}
#endif

/**
 * \brief Read converted data through PDC channel.
 *
 * \param p_adc The pointer of adc peripheral.
 * \param p_s_buffer The destination buffer.
 * \param ul_size The size of the buffer.
 */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) {
		p_adc->ADC_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC_RCR = ul_size;
		p_adc->ADC_PTCR = ADC_PTCR_RXTEN;

		return 1;
	} else { /* Check if the second PDC bank is free. */
		if (p_adc->ADC_RNCR == 0) {
			p_adc->ADC_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#elif SAM3U
#ifdef ADC_12B
static uint32_t adc12_read_buffer(Adc12b * p_adc, uint16_t * p_s_buffer,
		uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC12B_RCR == 0) && (p_adc->ADC12B_RNCR == 0)) {
		p_adc->ADC12B_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC12B_RCR = ul_size;
		p_adc->ADC12B_PTCR = ADC12B_PTCR_RXTEN;

		return 1;
	} else {	/* Check if the second PDC bank is free. */
		if (p_adc->ADC12B_RNCR == 0) {
			p_adc->ADC12B_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC12B_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#else
static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) {
		p_adc->ADC_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC_RCR = ul_size;
		p_adc->ADC_PTCR = ADC_PTCR_RXTEN;

		return 1;
	} else {	/* Check if the second PDC bank is free. */
		if (p_adc->ADC_RNCR == 0) {
			p_adc->ADC_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#endif
#endif

/**
 * \brief Start ADC sample.
 * Initialize ADC, set clock and timing, and set ADC to given mode.
 */
static void start_adc(void)
{
	/* Enable peripheral clock. */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	uint32_t i;
	pmc_enable_periph_clk(ID_ADC);
#elif SAM3U
#ifdef ADC_12B
	pmc_enable_periph_clk(ID_ADC12B);
#else
	pmc_enable_periph_clk(ID_ADC);
#endif
#endif

	/* Initialize ADC. */
	/*
	 * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 )
	 * For example, MCK = 64MHZ, PRESCAL = 4, then:
	 * ADCClock = 64 / ((4+1) * 2) = 6.4MHz;
	 */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Formula:
	 *     Startup  Time = startup value / ADCClock
	 *     Startup time = 64 / 6.4MHz = 10 us
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), 6400000, ADC_STARTUP_TIME_4);
#elif SAM3U
#ifdef ADC_12B
	/* Formula:
	 *     Startup  Time = (startup value + 1) * 8 / ADCClock
	 *     Startup time = (7 + 1) * 8 / 6.4MHz = 10 us
	 */
	adc12b_init(ADC12B, sysclk_get_cpu_hz(), 6400000, STARTUP_TIME, OFF_MODE_STARTUP_TIME);
#else
	/* Formula:
	 *     Startup  Time = (startup value + 1) * 8 / ADCClock
	 *     Startup time = (3 + 1) * 8 / 3.2MHz = 10 us
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), 3200000, STARTUP_TIME);
#endif
#endif

	memset((void *)&g_adc_sample_data, 0, sizeof(g_adc_sample_data));

	/* Set ADC timing. */
#if SAM3S ||  SAM3XA || SAM4S
	/* Formula:
	 *     Transfer Time = (TRANSFER * 2 + 3) / ADCClock
	 *     Tracking Time = (TRACKTIM + 1) / ADCClock
	 *     Settling Time = settling value / ADCClock
	 *
	 *     Transfer Time = (1 * 2 + 3) / 6.4MHz = 781 ns
	 *     Tracking Time = (1 + 1) / 6.4MHz = 312 ns
	 *     Settling Time = 3 / 6.4MHz = 469 ns
	 */
	adc_configure_timing(ADC, TRACKING_TIME, ADC_SETTLING_TIME_3, TRANSFER_PERIOD);
#elif  SAM3N || SAM4C
	adc_configure_timing(ADC, TRACKING_TIME);
#elif SAM3U
	/* Formula:
	 *     Sample & Hold Time = SHTIM/ADCClock
	 *
	 *     Sample & Hold Time = 6 / 6.4 = 938 ns
	 */
#ifdef ADC_12B
	adc12b_configure_timing(ADC12B, SAMPLE_HOLD_TIME);
#else
	adc_configure_timing(ADC, SAMPLE_HOLD_TIME);
#endif
#endif

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Enable channel number tag. */
	adc_enable_tag(ADC);
	/* Enable/disable sequencer. */
	if (g_adc_test_mode.uc_sequence_en) {
		/* Set user defined channel sequence. */
		adc_configure_sequence(ADC, ch_list, 2);

		/* Enable sequencer. */
		adc_start_sequencer(ADC);

		/* Enable channels. */
		for (i = 0; i < 2; i++) {
			adc_enable_channel(ADC, (enum adc_channel_num_t)i);
		}
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ch_list[0];
		g_adc_sample_data.uc_ch_num[1] = ch_list[1];
	} else {
		/* Disable sequencer. */
		adc_stop_sequencer(ADC);

		/* Enable channels. */
		adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER);
#if SAM3S || SAM3XA || SAM4S || SAM4C
		adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR);
#endif
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;
#if SAM3S || SAM3XA || SAM4S || SAM4C
		g_adc_sample_data.uc_ch_num[1] = ADC_TEMPERATURE_SENSOR;
#else
		g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER;
#endif
	}
#elif SAM3U
#ifdef ADC_12B
	adc12b_enable_channel(ADC12B, ADC_CHANNEL_POTENTIOMETER);
#else
	adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER);
#endif
	g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;
	g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER;
#endif

#if SAM3S ||  SAM3XA || SAM4S || SAM4C
	/* Enable the temperature sensor. */
	adc_enable_ts(ADC);
#endif
	/* Set gain and offset (only single ended mode used here). */
#if SAM3S || SAM3XA || SAM4S
	adc_disable_anch(ADC); /* Disable analog change. */
#endif
	if (g_adc_test_mode.uc_gain_en) {
#if SAM3S || SAM3XA || SAM4S
		adc_enable_anch(ADC);
		/* gain = 2 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_2);
#elif SAM3U
#ifdef ADC_12B
		adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_2);
#endif
#endif
	} else {
#if SAM3S || SAM3XA || SAM4S
		/* gain = 1 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_0);
#elif SAM3U
#ifdef ADC_12B
		adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_0);
#endif
#endif
	}

	if (g_adc_test_mode.uc_offset_en) {
#if SAM3S || SAM3XA || SAM4S
		adc_enable_anch(ADC);
		adc_enable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
#elif 	SAM3U
#ifdef ADC_12B
		adc12b_enable_input_offset(ADC12B);
#endif
#endif
	} else {
#if SAM3S || SAM3XA || SAM4S
		adc_disable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
#elif 	SAM3U
#ifdef ADC_12B
		adc12b_disable_input_offset(ADC12B);
#endif
#endif
	}
	/* Set Auto Calibration Mode. */
#if  SAM3S8 || SAM3SD8 || SAM4S
	if (g_adc_test_mode.uc_auto_calib_en) {
		adc_set_calibmode(ADC);
		while (1) {
			if ((adc_get_status(ADC) & ADC_ISR_EOCAL) ==
					ADC_ISR_EOCAL)
				break;
		}
	}
#endif

#if SAM3S8 || SAM4S || SAM3N || SAM3SD8
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc_configure_power_save(ADC, 1, 0);
	} else {
		adc_configure_power_save(ADC, 0, 0);;
	}
#elif SAM3U || SAM4C
#ifdef ADC_12B
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc12b_configure_power_save(ADC12B, 1, 0);
	} else {
		adc12b_configure_power_save(ADC12B, 0, 0);;
	}

#else
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc_configure_power_save(ADC, 1);
	} else {
		adc_configure_power_save(ADC, 0);;
	}
#endif
#endif

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_DRDY);
	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC_IRQn);
#elif SAM3U
#ifdef ADC_12B
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc12_read_buffer(ADC12B, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc12b_enable_interrupt(ADC12B, ADC12B_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc12b_enable_interrupt(ADC12B, ADC12B_IER_DRDY);

	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC12B_IRQn);
#else
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_DRDY);

	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC_IRQn);
#endif
#endif
	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
		adc_configure_trigger(ADC, ADC_TRIG_SW, 0);	/* Disable hardware trigger. */
#elif SAM3U
#ifdef ADC_12B
		adc12b_configure_trigger(ADC12B, ADC12B_TRIG_SW);
#else
		adc_configure_trigger(ADC, ADC_TRIG_SW);
#endif
#endif
		break;

	case TRIGGER_MODE_ADTRG:
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT, 0);
#elif SAM3U
#ifdef ADC_12B
		gpio_configure_pin(PINS_ADC12B_TRIG, PINS_ADC12B_TRIG_FLAG);
		adc12b_configure_trigger(ADC12B, ADC12B_TRIG_EXT);
#else
		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT);
#endif
#endif
		break;

	case TRIGGER_MODE_TIMER:
		configure_time_trigger();
		break;
#if SAM3S || SAM3U || SAM3XA || SAM4S
	case TRIGGER_MODE_PWM:
		configure_pwm_trigger();
		break;
#endif
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	case TRIGGER_MODE_FREERUN:
		adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
		break;
#endif
	default:
		break;
	}
}

/**
 * \brief Systick handler.
 */
void SysTick_Handler(void)
{
	gs_ul_ms_ticks++;
}

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
/**
 * \brief Interrupt handler for the ADC.
 */
void ADC_Handler(void)
{
	uint32_t i;
	uint32_t ul_temp;
	uint8_t uc_ch_num;

	/* With PDC transfer */
	if (g_adc_test_mode.uc_pdc_en) {
		if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) ==
				ADC_ISR_RXBUFF) {
			g_adc_sample_data.us_done = ADC_DONE_MASK;
			adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
			/* Only keep sample value, and discard channel number. */
			for (i = 0; i < NUM_CHANNELS; i++) {
				g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk;
			}
		}
	} else {	/* Without PDC transfer */
		if ((adc_get_status(ADC) & ADC_ISR_DRDY) ==
				ADC_ISR_DRDY) {
			ul_temp = adc_get_latest_value(ADC);
			for (i = 0; i < NUM_CHANNELS; i++) {
				uc_ch_num = (ul_temp & ADC_LCDR_CHNB_Msk) >>
						ADC_LCDR_CHNB_Pos;
				if (g_adc_sample_data.uc_ch_num[i] == uc_ch_num) {
					g_adc_sample_data.us_value[i] =
							ul_temp &
							ADC_LCDR_LDATA_Msk;
					g_adc_sample_data.us_done |= 1 << i;
				}
			}
		}
	}
}
示例#10
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);
			
		}*/
	}
}
示例#11
0
/**
 * \brief Application entry point for PWM with LED example.
 * Output PWM waves on LEDs to make them fade in and out.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	/* Initialize the SAM system */
	sysclk_init();
	board_init();

	/* Configure the console uart for debug information */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);
	
	/* Enable PWM peripheral clock */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pmc_enable_periph_clk(ID_PWM0);
#else
	pmc_enable_periph_clk(ID_PWM);
#endif

	/* Disable PWM channels for LEDs */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_disable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM0, PIN_PWM_LED1_CHANNEL);
#else
	pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL);
#endif

	/* 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()
	};
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_init(PWM0, &clock_setting);
#else
	pwm_init(PWM, &clock_setting);
#endif

	/* Initialize PWM channel for LED0 */
	/* Period is left-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel_led.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_init(PWM0, &g_pwm_channel_led);
#else
	pwm_channel_init(PWM, &g_pwm_channel_led);
#endif

	/* Enable channel counter event interrupt */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_enable_interrupt(PWM0, PIN_PWM_LED0_CHANNEL, 0);
#else
	pwm_channel_enable_interrupt(PWM, PIN_PWM_LED0_CHANNEL, 0);
#endif

	/* Initialize PWM channel for LED1 */
	/* Period is center-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
	/* Output waveform starts at a high level */
	g_pwm_channel_led.polarity = PWM_HIGH;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM0, PIN_PWM_LED1_CHANNEL, 0);
#else
	pwm_channel_init(PWM, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM, PIN_PWM_LED1_CHANNEL, 0);
#endif

	/* Configure interrupt and enable PWM interrupt */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	NVIC_DisableIRQ(PWM0_IRQn);
	NVIC_ClearPendingIRQ(PWM0_IRQn);
	NVIC_SetPriority(PWM0_IRQn, 0);
	NVIC_EnableIRQ(PWM0_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_enable(PWM0, PIN_PWM_LED1_CHANNEL);
#else
	NVIC_DisableIRQ(PWM_IRQn);
	NVIC_ClearPendingIRQ(PWM_IRQn);
	NVIC_SetPriority(PWM_IRQn, 0);
	NVIC_EnableIRQ(PWM_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL);
#endif


	/* Infinite loop */
	while (1) {
	}
}
示例#12
0
文件: tm_stick.c 项目: dorght/libHemp
static void configure_time_trigger_for_ssc(uint32_t ssc_trigger_hz)
{
	
#if 0
	gpio_configure_pin(PIO_PA12_IDX, PIO_PERIPH_B);
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channels */
	pwm_channel_disable(PWM, PWM_CHANNEL_1);

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = 1000 * 100,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);
	
	pwm_channel_t g_pwm_channel;

	/* Period is left-aligned */
	g_pwm_channel.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel.ul_period = 100;
	/* Duty cycle value of output waveform */
	g_pwm_channel.ul_duty = 50;
	g_pwm_channel.channel = PWM_CHANNEL_1;
	pwm_channel_init(PWM, &g_pwm_channel);
	
	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);
	
	pwm_channel_enable(PWM, PWM_CHANNEL_1);
#endif


	
	uint32_t ul_div = 0;
	uint32_t ul_tc_clks = 0;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	pmc_set_writeprotect(false);

	// Enable peripheral clock.
	pmc_enable_periph_clk(CONF_SSC_CLOCK_SOURCE_ID);

	// TIOA configuration 
	// gpio_configure_pin(PIN_TC0_TIOA0, PIN_TC0_TIOA0_FLAGS);
	// tc_set_writeprotect(TC2, true);
	tc_set_writeprotect(CONF_SSC_CLOCK_TC, false);

	// Configure TC for a 1Hz frequency and trigger on RC compare.
	tc_find_mck_divisor(ssc_trigger_hz, ul_sysclk, &ul_div, &ul_tc_clks, ul_sysclk);
	tc_init(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, ul_tc_clks | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
	uint32_t tmp_val = (ul_sysclk / ul_div) / ssc_trigger_hz;
	
	tc_write_ra(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val / 2);
	tc_write_rc(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val);

	// Start the Timer.
	tc_start(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL);

}

void tm_stick_init(uint32_t bus_speed_hz) {
	if(g_tm_stick_data.mutex == NULL) {
		g_tm_stick_data.mutex =  xSemaphoreCreateMutex();
	}
	
	if(g_tm_stick_data.rtos_task_semaphore == NULL) {
		vSemaphoreCreateBinary(g_tm_stick_data.rtos_task_semaphore);
	}
	
	configure_time_trigger_for_ssc(1000);
	
	sysclk_enable_peripheral_clock(ID_SSC);
	ssc_reset(SSC);
	// Do not go over 1MHz, the pulse will be too long and extend over to the next clock's rising edge (The spec. sheet of 4021BCM does not really list the operation times of 3.3V operation.
	// I tested a couple of speeds.... at 1.25MHz, I found that it sometimes misses some pulses.
	if(bus_speed_hz > TM_STICK_MAX_BUS_SPEED){
		bus_speed_hz = TM_STICK_MAX_BUS_SPEED;
	}
	ssc_set_clock_divider(SSC, bus_speed_hz, sysclk_get_cpu_hz()); 
	clock_opt_t rx_clk_opt = {
		.ul_cks = SSC_RCMR_CKS_MCK,
		.ul_cko = SSC_RCMR_CKO_TRANSFER,
// TODO: Fix the SSC clock for some reason shift 1/2 clock pulse position.
// This makes the button results shift one position to the right. So we have to change rising/falling edge to "correct" it (oh, well, "hack" around it).
// Don't know why.
// One possible patch up is to use a pin to signal which one is desired to determine which of the following settings to use..
#if defined(CONF_BOARD_ARDUINO_DUE) 
		.ul_cki = 0, //SSC_RCMR_CKI,
#else
		.ul_cki = SSC_RCMR_CKI,
#endif
		.ul_ckg = SSC_RCMR_CKG_CONTINUOUS,
		.ul_start_sel = SSC_RCMR_START_RF_FALLING,
		.ul_period = 0,
		.ul_sttdly = 0
	};
	
	data_frame_opt_t rx_data_frame_opt = {
		.ul_datlen = 23,
		.ul_msbf = 0,  //SSC_RFMR_MSBF,
		.ul_fsos = SSC_RFMR_FSOS_NONE,
		.ul_datnb = 0,
		.ul_fsedge = SSC_RFMR_FSEDGE_NEGATIVE,
		.ul_fslen = 0,
		.ul_fslen_ext = 0
	};
	
	ssc_set_receiver(SSC, &rx_clk_opt, &rx_data_frame_opt);
	ssc_enable_interrupt(SSC, SSC_IER_RXRDY);
	
	// It is VERY IMPORTANT to set the priority of the interrupt to conform to what FreeRTOS needs because we are calling FreeRTOS interrupt-safe APIs (those *FromISR) from within interrupt handlers.
	// If we don't do this, if would work at the beginning, and then eventually the whole thing will come crashing down.
	// And it's not gonna crash even after millions of interrupts are handled. It will come crashing down in some very weird place after you start using another interrupt handler, like the pio handlers, and only after some handlling...
	// And, it will appear random. You press the button a couple of times, it dies. Then, at other times, you press and hold the button, etc. etc. Each time will be different.
	// You would be suspecting your stack overflowed, your code does a wild pointer, etc. etc. It's very difficult to debug. Trust me, you don't wanna go there.
	NVIC_ClearPendingIRQ(SSC_IRQn);
	NVIC_SetPriority(SSC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	
	NVIC_EnableIRQ(SSC_IRQn); 
	
	ssc_enable_rx(SSC);
}

void SSC_Handler( void ) {	
	portBASE_TYPE xHigherTaskWoken = pdFALSE;
	uint32_t* in_data_buf = (uint32_t*)g_tm_stick_data.data;
	uint32_t in_data = 0;
	static uint32_t previous_in_data = 0;
	static bool is_first_time = true;
	// calculate the mask needed to wipe off extra high bit junk.
	static uint32_t mask = 0xFFFFFFFF;
	if(is_first_time) {
		for(int i = 4; i > TM_STICK_NUM_DATA_BYTES; i--) {
			mask = mask >> 8;
		}
	}

	if(ssc_is_rx_ready(SSC) == SSC_RC_YES) {
		xSemaphoreTakeFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
		in_data = SSC->SSC_RHR;
		// in_data >>= 1; // No idea why it always reads 25bits (one too many bit at the end LSB), instead of 24 I told it to. Therefore, we shift it off.
		in_data = ~in_data; // reverse it. So, now 1 is on, 0 is off.
		in_data &= mask;
		
		// Glitch filtering below.
		if(is_first_time
			||  (previous_in_data ^ in_data) == 0) {
			is_first_time = false;
			*in_data_buf = in_data;
		}
		previous_in_data = in_data;
		xSemaphoreGiveFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
	
		xHigherTaskWoken = pdFALSE;
		xSemaphoreGiveFromISR(g_tm_stick_data.rtos_task_semaphore, &xHigherTaskWoken); // if there is an RTOS waiting for the ADC task mutex, wake it up.
		portEND_SWITCHING_ISR(xHigherTaskWoken);
	}
}

#ifdef __cplusplus
}
void init_pwm(void)
{
	/* Enable PWM peripheral clock */
	pmc_enable_periph_clk(ID_PWM0);

	/* Disable PWM channels for LEDs */
	pwm_channel_disable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM0, PIN_PWM_LED1_CHANNEL);

	/* 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(PWM0, &clock_setting);

	/* Initialize PWM channel for LED0 */
	/* Period is left-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel_led.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Enable channel counter event interrupt */
	pwm_channel_enable_interrupt(PWM0, PIN_PWM_LED0_CHANNEL, 0);

	/* Initialize PWM channel for LED1 */
	/* Period is center-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
	/* Output waveform starts at a high level */
	g_pwm_channel_led.polarity = PWM_HIGH;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM0, PIN_PWM_LED1_CHANNEL, 0);

	/* Configure interrupt and enable PWM interrupt */
	NVIC_DisableIRQ(PWM0_IRQn);
	NVIC_ClearPendingIRQ(PWM0_IRQn);
	NVIC_SetPriority(PWM0_IRQn, 0);
	NVIC_EnableIRQ(PWM0_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM0, PIN_PWM_LED0_CHANNEL);
//jsi 15feb16	pwm_channel_enable(PWM0, PIN_PWM_LED1_CHANNEL);

}
/*! \brief Main function. Execution starts here.
 *
 *  \return 0 on success
 */
int main(void)
{
  pwm_opt_t pwm_opt;                // PWM option config.
  avr32_pwm_channel_t pwm_channel = {{0}, // cmr
                                     {0}, // cdty
                                     {0}, // cdtyupd
                                     {0}, // cprd
                                     {0}, // cprdupd
                                     {0}, // ccnt
                                     {0}, // dt
                                     {0}};// dtupd  ;  One channel config.
  unsigned int channel_id;

  // Start Main Clock On external 16MHz Oscillator
  // Start PLL for PWM
  local_start_highfreq_clock();
  // Start Enable Generic Clock with PLL as source clock
  pwm_start_gc();

  channel_id = EXAMPLE_PWM_CHANNEL_ID;
  gpio_enable_module_pin(EXAMPLE_PWM_L_PIN, EXAMPLE_PWM_L_FUNCTION);
  gpio_enable_module_pin(EXAMPLE_PWM_H_PIN, EXAMPLE_PWM_H_FUNCTION);
  // PWM controller configuration.
  pwm_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
  pwm_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
  pwm_opt.prea = AVR32_PWM_PREA_CCK;
  pwm_opt.preb = AVR32_PWM_PREB_CCK;

  pwm_opt.fault_detection_activated = false;
  pwm_opt.sync_channel_activated    = true;
  pwm_opt.sync_update_channel_mode  = PWM_SYNC_UPDATE_MANUAL_WRITE_MANUAL_UPDATE;
  pwm_opt.sync_channel_select[0]    = true;
  pwm_opt.sync_channel_select[1]    = true;
  pwm_opt.sync_channel_select[2]    = false;
  pwm_opt.sync_channel_select[3]    = false;
  pwm_opt.cksel                     = PWM_CKSEL_GCLK;
  pwm_init(&pwm_opt);

  // Update the period
  pwm_update_period_value(10);

  // Channel configuration
  pwm_channel.CMR.dte   = 1;        // Enable Deadtime for complementary Mode
  pwm_channel.CMR.dthi  = 1;        // Deadtime Inverted on PWMH
  pwm_channel.CMR.dtli  = 0;        // Deadtime Not Inverted on PWML
  pwm_channel.CMR.ces   = 0;        // 0/1 Channel Event at the End of PWM Period
  pwm_channel.CMR.calg  = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
  pwm_channel.CMR.cpol  = PWM_POLARITY_LOW;            // Channel polarity.
  pwm_channel.CMR.cpre  = AVR32_PWM_CPRE_CCK;           // Channel prescaler.
  pwm_channel.cdty      = 10;       // Channel duty cycle, should be < CPRD.
  pwm_channel.cprd      = 20;       // Channel period.

  // With these settings, the output waveform period will be :
  // (56MHz)/20 == 2.8MHz == (MCK/prescaler)/period, with MCK == 56MHz,
  // prescaler == 1, period == 20.

  pwm_channel_init(channel_id, &pwm_channel); // Set channel configuration to channel 0
  pwm_start_channels((1 << channel_id));  // Start channel 0 & 1.

  while(1);
}