Hi Leute,
Ein einfaches C-Programm (LEDs blinken), das auf meinem ATmega16 läuft
(mit externem 16'000-Quarz), läuft auf dem ATmega32 (auf dem selben
Board, einfach ausgetauscht) nicht. Das Programm wurde von AVRdude über
ISP erfolgreich auf den Controller geschrieben, allerdings bleiben die
LEDs dunkel.
Folgendes habe ich für den Umstieg gemacht:
- Den Controller am Board ausgetauscht.
- Ich habe mit den Fusebits die identischen Einstellungen gesetzt wie am
ATmega16. Einziger Unterschied: Boot Flash Section size = 256 (statt 128
wie beim 16er, da nicht möglich). Ist das vielleicht das Problem?
- Ich habe in meinem Makefile MCU = atmega16 durch MCU = atmega32
ersetzt.
- Ich habe mich über die Unterschiede informiert: Manche Vektoren sind
anders definiert, sollte aber in C-Programmen egal sein, oder?
Kann mir jemand helfen oder Tipps zur Fehlersuche geben? Hab ich was
vergessen?
Viele Grüße
Wenn man jetzt noch wüsste was MCU in deinem makefile genau macht...
Der Prozessor muss an zwei Stellen bekannt sein:
- beim Compiler/Linkeraufruf, um den für die Architektur geeigneten Code
zu erzeugen
- im Quellcode selbst muss ein Makro bekannt sein, damit der richtige
Header (und damit die Adressen der I/O-Register) eingebunden werden.
Haro schrieb:> - beim Compiler/Linkeraufruf, um den für die Architektur geeigneten Code> zu erzeugen
Dafür ist doch das MCU, oder?
Haro schrieb:> - im Quellcode selbst muss ein Makro bekannt sein, damit der richtige> Header (und damit die Adressen der I/O-Register) eingebunden werden.
ich hab das avr\io.h in main.c eingebunden, das sollte ja dann mithilfe
des MCU automatisch auf das iom32.h zugreifen und auch die Makros
richtig definieren?
Zeig doch einfach mal, welche Befehle (avr-gcc ....) beim Ausführen des
Makefiles ausgeführt werden. Dann sehen wir ja, ob die Konstante MCU im
Makefile in die richtigen avr-gcc-Optionen mündet.
Die avr-gcc-Aufrufe sehen korrekt aus.
Max schrieb:> - Ich habe mit den Fusebits die identischen Einstellungen gesetzt wie am> ATmega16. Einziger Unterschied: Boot Flash Section size = 256 (statt 128> wie beim 16er, da nicht möglich). Ist das vielleicht das Problem?
Solange nicht BOOTRST aktiviert ist, spielt die Boot Flash Section size
keine Rolle.
Apropos.... zeig doch einfach mal die Fuses-Werte.
Und bitte auch das Blink-Programm, also main.c.
Im include-Verzeichnis von avr sind neben dem iom32.h noch viele weitere
für den 32er, zb. iom32c1.h oder iom32hvb.h . Gibt es da einen
Unterschied zwischen verschiedenen Controllern, oder wofür existieren so
viele verschiedene?
Max schrieb:> Im include-Verzeichnis von avr sind neben dem iom32.h noch viele weitere> für den 32er, zb. iom32c1.h oder iom32hvb.h . Gibt es da einen> Unterschied zwischen verschiedenen Controllern, oder wofür existieren so> viele verschiedene?
Bei
http://www.engbedded.com/fusecalc
zum Berechnen von Fuse-Werten finde ich alleine schon 8 verschiedene
ATmega32, die sich von den Fuse-Bits ziemlich stark unterscheiden.
Welchen ATmega32 hast Du denn jetzt?
Frank M. schrieb:> Apropos.... zeig doch einfach mal die Fuses-Werte.
Low Fuse: 0xBF
High Fuse: 0xCF
Extended Fuse: --
Lock Fuse 0xFF
Frank M. schrieb:> Und bitte auch das Blink-Programm, also main.c.
Das Programm ist etwas vermüllt, ist eine Bastel-Datei. Funktioniert
aber definitiv mit dem ATmega16.
Ja, "vermüllt" kann man es durchaus nennen.
Ich bekomme das Programm gar nicht compiliert, weil mir deine privaten
Includes
1
#include"avr_register.h" //with Hardware assigns
2
#include"main.h" //witdh Hardware assigns
3
#include"uart.h"
4
#include"TxtFunc.h"
fehlen.
Das hier:
1
#include"avr\iom32.h"
solltest Du auf keinen Fall machen, weil Dein Quelltext dann
hardware-abhängig wird.
Stattdessen ist richtig:
1
#include<avr/io.h>
Dieses generische io.h zieht dann das processor-spezifische Include
selbst nach. Also überlasse die Entscheidung bitte dem Compiler, welches
Include für Deinen Processor richtig ist.
Fällt Dir etwas am Schrägstrich auf? Es muss ein Slash und kein
Backslash sein in C-Programmen. Viele Windows-User machen das falsch,
weil sie an ihren Windows-Explorer denken. Wenn Du aber z.B. an URLs
denkst, die Betriebssystem-unabhängig sind, wird ein Slash ('/')
verwendet. Denke bitte ein wenig "globaler" ;-)
Also bitte ersetze generell die '\' durch '/' in den
include-Anweisungen.
Das waren aber alles erstmal nur technische Hinweise. Zum eigentlichen
Programm kann ich nichts inhaltliches sagen, weil die oben genannten
Includes fehlen bzw. sehr viel Zeugs im Quelltext steht, der mit Deinem
Problem, LEDs zum Blinken zu bewegen, gar nichts zu tun hat. Das fängt
mit dem uart.h an und hört mit fehlenden Konstanten auf.
Max schrieb:> Frank M. schrieb:>> Welchen ATmega32 hast Du denn jetzt?>> ATMEGA32-16PU im DIP-40-Gehäuse. Der entspricht meines Wissens auf> http://www.engbedded.com/fusecalc dem ATmega32 ohne Zusatz. Irre ich> mich?
Nein, ist okay.
Die Ursache, warum das Programm nicht läuft, könnte in Deinem privaten
avr_register.h versteckt sein, denn da werden offenbar die Konstanten:
TIMSK_TOIE2_FLAG
TIMSK_OCIE2_FLAG
TIFR_OCF2_OUTP_COMPARE_FLAG
TIFR_TOV2_TIMER_OVERFLOW_FLAG
TIMSK_TOIE2_FLAG
definiert. Ich kenne sie jedenfalls nur ohne den Zusatz _FLAG.
Zeig bitte mal avr_register.h.
Frank M. schrieb:> Das waren aber alles erstmal nur technische Hinweise. Zum eigentlichen> Programm kann ich nichts inhaltliches sagen,
Vielen Dank für die Tipps!
Das iom32.h hab ich tatsächlich erst eingefügt, als ich feststellte,
dass nix geht.
Das mit dem Programm ist richtig, ich hab vieles noch in der main.h
definiert. Allerdings läuft es ja am 16er. Ebenso andere bereits
getestete Programme. Aber am 32er geht keines davon. Der Fehler muss
woanders liegen.
Danke für die Hilfe bisher!
Frank M. schrieb:> Zeig bitte mal avr_register.h.
Das gesamte avr_regiser.h würde den Rahmen sprengen.
Die _FLAG dienen nur der Übersicht, um nicht immer im Datenblatt
nachschauen zu müssen. Hier die relevanten:
Max schrieb:> Frank M. schrieb:>> Zeig bitte mal avr_register.h.>> Das gesamte avr_regiser.h würde den Rahmen sprengen.>> Die _FLAG dienen nur der Übersicht, um nicht immer im Datenblatt> nachschauen zu müssen.
?
Wer muss denn sowas im Datanblatt nachsehen? Kein Mensch.
Genau dafür gibt es den include für avr/io.h bzw. die restlichen, damit
man genau das nicht machen muss.
> Hier die relevanten:
Die hättest du dir alle sparen können. Wenn man sich schon solche Dinge
macht, dann wenigstens so
1
#define TIMSK_TOIE0_FLAG (1<<TOIE0)
2
#define TIMSK_OCIE0_FLAG (1<<OCIE0)
3
#define TIMSK_TOIE1_FLAG (1<<TOIE1)
4
#define TIMSK_OCIE1B_FLAG (1<<OCIE1B)
5
#define TIMSK_OCIE1A_FLAG (1<<OCIE1A)
6
...
mit anderen Worten:
Du tust einen Teufel und wirst die Zahlenwerte selbst hinschreiben!
Statt dessen basierst du alles auf den Konstanten, die du mit den
Standard AVR Includes sowieso kriegst. Denn die stimmen nämlich, ohne
dass jetzt jemand für dich den Code durchsuchen und deinen Tippfehler
suchen muss.
> Allerdings läuft es ja am 16er.
Das ist nur insofern interessant, als es zur Fehlersuche komplett
irrelevant ist.
Schreib ein ordentliches einfaches Testprogramm, dass du in deinen M32
brennen kannst und nicht so einen vermüllten Dreck, bei dem sich vorne
und hinten keiner auskennt und man erst mal Stunden damit verbringen
müsste, das alles auseinanderzuklamüsern.
Es hat schon seinen Grund, warum immer die 'Programmierer' mit dem
scheuslichsten Source Code auch diejenigen sind, die dann immer die
seltsamsten Fehler haben.
Was ist so schlimm an ...
1
#define F_CPU 16000000UL
2
3
#include<avr/io.h>
4
#include<utils/delay.h>
5
6
7
intmain()
8
{
9
DDRB=0xFF;
10
11
while(1){
12
PORTB=0x00;
13
_delay_ms(500);
14
PORTB=0x0F;
15
_delay_ms(500);
16
}
17
}
Ist das zu einfach? zu banal? zu simpel, dass man da einfach mal sehen
könnte, ob deine M32 grundsätzlich laufen? Nicht technisch genug? So
einfach, dass auch deine Oma den Code verstehen könnte? Zu wenig
Möglichkeiten für Fehler?
Karl Heinz schrieb:> Die hättest du dir alle sparen können. Wenn man sich schon solche Dinge> macht, dann wenigstens so>>
1
>#defineTIMSK_TOIE0_FLAG(1<<TOIE0)
2
>#defineTIMSK_OCIE0_FLAG(1<<OCIE0)
3
>#defineTIMSK_TOIE1_FLAG(1<<TOIE1)
4
>#defineTIMSK_OCIE1B_FLAG(1<<OCIE1B)
5
>#defineTIMSK_OCIE1A_FLAG(1<<OCIE1A)
6
>...
7
>
Eben. Nur so macht man sich unabhängig von einem konkreten µC. Ich weiß
jetzt nicht, ob diese Bits in ATmega32 und ATmega16 zufällig identisch
ist. Aber genau sowas könnte schon der Grund sein, warum es beim TO
nicht läuft. Ich hatte schon gestern befürchtet, dass da konkrete Zahlen
drinstehen. Also weg mit diesem Include und direkt die bereits
vorhandenen Preprocessor-Konstanten benutzen. Dafür sind sie ja da.
> mit anderen Worten:> Du tust einen Teufel und wirst die Zahlenwerte selbst hinschreiben!> Statt dessen basierst du alles auf den Konstanten, die du mit den> Standard AVR Includes sowieso kriegst.
Ich nehme mal an, der TO wusste bis dato noch gar nicht, dass es solche
Konstanten schon fix und fertig gibt ;-)
Gruß,
Frank
@ Frank M. (ukw) Benutzerseite
>> #define TIMSK_TOIE0_FLAG (1<<TOIE0)>> #define TIMSK_OCIE0_FLAG (1<<OCIE0)>> #define TIMSK_TOIE1_FLAG (1<<TOIE1)>Eben. Nur so macht man sich unabhängig von einem konkreten µC.
Schöne Illusion ;-)
> Ich weiß>jetzt nicht, ob diese Bits in ATmega32 und ATmega16 zufällig identisch>ist.
Sind sie. Aber zwischen den etwas älteren ala ATmega8 und neueren ala
Atmega88 gibt es genügend Unterschiede, dass dieses Konzept nicht
aufgeht. Andere Prozessoren ala MSP430 sind da deutlich besser, weil sie
WIRKLICH einheitliche, orthogonale Peripherie und dazugehörige Register
haben.
Wenn man WIRKLICH CPU-unabhängig werden will ala Arduino, muss man
DEUTLICh mehr in die HAL (hardware abstraction layer) stecken, was
teilweise auch mit größeren Leistungsverlusten erkauft wird.
Falk Brunner schrieb:>>Eben. Nur so macht man sich unabhängig von einem konkreten µC.> Schöne Illusion ;-)
Du hast schon recht, allein schon deshalb, weil die
Preprocessor-Konstanten nicht bei allen ATmegas/ATTiny gleich heißen.
Ich weiß das schon, trotzdem ist mit der Vermeidung von konkreten
Zahlenwerten schon einiges gewonnen.
>> Ich weiß>>jetzt nicht, ob diese Bits in ATmega32 und ATmega16 zufällig identisch>>ist.>> Sind sie.
Will ich gar nicht wissen, würde mich nur belasten. ;-)
Es reicht, wenn ich weiß, dass es dafür Preprocessor-Konstanten gibt,
die genau das tun, was sie sollen.
> Aber zwischen den etwas älteren ala ATmega8 und neueren ala> Atmega88 gibt es genügend Unterschiede, dass dieses Konzept nicht> aufgeht.
Stimmt. Wenn ich mir die Preprocessor-Orgie anschaue, die ich mir im
IRMP/IRSND angetan habe, um sämtliche PWM-Konstellationen auf allen
gebräuchlichsten ATmegas/ATTinys einheitlich abzubilden, wäre das
eigentlich schon ein Grund, die µC-Familie zu wechseln ;-)
> Wenn man WIRKLICH CPU-unabhängig werden will ala Arduino, muss man> DEUTLICh mehr in die HAL (hardware abstraction layer) stecken, was> teilweise auch mit größeren Leistungsverlusten erkauft wird.
Wenn man alles über den Preprocessor abwickeln kann, kommt es gar nicht
zu Leistungsverlusten. Aber der Code sieht dann ziemlich grausig aus,
siehe zum Beispiel irsnd.c aus dem IRMP-Projekt.
http://www.mikrocontroller.net/svnbrowser/irmp/irsnd.c?view=markup
EDIT: Muss aber hinzufügen, dass der Code nicht nur auf AVR, sondern
auch auf PIC und ARM (STM32), auf Dateibasis zum Debuggen auch noch auf
Linux und Windows läuft.
So, hatte grade wieder Zeit.
Mit nem komplett neu aufgesetzen Programm gehts tatsächlich. Vielen Dank
für eure Hilfe!
Rein aus Interesse: Kann sich jemand vorstellen, warum es auf
Pin-gleichen Controllern (16 und 32), die (bis auf 2 Register und leicht
andere Vektoren) augenscheinlich identisch zu behandeln sind, dazu
kommen kann, dass ein Programm auf dem einen läuft und dem anderen
nicht?
Würde mich interessieren..