Can someone come to check my code?

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <asf.h>
#define  DUTY_CYCLE 1000

volatile avr32_pwm_t *pwm = &AVR32_PWM;

__attribute__((__interrupt__))
void pwm_handler()
{
	AVR32_PWM.isr;
	if (pwm->channel[0].cdty == 0)
		{
			pwm->channel[0].cdty+=1;
			pwm->channel[1].cdty+=1;
			pwm->channel[2].cdty+=1;
			pwm->channel[6].cdty+=1;
		} 
		else if (pwm->channel[0].cdty == DUTY_CYCLE)
		{
			pwm->channel[0].cdty-=1;
			pwm->channel[1].cdty-=1;
			pwm->channel[2].cdty-=1;
			pwm->channel[6].cdty-=1;
		}
		else
		{
			pwm->channel[0].cdty+=1;
			pwm->channel[1].cdty+=1;
			pwm->channel[2].cdty+=1;
			pwm->channel[6].cdty+=1;
		}
		delay_ms(50);
}

int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */
	
	sysclk_init();
	
	delay_init(16000000);
	
	/* PWM controller configuration. */
	
	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
		};

	/* PWM channel configuration structure. */
	avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };
	
	/* 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.cdty = 0; /* Channel duty cycle, should be < CPRD. */
	pwm_channel.cprd = DUTY_CYCLE; /* 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_8; /* Channel prescaler. */	
	
	static const gpio_map_t PWM_GPIO_MAP =
	{
		{7, 0},
		{8, 0},
		{21,0},
		{22,0}
	};
	
	gpio_enable_module(PWM_GPIO_MAP, sizeof(PWM_GPIO_MAP)/sizeof(PWM_GPIO_MAP[0]) );
	
	/* Initialize the PWM module. */
	pwm_init(&pwm_opt);
	
	pwm_channel_init(0,&pwm_channel);
	pwm_channel_init(1,&pwm_channel);
	pwm_channel_init(2,&pwm_channel);
	pwm_channel_init(6,&pwm_channel);
	
	INTC_init_interrupts();

	// Register the EIC interrupt handlers to the interrupt controller.
	INTC_register_interrupt(&pwm_handler,
			AVR32_PWM_IRQ, AVR32_INTC_INT1);
	
	pwm->ier = 0x47; //PA07,08,21,22
	
	pwm_start_channels(0x47);

	/* Insert application code here, after the board has been initialized. */
	
	while(1)
	{
		pwm->ier =0x47;
	}
}

This doesn't produce the interrupt. I connect the four pins to 4 LEDs, it should shade but it's maintaining the brightness as cdty is 0...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) Which processor ? From your past questions I am guessing this is for a UC3Bxxx
2) To me, the logic in the ISR would cause .cdty to oscillate between DUTY_CYCLE and DUTY_CYCLE-1
3) Why do you have a time delay inside the interrupt-service routine ????

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am guessing this is for a UC3Bxxx

A very good guess also based on the fact that the post is in the UC3 forum and the tag says  AT32UC3B0512 wink of course that may not mean anything, some people tend to post anywhere.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OP said:  Can someone come to check my code?

 

The style of your code seems ok, although the number of spaces for indent looks to be more then 4 spaces.....

I prefer to see comments that tell what to expect from the code (functions, methods) and or to clarify why something was done the way it is.

 

Using delays in a ISR is frowned upon!  ISR should be as fast as possible, generally!

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is the UC3B0512 MCU. The logic that I want to make is to oscillate duty cycle between 0 and DUTY_CYCLE with the time split of 1ms. That's why I use a delay function inside the ISR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a power-on/reset, all interrupts are disabled, so you will need a cpu_irq_enable(); before the while(1)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrAn wrote:

...That's why I use a delay function inside the ISR.

 

Trust us, you'll want to learn how to accomplish your goals without using delays inside ISRs.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrAn wrote:

The logic that I want to make is to oscillate duty cycle between 0 and DUTY_CYCLE...

 

Once your code gets to DUTY_CYCLE, how does it go back down to 0?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <asf.h>
#define  DUTY_CYCLE 1000

volatile avr32_pwm_t *pwm = &AVR32_PWM;

__attribute__((__interrupt__))
void pwm_handler()
{
	AVR32_PWM.isr;   //may not seem valid
	if (pwm->channel[0].cdty == 0)
		{
			pwm->channel[0].cdty+=1;
			pwm->channel[1].cdty+=1;
			pwm->channel[2].cdty+=1;
			pwm->channel[6].cdty+=1;
		} 
		else if (pwm->channel[0].cdty < DUTY_CYCLE) //changed
		{
			pwm->channel[0].cdty+=1;
			pwm->channel[1].cdty+=1;
			pwm->channel[2].cdty+=1;
			pwm->channel[6].cdty+=1;
		}
		else
		{
			pwm->channel[0].cdty-=1;
			pwm->channel[1].cdty-=1;
			pwm->channel[2].cdty-=1;
			pwm->channel[6].cdty-=1;
		}
}

int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */
	
	sysclk_init();
	
	delay_init(16000000);
	
	/* PWM controller configuration. */
	
	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
		};

	/* PWM channel configuration structure. */
	avr32_pwm_channel_t pwm_channel = { .ccnt = 0 };
	
	/* 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.cdty = 0; /* Channel duty cycle, should be < CPRD. */
	pwm_channel.cprd = DUTY_CYCLE; /* 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_8; /* Channel prescaler. */	
	
	static const gpio_map_t PWM_GPIO_MAP =
	{
		{7, 0},
		{8, 0},
		{21,0},
		{22,0}
	};
	
	gpio_enable_module(PWM_GPIO_MAP, sizeof(PWM_GPIO_MAP)/sizeof(PWM_GPIO_MAP[0]) );
	
	/* Initialize the PWM module. */
	pwm_init(&pwm_opt);
	
	pwm_channel_init(0,&pwm_channel);
	pwm_channel_init(1,&pwm_channel);
	pwm_channel_init(2,&pwm_channel);
	pwm_channel_init(6,&pwm_channel);
	
	INTC_init_interrupts();

	// Register the EIC interrupt handlers to the interrupt controller.
	INTC_register_interrupt(&pwm_handler,
			AVR32_PWM_IRQ, AVR32_INTC_INT1);
	
	pwm->ier = 0x47;
	
	pwm_start_channels(0x47);

	cpu_irq_enable();
	/* Insert application code here, after the board has been initialized. */
	
	while(1)
	{
		delay_s(1);   //delay not in ISR :)
		pwm->ier =0x47;  //may seem not valid..
	}
}

It really does the oscillation of the brightness. However, it seems a bit strange: the LEDs blink in high brightness first and then blink in the low one after a while... (I think that 1000 is enough for the period to not form the blink).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The LEDs and then always keep dim blinking...

Last Edited: Sun. Sep 10, 2017 - 03:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, no. It keeps oscillating. So it seems to work fine. However, the time for dim is much much much longer than bright. Not having an oscilloscope is really a big problem...

Last Edited: Sun. Sep 10, 2017 - 03:22 PM