10-bit fast PWM help

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I'm trying to use 10-bit non-inverting fast PWM (on an ATMega48) to generate output on OC1A.

I'm also doing a 10-bit ADC (AREF is VCC) on one of the ADC inputs.

Theoretically, if I load OCRA with the contents of ADCW from and ADC conversion, shouldn't I get a voltage output approximate to that of the voltage on my ADC input if the PWM signal is passed through an RC filter?

I'm trying to make sure I understand how the PWM signal is generated based on the OCRA values.

Thanks!

#include 
#include 

uint16_t volatile vtarget;

ISR(ADC_vect)						
{
	vtarget = ADCW;
}

int main(void)
{

	DDRB = 0xFF;						//Outputs on PORTB
	ADMUX =  0b01000000;					//Set AREF to Vcc, ADC0 as MUX input
	ADCSRB = 0b01000000;					//Enable input multiplexer, set ADC trigger to "Free Running Mode"
	sei();									//Enable global interrupts
	ADCSRA = 0b11101000;					//Set division scale and begin first conversion
	TCCR1A = 0b10000011;					//COM1A1 clear on compare match
	TCCR1B = 0b00001001;					//WGM 0111 (Fast PWM/10-bit), Tclk = IOclk /1

	while (1)
	{
		OCR1A = vtarget;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Be warned the interrupt could go off and 'interrupt' may be changed half way through it being used to write OCR1A in the while(1) loop. As 16 bit accesses cannot be atomic in a single opcode you may want to consider adding some interrupt protection to the access in the while(1)

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

Just disable global interrupts before and after:

OCR1A = vtarget;

Correct? Does everything else look good?

Thanks for the input, clawson.

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

Just to follow up:

Yes, this does work. It's off by a little bit, due to differences in PWM output versus ADC input, but it does work.

If you're going to use ADCW in GCC, make sure that ADLAR is NOT set to one. Doing so really messes up your results.