User Tools

Site Tools


elektronik:start

AVR-PWM mit Atmega168

Hier ein kleiner Aufbau wie man mit dem Atmega 168 (oder einem anderen Atmega) PWM erzeugen kann.

Aufbau

Hier kommt das Programm und das Makefile.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
#define led_active_on()            (PORTD |=  (1<<PD2))
#define led_active_off()        (PORTD &= ~(1<<PD2))
 
// outputs
#define set_pwm_line_1(value)    (OCR1A = value)
#define set_pwm_line_2(value)    (OCR1B = value)
 
// -----------------------------------------------------
// io handling
// -----------------------------------------------------
void init_io()
{
    // DDRX: Bit 1 = output / 0 = input
    // if input  : PORTX = 1 : Pullup active
    // if output : PORTX = state of the output
 
    // Port B
    // Outputs
    DDRB  = 0b11111111;
    PORTB = 0b11111111;
 
    // Port C
    // Outputs
    DDRC  = 0b11111111;
    PORTC = 0b11111111;
 
    // Port D
    // Outputs
    DDRD  = 0b11111111;
    PORTD = 0b11111111;
}
 
// -----------------------------------------------------
// regulation
// Timer 0A: Regulation cycle: 100Hz (CTC)
// Timer 1A: PWM Channel 1 2000Hz
// Timer 1B: PWM Channel 2 2000Hz
// -----------------------------------------------------
void init_pwm()
{
    // regulatin counter (ctc)
    // prescale 1024
    TCCR0A |= (1<<WGM01);
    TCCR0B |= (1<<CS02) | (1<<CS00);
    TIMSK0 |= (1<<OCIE0A);
    OCR0A = 156;
 
    // Fast PWM Generation 10 Bit on port 1A and 1B (Waveform generation mode 7)
    // prescale 8 (2 kHz PWM)
    TCCR1A |= (1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) ;
    TCCR1B |= (1<<WGM12) | (1<<CS11);
 
    // no output at start
    OCR1A = 0;
    OCR1B = 0;
}
 
 
// -----------------------------------------------------
// main loop
// -----------------------------------------------------
void DoPWM()
{
    static uint16_t val = 0;
    val += 5;
    if (val >= 1024)
    {
        val = 0;
    }
 
    OCR1A = 1023-val;
    OCR1B = 1023-val;
}
 
int main(void)
{
    // init stuff
    init_io();
    init_pwm();
 
    // endless loop
    while(1)
    {
        // on
        led_active_on();
        _delay_ms(50);
        DoPWM();
 
        led_active_off();
        _delay_ms(50);
        DoPWM();
    }
}
CC=avr-g++
RM=rm -f
OBJCOPY=avr-objcopy
OBJDUMP=avr-objdump
AVRDUDE=avrdude -p m168 -c avrispmkii -P usb -e -U flash:w:
AVRSIZE=avr-size
 
MCU=atmega168p
F_CPU=16000000
 
CFLAGS=-g -DF_CPU=$(F_CPU) -Wall -Os --std=gnu++0x -mcall-prologues
 
OBJ = main.o
 
BIN = pwmtest.bin
HEX = pwmtest.hex
MAP = pwmtest.map
ASM = pwmtest.asm
 
.phony: clean fuse flash
 
all:    $(OBJ)
    $(RM) $(HEX) $(BIN) $(MAP)
    $(CC) -mmcu=$(MCU) $(CFLAGS) -o $(BIN) -Wl,-Map,$(MAP) $(OBJ)
    $(OBJCOPY) -R .eeprom -O ihex $(BIN) $(HEX)
    $(OBJDUMP) -h -S $(BIN) > $(ASM)
 
%.o: %.cpp
    $(CC) -mmcu=$(MCU) $(CFLAGS) -c $<
 
clean:
    $(RM) $(OBJ) $(BIN) $(HEX) $(MAP)
 
flash: $(OBJ)
    $(AVRDUDE)$(HEX)    
 
size:    $(BIN)
    $(AVRSIZE) -C --mcu=$(MCU) $(BIN)
 
# External Osc > 8MHz
fuse:
    $(AVRDUDE) -U lfuse:w:0xdf:m -U hfuse:w:0xde:m

Wie ihr seht ist es nicht schwer damit ein PWM zu erzeugen.

Zur Visualisierung hab ich an PD2 eine Blink LED angeschlossem welche alle 50 ms an und aus geht. Auch wird einfach der PWM Wert hochgezählt um auf dem Oszi was zu sehen. Mit der LED sehe ich einfach dass das Programm läuft.

Hier der Aufbau. Als Board hab ich das RN-MiniControl genommen, da es einfach recht viele Möglichkeiten bietet um schnell was zu testen.

An PB1(OC1A) hab ich das PWM Signal ausgegeben. Hier das Oszi:

(If Flash is installed, you can watch a video inside this web page.)

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
elektronik/start.txt · Last modified: 2016/06/07 16:45 (external edit)