Forum: Mikrocontroller und Digitale Elektronik Anfängerprobleme mit MEGA32


von Sebastian (Gast)


Lesenswert?

Hi,

Ich habe mir heute auf einem Steckbrett eine Experimentierschaltung mit 
einem Mega32 aufgebaut. Als Programmer benutze ich einen einfachen 
Parallelport Programmer und Ponyprog. Das scheint soweit auch zu 
funktioniere. Kann den Flash schreiben, auslesen und auch FuseBits 
einstellen. Leider bekomme ich es nicht hin eine einfache LED ans 
leuchten zu bekommen.

Hier mein Prog.Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/eeprom.h>
4
5
//CPU Frequenz für Programm auf 1MHz einstellen(interner Takt)
6
#define F_CPU    4000000
7
8
//Bautrateneinstellung
9
#define BAUD 4800L          // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
10
 // Berechnungen
11
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
12
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
13
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille 
14
 
15
#if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
16
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
17
#endif
18
19
//***********************
20
typedef unsigned char byte;
21
typedef unsigned int word;
22
23
typedef struct byte_str{
24
  unsigned b0:1;
25
  unsigned b1:1;
26
  unsigned b2:1;
27
  unsigned b3:1;
28
  unsigned b4:1;
29
  unsigned b5:1;
30
  unsigned b6:1;
31
  unsigned b7:1;
32
};
33
34
35
//***********************
36
void ioinit(void);
37
void delay_ms(unsigned int ms);
38
39
40
//***********************
41
// Initialisierung der IO
42
void ioinit(void)
43
{
44
    
45
    DDRA = 0xff;    // PortB als Ausgang deklarieren
46
    //PORTB = 0x00;   // Ports auf HIGH schalten
47
  
48
  DDRC = 0xff;
49
  PORTC = 0x2A;
50
  
51
  DDRD = 0xff;
52
  PORTD = 0x00;  
53
  
54
  sei();  //Interrupts an
55
  //cli(); Interrupts aus
56
  
57
}
58
/***********************/
59
//UART Funktionen
60
61
void aktiviereUART(void)
62
{
63
  UCSRB |= (1<<TXEN);               // UART TX einschalten
64
  UCSRB |= ( 1 << RXEN );      //UART RX einschalten
65
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);  // Asynchron 8N1 
66
}
67
void uart_write_char(char c)
68
{
69
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich                   */
70
    {
71
    }
72
 
73
    UDR = c;/* schreibt das Zeichen x auf die Schnittstelle */
74
}
75
void uart_write_String (char *s)
76
{
77
    while (*s)
78
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
79
        uart_write_char(*s);
80
        s++;
81
    }
82
}
83
84
85
86
87
//********************
88
//Methoden
89
90
// Warteschleife
91
void delay_ms(unsigned int ms)
92
{
93
    unsigned int zaehler;
94
   
95
    while (ms) {
96
        zaehler = F_CPU / 5000;
97
       
98
        while (zaehler) {
99
            asm volatile("nop");
100
            zaehler--;
101
        }
102
        ms--;
103
    }
104
}
105
106
// Hauptprogramm
107
int main(void) {
108
    unsigned char i;   
109
110
    ioinit();  
111
  
112
   
113
    // Endlosschleife
114
    while (1) {
115
        
116
    PORTD=0xff;
117
    PORTA=0x00;
118
    
119
    }   
120
121
    return 0;
122
}

Ich habe eine LED mit minus an PD6 über 330Ohm an Vss(5V). Die LED will 
aber nicht leuchten.
Ich habe einen Externen Quarz mit 4Mhz angeschlossen. Muss ich das in 
den FuseBits irgendwie einstellen das der ext. Quarz genutzt wird? 
Welche Bits muss ich in PonyProg setzen? Wie kann ich mir sicher sein, 
das der ext. Quarz korrekt arbeitet?

Sebi

von Andreas K. (a-k)


Lesenswert?

> Ich habe eine LED mit minus an PD6 über 330Ohm an Vss(5V). Die LED will
> aber nicht leuchten.

Warum sollte sie auch. Wenn der Minuspol an PD6 liegt, dann folglich der 
Plus an Vss (das Kürzel für Masse), also ist die LED grad verkehrt herum 
dran.

Wenn du andererseits mit Vss(5V) in Wahrheit Vcc meinst, dann ist zwar 
die LED richtig rum, aber mit PORTD=0xFF liegt der Ausgang auch auf 5V 
und die LED kriegt nix.

von Sebastian (Gast)


Lesenswert?

Die Led ist mit dem kurzen beinchen an dem Port und mit dem anderen über 
330Ohm an 5V. Ich nutze Port PD6. Aber es geht nicht. Muss ich noch 
irgendwas anderes im Controller einstellen?

