AVR Atmega328P Fast PWM beeinflusst UART

OP #6004981
Lesenswert?

Hallo Forum,

in einem Projekt verwende ich einen Atmega328P (classic Arduino Due 
Board aber mit Atmel ICE geflashed). Ich habe eine Fast PWM 
initialisiert (Timer0 Mode 3) und die UART Schnittstelle. Beide separat 
funktionieren super, aber sobald ich die PWM einschalte (Clock Source in 
TCCR0B Register) spinnt die UART komplett. Character werden nicht mehr 
korrekt übertragen oder empfangen. Es scheint als würde die BAUD Rate 
durch den Timer beeinflusst. Unten mein Code. Das meiste stammt aus 
einer Aplication Note. Hat jemand so was ähnliches schon mal erlebt?
1
#define F_CPU 16000000
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5

6
#define BAUD 9600
7
#define MYUBRR F_CPU/16/BAUD-1
8

9
unsigned char UART_receive( void );
10
void UART_send( char data);
11

12
void AVR_init(void) {
13

14
    /* Clock init done by FUSES, CLK = 16 MHz ext. Oscillator */
15
    
16
    /*LED PIN*/
17
    /*---------------------------------------------------------*/
18
    DDRB = (1 << PINB5);
19

20
    /* init UART asynchronous 9600 8Bits 1Stop */
21
    /*---------------------------------------------------------*/
22
    /*Set baud rate registers according to MYUBRR definition*/
23
    UBRR0H = (unsigned char) (MYUBRR >> 8);
24
    UBRR0L = MYUBRR;
25

26
    /* Enable receiver and transmitter */
27
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);
28

29
    /* Set frame format: 8data, 1stop bit */
30
    UCSR0C = (0 << UMSEL00);
31
    UCSR0C |= (0 << UCSZ00) | (1 << UCSZ01) | (1 << UCSZ00);
32

33
    /*init PWM, Timer*/
34
    /*---------------------------------------------------------*/
35
    /*Timer/Counte0 as PWM Waveform Generator on PD6/PD5 OC0A/OC0B (Arduino Pin 6, 5) (FAST PWM MODE 3)*/
36
    DDRD = (1 << PIND6);
37
    DDRD = (1 << PIND5);
38
    
39
    TCCR0A = (1 << COM0A1) | (0 << COM0A0);
40
    TCCR0A |= (1 << COM0B1) | (0 << COM0B0);
41
    
42
    /*MODE 3: Fast PWM TOPP = 0xFF*/
43
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
44
    
45
    /* MODE 7 */
46
    TCCR0B |= (0 << WGM02);
47
    
48
    /*Select CLK Source and Prescaler*/
49
    /*Prescaler 1, 8, 64, 256, 1024*/
50
    TCCR0B |= (0 << CS02) | (1 << CS01) | (0 << CS00);
51
    // HIER GEHT WAS SCHIEF sobald ein CS0x bit gesetzt wird
52
    
53
    /*Interrupt enable*/
54
    TIMSK0 = (1 << OCIE0A) | (1 << OCIE0B);
55
    
56
    /*This Register defines compare Match => Duty Cycle PWM Channel A in MODE 3 activated*/
57
    /*This Register defines compare Match => Periode PWM Channel A in MODE 7 activated*/
58
    OCR0A = 128;
59
    
60
    /*This Register defines compare Match => Duty Cycle PWM Channel B in MODE 3 activated*/
61
    /*This Register defines compare Match => Duty Cycle PWM Channel A in MODE 7 activated*/
62
    OCR0B = 64;
63
    
64
    /* MODE3: Output Waveform Frequency = F_CPU/Prescaler/256  */
65
    /* MODE7: Output Waveform Frequency = F_CPU/2/Prescaler/(OCR0A+1)  */
66
    
67
    sei();
68
};
69

70
int main(void){
71
    
72
    AVR_init();
73
    
74
    while( 1 ) {
75
        UART_send( UART_receive() );
76
    }
77
}
78

79
unsigned char UART_receive(void){
80
    /* Wait for data to be received */
81
    while (!(UCSR0A & (1<<RXC0)));
82
    /* Get and return received data from buffer */
83
    return UDR0;
84
};
85

86
void UART_send( char data){
87
    /* Wait for empty transmit buffer */
88
    while (!(UCSR0A & (1<<UDRE0)));
89
    /* Put data into buffer, sends the data */
90
    UDR0 = data;
91
};

Hinweis: ich weiß, dass der Syntax
1
REG |= (0<<XXX);
 keine keine Resultat erzielt, ich nutzte es als Platzhalter / 
Vollständigkeit

viele Grüße und schon mal vielen Dank für Eure Anregungen
Lukas
Gast #6005005
Lesenswert?

Lukas B. schrieb im Beitrag #6004981
> #define MYUBRR F_CPU/16/BAUD-1

