Cantafford
Member
Hello,
I'm trying to control a DC motor with an ATmega328P. Actually I will need to control a servo motor later but I need to learn to generate PWM signals properly first. Since I need a high resolution I used timer1 which can generate 16 bit pwm resolution.
I have used 10 bit fast pwm mode and tried to implement a duty cycle of 50%. Something I don't understand though is how can I set the period(frequency) of the PWM signal. I have just started working with AVR's and I don't know how to do this. For example when programming PICs you need to set the period of the pwm signal before setting it's duty cycle. But for AVR's I have not found how to do this in the datasheet. This is how I initialized my timer1 module:
When I simulate this the motor does not run at all.
Here is the full code(ignore the ADC part that's not important).
I'm trying to control a DC motor with an ATmega328P. Actually I will need to control a servo motor later but I need to learn to generate PWM signals properly first. Since I need a high resolution I used timer1 which can generate 16 bit pwm resolution.
I have used 10 bit fast pwm mode and tried to implement a duty cycle of 50%. Something I don't understand though is how can I set the period(frequency) of the PWM signal. I have just started working with AVR's and I don't know how to do this. For example when programming PICs you need to set the period of the pwm signal before setting it's duty cycle. But for AVR's I have not found how to do this in the datasheet. This is how I initialized my timer1 module:
Code:
TCCR1A = 0b10111111; // fast non inverting 10 bit pwm mode
TCCR1B = 0b00001001; // 10 bit fast pwm mode, no prescaler
TCNT1H = 0xEF; // 50 duty cycle
TCNT1L = 0xFF;
When I simulate this the motor does not run at all.
Here is the full code(ignore the ADC part that's not important).
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000 // CPU speed - always define prior to including util/delay.h
#include <util/delay.h>
int main()
{
DDRB = 0xFF; // PWM is output(also the LEDs)
DDRD = 0xFF;
ADMUX = 0b01010000; // AREF reference, result left justified, ADC0 selected
ADCSRA = 0b10011111;
sei(); // enable global interrupts
ADCSRA |= (1 << ADSC); // start conversion
TCCR1A = 0b10111111; // fast non inverting 10 bit pwm mode
TCCR1B = 0b00001001; // 10 bit fast pwm mode, no prescaler
TCNT1H = 0xEF; // 50 duty cycle
TCNT1L = 0xFF;
while(1)
{
}
}
ISR(ADC_vect)
{
PORTD = ADCL; // put result of conversion on PORTB
PORTB = (ADCH << 2) & 0xFF; // get ADCH to RB3 and RB2 and also keep PWM pin unchanged
ADCSRA |= (1 << ADSC); // restart conversion
}