Wie nutze ich den externen Quarz?

von Karl H. (kbuchegg)


Lesenswert?

Sebastian wrote:
> Die Led ist mit dem kurzen beinchen an dem Port und mit dem anderen über
> 330Ohm an 5V. Ich nutze Port PD6. Aber es geht nicht. Muss ich noch
> irgendwas anderes im Controller einstellen?
>
> Wie nutze ich den externen Quarz?

Eins nach dem anderen. Jetzt muss erstmal deine LED leuchten
und dazu ist es unerheblich ob dein Quarz jetzt aktiv ist
oder nicht. Dein Mega32 arbeitet, wenn du an den Fuses noch nichts
verstellt hast, mit dem internen Oszillator auf ca. 1Mhz.
Wichtig ist nur: Er arbeitet.

Gib doch einfach mal ein anderes Bitmuster am Port aus:
0xAA
Das ist binär 10101010, dh. immer abwechselnd eine 1 und
eine 0. Wenn deine LED also am Pin PD6 nicht leuchtet
dann versuche mal den Pin PD5. An einem der beiden muss
es gehen, ansonsten ist was an der Hardware faul.

von Sebastian (Gast)


Lesenswert?

Ah,Ich habs hinbekommen. Sie blinkt jetzt....*Freu*

Und wie gehts jetzt weiter?

von Karl H. (kbuchegg)


Lesenswert?

Sebastian wrote:
> Ah,Ich habs hinbekommen. Sie blinkt jetzt....*Freu*

Gut

>
> Und wie gehts jetzt weiter?

Keine Ahnung. Was willst du denn machen?


Wegen der Umstellung auf Quarz:
http://www.mikrocontroller.net/articles/AVR_Fuses

von Sebastian (Gast)


Lesenswert?

Erstmal würde ich gerne verstehen wie ich das mit der Zeit und der 
Taktfrequenz geregelt bekomme.

Ich habe ja F_CPU 4000000 wegen dem ext. Quarz. Dann ist in der delay_ms 
eine wartezeit in ms eingegeben. Wie errechnet man die exakte wartezeit 
in ms, so das die wartezeit wirklich in ms angegeben werden kann?

von Karl H. (kbuchegg)


Lesenswert?

Sebastian wrote:
> Erstmal würde ich gerne verstehen wie ich das mit der Zeit und der
> Taktfrequenz geregelt bekomme.
>
> Ich habe ja F_CPU 4000000 wegen dem ext. Quarz.

Dann solltest du dem obigen Link folgen, die Seite komplett
lesen und den Mega32 mal auf Quarz-Betrieb umstellen

> Dann ist in der delay_ms
> eine wartezeit in ms eingegeben. Wie errechnet man die exakte wartezeit
> in ms, so das die wartezeit wirklich in ms angegeben werden kann?

Gar nicht.
Du gibst einfach an, wieviele ms du haben willst und _delay_ms
macht das dann.
Aber beachte:
Die delay Funktion die du da hast, die schmeist du gleich
wieder weg und verwendest die, die mit dem Compiler mitgeliefert
wird. Kein Grund das Rad neu zu erfinden.


#define F_CPU 4000000

#include <avr/io.h>
#include <util/delay.h>

int main()
{
  ....

  _delay_ms( 10.0 );     // Warte 10 Millisekunden

  ....
}

Aber Achtung: Diese mitgelieferte Funktion hat eine Obergrenze.
Du kannst nicht beliebige Millisekunden anfordern. Die Obergrenze
ist von deiner Taktfrequenz abhängig und ist als Formel in delay.h
angegeben.
10 Millisekunden sind aber kein Problem. Wenn du daraus eine
ganze Sekunde machen willst (sowas macht man allerdings in einem
relaen Programm nicht), dann musst du halt 100 mal 10 Millisekunden
abwarten:

   for( i = 0; i < 100; ++i )
     _delay_ms( 10.0 );


(Den Optimizer des Compilers einschalten nicht vergessen, sonst
stimmen die Zeiten nicht)

von Sebastian (Gast)


Lesenswert?

Wie würde man das denn in einem realen prog. machen? Sagen wir mal man 
möchte 1000ms warten. Würde man eine solche Schleife nutzen?

Gibt es irgendwo eine übersicht über die vom Compiler oder von WinAVR 
zur verfügung gestellten methoden?

Habe mal in PonyProg die FUSEBits ausgelesen. CKSEL 3-1 haben ein 
häkchen, 0 nicht. Da das anscheinend invertierte logik ist, bedeutet das 
0001 wenn ich das nach der FUSEBIT seite deute bedeutet das internal 
QuarzOsz. wie zu erwarten.