Du solltest die rechte Seite von defines immer klammern, denn ...

>     UBRR0H = (unsigned char) (MYUBRR >> 8);

bei sowas kann Unerwartetes entstehen, naemlich ...
1
  F_CPU/16/BAUD - 1 >> 8

(Leerzeichen zecks Lesbarkeit)

leo
Gast #6005040
Lesenswert?

Lukas B. schrieb:
> OMG schrieb:
>> Lukas B. schrieb:
>>> verwende ich einen Atmega328P (classic Arduino Due Board
>>
>> Du musst dich schon entscheiden: Arduino Due oder Mega328P,
>> beides auf einem Board wirds wohl nicht sein.
>
> Arduino Duemilanove ist das Board, Atmega328P ist der Controller. Stimmt
> also beides ;)

Dann musst Du ihn auch Duemilanove nennen, der Due hat einen SAM 
Prozessor drauf ;-)
OP #6005075
Lesenswert?

Thomas E. schrieb:
> Lukas B. schrieb:
>> TIMSK0 = (1 << OCIE0A) | (1 << OCIE0B);
>
> Wo sind deine ISRs?

ISR braucht man nicht bei Fast PWM, die Pins werden direkt vom 
CombarMatch geschalten. Nix Software, alles autarke Hardware.
1
 
2
TCCR0A = (1 << COM0A1) | (0 << COM0A0);
3
TCCR0A |= (1 << COM0B1) | (0 << COM0B0);
4
    
5
TCCR0A |= (1 << WGM01) | (1 << WGM00);

Zitat Datacheet: Clear OC0A on compare match, set OC0A at BOTTOM,
(non-inverting mode).
Gast #6005186
Lesenswert?

Lukas B. schrieb:
> TIMSK0 = (1 << OCIE0A) | (1 << OCIE0B);

die zeile hatte ich auch nur mit den passenden ISR im kopf

PWM ohne ISR geht , JA
aber dann ohne das TIMSKx


hab grad irgndwo ne Lüftersteuerung gefunden
1
  PORTD   &= ~(1<<PD3);
2
  DDRD  |=  (1<<PD3);   // luefter
3

4
  TCCR2A  = (1<<WGM21)| (1<<WGM00);
5
  TCCR2B  = (1<<CS20) |(1<<CS21)|(1<<CS22); 
6

7
  if( ocrval ){
8
       TCCR2A  |=  (1<<COM2B1);      
9
    if( ocrval < 40)
10
      OCR2B = ocrval ;
11
    else  
12
      OCR2B = 40 ;
13
  }else{
14
    TCCR2A  &= ~(1<<COM2B1);
15
  }
Gast #6005189
Lesenswert?

Sven K. schrieb:
> Wolfgang schrieb:
>> Ein Arduino Duemilanove ist kein Arduino Due.
>>
>> Auf dem Arduino Due sitzt ein SAM3X8E ARM Cortex-M3 Controller.
>
> wurde doch davor jetzt schon ausgiebigst geklärt...

Das sind die 2 oder 3 Typen, die zwar nichts zur Beantwortung der Frage 
beitragen können, aber dafür einen Riesenspaß beim Verwirren der Leser 
haben. Fast immer heißen die Thomas oder Joachim. Manchmal auch 
Wolfgang.

Wie Fußpilz -auch ganz schlecht loszuwerden.
:(
OP #6005192
Lesenswert?

S. Landolt schrieb:
>> ISR braucht man nicht bei Fast PWM
>
> Korrekt. Nur - weshalb werden die Interrupts dann freigegeben?
>
>
>> /*Interrupt enable*/
>>    TIMSK0 = (1 << OCIE0A) | (1 << OCIE0B);

Super! Danke für den Tipp, das war der Hacken :)

Habe es auskommentiert und siehe da, alles funktioniert wie gewollt. Ich 
dachte mir der Interrupt Controller des Timers muss aktiv sein damit der 
OC0A Pin Toggelt aber "again what learned" wie der Sachse sagt.

Vielen Dank für die schnellen Reaktionen und Hilfestellungen. Das war 
meine erste Anfrage und gleich ein Erfolgserlebnis.
Moderator Persönliche Seite #6005264
Lesenswert?

Lukas B. schrieb:
> Habe es auskommentiert und siehe da, alles funktioniert wie gewollt.

Auch wenn es jetzt läuft, solltest Du Leos Rat in 
Beitrag "Re: AVR Atmega328P Fast PWM beeinflusst UART" beherzigen. Die 
rechte Seite eines #defines sollte man immer klammern. Sonst kann das 
bei weiteren Berechnungen ziemlich in die Hose gehen. Leo erklärt in 
seinem Beitrag auch, warum.

Ersetze bitte:
1
#define MYUBRR F_CPU/16/BAUD-1

durch:
1
#define MYUBRR (F_CPU/16/BAUD-1)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren