I'm new to Atmel Studio. I used BASCOM-AVR until now. I know my question is very basic but I couldn't solve my problem by searching internet.
I wrote a code in BASCOM (Basic laguage) to control two DC motors using ATmega32 and L298n. Here is a part of it:

$regfile = "m32def.dat"
$crystal = 1000000

Config Timer1 = Pwm , Pwm = 10 , Compare_A_Pwm = Clear_Up , Compare_B_Pwm = Clear_Up , Prescale = 1

'D.0 and D.1 for right, D.2 and D.3 for left
Config PortD.3 = Output
Config PortD.2 = Output
Config PortD.1 = Output
Config PortD.0 = Output

'pwm1a for left motor, pwm1b for right motor

    reset portd.1
    reset portd.2
    set portd.0
    set portd.3
    pwm1b = 500
    pwm1a = 1023
    waitms 2000

    reset portd.0
    reset portd.3
    set portd.1
    set portd.2
    pwm1b = 1023
    pwm1a = 500
    waitms 2000

Now I want to convert it to "C" for Atmel Studio but I can't understand syntax for PWM in C.
Also, I didn't understand the way to set just a pin to 0 or 1 (not a port). I mean, if I write (in Atmel Studio):

PORTD = 0b00001001;

pind0 and pind3 are high and pind1 and pind2 are low but I'm worried if setting pind4...7 to 0 affects PWM (Because PD4 and PD5 are for PWM).
Could you please explane me syntax of PWM in C and answer my second question?
It would be very good if you convert my code to C and explane C by comparing it to Basic! :)

  • $\begingroup$ in general, keep an image in memory of what the port pins should be. Initialize that image. Then write that image to the port in a single code statement. When wanting to modify what the port pins levels are, modify the image, then write the whole image to the port in a single code statement $\endgroup$ – user3629249 May 18 '19 at 2:09

OK. After many researches and reading some books, I found the way. Here is my code:

#include <avr/io.h>
#define F_CPU 8000000UL     //8MHz CPU frequency
#include <util/delay.h>     //To use _delay_ms()

void pwm_init()     //to initialize PWM
    TCCR1A = 0b10100011;     //register TCCR1A
    TCCR1B = 0b00000001;     //register TCCR1B
    DDRD = 0b11111111;     //set portd as output 

int main(void)
    pwm_init();     //to initialize PWM
    //D0 and D1 for right motor, D2 and D3 for left motor
        PORTD = 0b00000101;
        OCR1A = 1023;     //maximum
        OCR1B = 500;

        PORTD = 0b00000110;
        OCR1A = 500;
        OCR1B = 1023;     //maximum

In my code, because I want to control a DC motor using L298, I must use "10-BIT Phase correct PWM" mode, prescale 1 and non-inverted PWM; So that I must set register TCCR1A in this way:

COM1A1 & COM1B1: 1
COM1A0 & COM1B1: 0
FOC1A & FOC1B: 0
WGM11 & WGM10:1

And TCCR1B in this way:

CS10: 1
All other bits: 0

According to the structure of TCCR1A and TCCR1B registers, you must set them like this:

TCCR1A = 0b10100011;
TCCR1B = 0b00000001;

And you can set PWM duty cycle by setting OCCR1A and OCCR1B variables. It's clear that minimum value is always 0! But maximum value depends on resolution of your PWM (8,9 or 10-BIT).

Note: I didn't test it using real parts yet. Just simulations show me the correct result. If there is any mistake in my code, please post it in the comments!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.