von Andreas K. (a-k)


Lesenswert?

> Wie würde man das denn in einem realen prog. machen? Sagen wir mal man
> möchte 1000ms warten. Würde man eine solche Schleife nutzen?

Lässt sich so allgemein nicht beantworten. In einfachen Programmen ja, 
in komplexen Programmen arbeitet man eher mit Timer-Interrupts und 
dadurch gesetzten Erinnerungen.

> Gibt es irgendwo eine übersicht über die vom Compiler oder von WinAVR
> zur verfügung gestellten methoden?

Mit ein bischen Suche nach dem passenden Icon bei dir auf der Platte. 
Oder http://www.nongnu.org/avr-libc/user-manual/index.html.

von Sebastian (Gast)


Lesenswert?

Kann ich mit dem Internen Osz. auch höhere Frequenzen machen? Habe 
gerade gesehen das man beim AVR Fuse Calc
http://palmavr.sourceforge.net/cgi-bin/fc.cgi
auch 8MHz wählen kann. Geht das dann ohne ext. Quarz?

von Andreas K. (a-k)


Lesenswert?

> Kann ich mit dem Internen Osz. auch höhere Frequenzen machen?

Wie wär's mit einem Blick ins Datasheet? Dein Text über die Fuses deutet 
an, dass du immerhin mal reingesehen hast. Sowas steht da drin.

von Sebastian (Gast)


Lesenswert?

Jagut, also scheint der sogar 8MHz intern zu können. Man kann das ja 
sogar noch irgendwie kllibrieren wenn ichs richtig verstehe. Dann muss 
ich die bits jetzt auf 0100 für 8MHz setzen. Das wäre in Ponyprog X0XX 
bei CKSEL3-0 (X=Häkchen).

von Tracer (Gast)


Lesenswert?

was hast du denn an material benutzt um das obige progeamm zu schreiben? 
bin nämlich auch noch anfänger und muss mich erstmal reinfitzen deshlab 
bin ich für jeden vorschlag dankbar. hab schon tutorial gelesen aber der 
prinzipiele programmaufbau und wie ich an sowas rangeh ist mir noch 
nicht wirklich klar

von Sebastian (Gast)


Lesenswert?

Ich habe WinAVR installiert. Damit kannst du die make-Files und den 
Programmcode erstellen und dann auch kompilieren. Zum programmieren 
nutze ich PonyProg und einen einfachen ParallelPort Programmer. Das 
findest du alles kostenlos im Internet, bzw beim Programmer die 
Bauanleitung. Der Parallelport Programmer geht sogar nur mit 2 
Widerständen.
Programmcode habe ich mir einfach aus dem avr-gcc tutorial hier auf der 
seite zusammengesucht. Mein Code enthält viel was man erstmal nicht 
braucht, ich hab einfach nur alles, was ich interessant fand mit rein 
kopiert.

von Christoph E. (gluema)


Lesenswert?

wie lange hast du gesessen für alles?

von Karl H. (kbuchegg)


Lesenswert?

Christoph Erstmalegal wrote:
> wie lange hast du gesessen für alles?

Die Frage klingt so nach: Ich muss auf die Schnelle programmieren
lernen und möchte das so schnell wie möglich hinter mich bringen.

Ins Stammbuch geschrieben:
Für die ersten Schritte kann man schon ein paar Tage rechnen,
je nach persönlicher Eignung. Einen etwas fotgeschritteneren
Anfängerstatus erreicht man erst nach ein paar Wochen. So
einigermassen la-la wird man in der Programmierung erst nach
ein paar Monaten. Um mal eine Zahl zu nennen: sagen wir mal
6 - 9 Monate. Gut wird man nicht unter einem Jahr und wenn man
zu einem Experten aufsteigen will, dann reden wir von Jahren
(nicht unter 3).

Die Zahlen mögen je nach persönlicher Eigung und dem Willen
sich zu quälen variieren aber die Proportionen bleiben
erhalten.

Das soll jetzt aber niemanden abhalten, Softwareentwicklung
zu betreiben. Nur so, wie Lieschen Müller sich die Programmierung
vorstellt, so ist das nicht. Das mussten auch die Arbeitsämter
lernen, als sie vor Jahren Unsummen in 2 Monats Schnellsiederkurse
zur Umschulung auf Programmierer investierten. Rausgeschmissenes
Geld.

von Johannes M. (johnny-m)


Lesenswert?

Christoph Erstmalegal wrote:
> wie lange hast du gesessen für alles?
Wie, kommt man jetzt sogar in den Knast dafür;-? Vorbestraft wegen 
AVR-Vergewaltigung?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.