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?
Max schrieb: > Dafür ist doch das MCU, oder? Wenn man jetzt noch wüsste was MCU in deinem makefile genau macht...
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.
:
Bearbeitet durch Moderator
Frank M. schrieb: > Zeig doch einfach mal, welche Befehle (avr-gcc ....) beim Ausführen des > Makefiles ausgeführt werden. Hier bitteschön:) Compiling C: main.c avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o Linking: main.elf avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -MMD -MP -MF .dep/main.elf.d main.o uart.o TxtFunc.o --output main.elf -Wl,-Map=main.map,--cref -lm
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.
:
Bearbeitet durch Moderator
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.
1 | #include <ctype.h> |
2 | #include <inttypes.h> |
3 | #include <avr\io.h> |
4 | #include <avr\pgmspace.h> // <--#include <progmem.h> |
5 | |
6 | #include <stdio.h> |
7 | #include <math.h> |
8 | #include <stdlib.h> |
9 | #include <stdarg.h> |
10 | #include <string.h> |
11 | #include <avr\interrupt.h> // obsolete #include <avr\signal.h> |
12 | |
13 | #include <avr\wdt.h> |
14 | //Produziert Fehler...
|
15 | #include <util\delay.h> //_delay_loop_1 _delay_loop_2 delay_ms |
16 | |
17 | #include "avr_register.h" //with Hardware assigns |
18 | #include "main.h" //witdh Hardware assigns |
19 | #include "uart.h" |
20 | #include "TxtFunc.h" |
21 | #include "avr\iom32.h" |
22 | |
23 | |
24 | |
25 | // Hardwareassignment
|
26 | #define UART_BAUD_RATE 9600 /* 9600 baud */ |
27 | //#define UART_BAUD_RATE 19200
|
28 | //#define UART_BAUD_RATE 57600
|
29 | |
30 | #ifdef TIMER_TICK_USED
|
31 | void StartTickTimer(void); //0.1 Seconds interrupt |
32 | #endif
|
33 | |
34 | //CONSTANT ARRAYs IN .TEXT = ROM ARREA .DATA IST SRAM !! .BSS SRAM
|
35 | //const char MCA_DELIMTERSTR[] PROGMEM = { ',',0 };
|
36 | |
37 | volatile uint32_t gu32_Ticks; //T2 timeCounter, only NN_Counter for Keypressings |
38 | |
39 | #ifdef Board_V2G_HARDWARE_POLLING
|
40 | uint8_t gu8ProgMode = 0; |
41 | #define PROG_Mode_BLINK_LED 0x01
|
42 | |
43 | #endif
|
44 | |
45 | |
46 | #ifdef TIMER_TICK_USED
|
47 | // ****************************************************************
|
48 | //volatile SIGNAL(TIMER2_OVF_vect) //oder SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit SEI am Anfang
|
49 | SIGNAL( TIMER2_OVF_vect ) //oder SIGNAL--INTERRUPT(SIG_OVERFLOW2) = mit SEI am Anfang |
50 | // *******************************************************************
|
51 | {
|
52 | sei(); |
53 | //cli();/
|
54 | gu32_Ticks++; |
55 | #ifdef UART_USE_ENABLED
|
56 | UART_TXRX_Check(); //IMMER VORNAHANDEN !! IN ALLEN LOOPS DIE ZEIT BRAUCHEN |
57 | #endif
|
58 | };
|
59 | #endif
|
60 | |
61 | |
62 | |
63 | // *************************************
|
64 | void StartTickTimer(void) //0.1 Seconds interrupt |
65 | //Normal MODE OC2 Disconnect Prescale 64
|
66 | // *************************************
|
67 | {
|
68 | unsigned char sreg; |
69 | sreg = SREG; //loakaler Speicher |
70 | cli(); |
71 | TIMSK &= ~( TIMSK_TOIE2_FLAG | TIMSK_OCIE2_FLAG ); |
72 | gu32_Ticks = 0; |
73 | OCR2 = 0; |
74 | TCNT2 = 0; //Timer MAX = TOP Compare |
75 | TIFR |= TIFR_OCF2_OUTP_COMPARE_FLAG | TIFR_TOV2_TIMER_OVERFLOW_FLAG ; // zum löschen setzen! |
76 | //TIMER STARTS with Presscale Select = 64
|
77 | TCCR2 = TCCR2_CLK_256; // 0000 0100//Timer Counter CTRL -- NORMAL MODE=NO OCR2 |
78 | //TCCR2 = TCCR2_CLK_0; //
|
79 | TIMSK |= TIMSK_TOIE2_FLAG; //_BV(TOIE2); // BESSER == OVERFLOW |
80 | SREG = sreg; |
81 | sei(); |
82 | };
|
83 | |
84 | |
85 | |
86 | |
87 | // *******************************************************************
|
88 | int main(void) |
89 | // *******************************************************************
|
90 | {
|
91 | static uint32_t u32Now; |
92 | //static uint16_t u16Toggle;
|
93 | |
94 | //INITS
|
95 | cli();//The global interrupt flag is maintained in the I bit of the status register (SREG). |
96 | |
97 | |
98 | //INIT HARDWARE
|
99 | //USing of PORTOUTS 1=OUT, 0=IN
|
100 | DDRA = 0xFF; // 00 ist Eingang, FF ist Ausgang |
101 | PORTA = 0x00; |
102 | DDRB = 0xFF; |
103 | PORTB = 0x00; |
104 | DDRC = 0xFF; //Port C auf FF |
105 | PORTC = 0x00; |
106 | |
107 | #ifndef Board_V2G_HARDWARE_POLLING
|
108 | DDRD = 0x02; |
109 | PORTD = 0x02; |
110 | #else
|
111 | DDRD = PORTD_DDRX_BOARD_V2G_AUX_MSK; |
112 | PORTD = PORTD_BOARD_V2G_AUX_PULLUP_MSK; |
113 | #endif
|
114 | //SFIOR = (1<<PUD); //Pullup Disable
|
115 | |
116 | StartTickTimer(); //8 Bit Timer 2 = MS Tick Counter |
117 | //Pointer and Strings init
|
118 | wdt_enable(WDTO_2S); //Set 1.9Sec WatchDog ENABLE |
119 | wdt_reset(); //WATCHDOG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
120 | |
121 | u32Now = 0; |
122 | gu32_Ticks = 0; |
123 | |
124 | uint8_t u8NN = 0; |
125 | uint8_t flagge7 = 0; |
126 | |
127 | sei(); |
128 | |
129 | // ************ MAIN LOOP FOR EVER *********************
|
130 | for (;;) /* loop forever */ //Aber schnell > 200.000 mal/Sekunde |
131 | {
|
132 | wdt_reset(); //WATCHDOG! |
133 | |
134 | |
135 | //Hier kann was gemacht werden jede 1 Sekunde
|
136 | if( (gu32_Ticks -u32Now) > PULS_50MS_TICK ) |
137 | {
|
138 | u32Now = gu32_Ticks; //Zeit merken !! |
139 | |
140 | if (flagge7 == 0) |
141 | {
|
142 | u8NN++; |
143 | }
|
144 | else
|
145 | {
|
146 | u8NN--; |
147 | }
|
148 | |
149 | u8NN %= 8; |
150 | PORTB = (1 << u8NN); |
151 | |
152 | |
153 | if (u8NN == 0) |
154 | {
|
155 | flagge7 = 0; |
156 | }
|
157 | |
158 | if (u8NN == 7) |
159 | {
|
160 | flagge7 = 1; |
161 | }
|
162 | |
163 | |
164 | // uart_puts_p( PSTR("TimerTick="));
|
165 | // PrintLongCR( gu32_Ticks );
|
166 | }; // Tickcounter |
167 | |
168 | }; //main loop Ende |
169 | };
|
170 | // ******************* MAIN END ********************************************
|
171 | |
172 | }
|
Max schrieb: > iom32c1.h oder iom32hvb.h Das sind völlig andere Controller. Der Mega32C1 z.B. ist einer mit 32 Pins und CAN.
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.
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?
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:
1 | #define TIMSK_TOIE0_FLAG 0x01
|
2 | #define TIMSK_OCIE0_FLAG 0x02
|
3 | #define TIMSK_TOIE1_FLAG 0x04
|
4 | #define TIMSK_OCIE1B_FLAG 0x08
|
5 | #define TIMSK_OCIE1A_FLAG 0x10
|
6 | #define TIMSK_TICIE1_FLAG 0x20
|
7 | #define TIMSK_TOIE2_FLAG 0x40
|
8 | #define TIMSK_OCIE2_FLAG 0x80
|
Laut http://www.gaw.ru/pdf/Atmel/app/avr/AVR089.pdf sind die Timer-Register im 32er und 16er aber identisch.
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 | int main() |
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?
:
Bearbeitet durch User
Karl Heinz schrieb: > 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 | > ... |
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.
:
Bearbeitet durch Moderator
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..
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.