Hallo Leute,
Erstmal will ich betonen, dass ich euer Forum sehr informativ finde, und
dass es mir schon oft geholfen hat. Bisher hat mir die Suchfunktion
jedoch immer ausgereicht. Jetzt sehe ich mich mit einem Mysterium
konfrontiert. Ich versuche ein Programm, welches in einer (einwandfrei
funktionierenden) Bascom Variante vorliegt in GCC zu schreiben. Es geht
um die bedienung eines Modems, welches über das Speicherinterface am
AT90CAN128 Mikrocontroller angeschlossen ist-
Ich habe das Bascom Programm auf ein minimum reduziert. Das Modem soll
ein Interrupt auslösen, wenn ein Gültiges Paket hereinkommt. Die dazu
notwendige Initialisierung ist entsprechend dem Datenblatt des Modems
korrekt. In der Bascom Version funktioniert alles super und ich kriege
immer zuverlässige Interrupts.
Das GCC Programm ist in meinen Augen absolut identisch. Es verhält sich
jedoch anders. Es werden keine Interrupts ausgelöst. Es gibt jedoch
einen Trick der mich sehr verwirrt: Wenn ich zunächst das Bascom
Programm raufschreibe und ein Paar Interrupts provozere, und danach das
GCC Programm raufspiele, dann funktioniert es bis ich ein mal Reset
drücke. Danach werden wieder keine Interrupts ausgelöst. Wie gesagt, das
Bascom Programm läuft perfekt. Die Logik sagt mir dass ich irgend etwas
mit der Interrupt Initialisierung in GCC falsch mache. Ich finde meinen
Fehler jedoch nicht. Vielleicht könnt ihr mir helfen.
Anbei beide Quellcodes, die Header "LEDS.h" und "UART.h" dürften für das
Problem nicht von Belangen sein. Bei Bedarf poste ich die aber
ebenfalls.
Zunächst also das Bascom-Programm:
SET_REG(10496,0b01000101);//Wirkt sich aus, wie er sollte 4800
64
_delay_ms(1);
65
66
//Hier wird die grundsätzliche Initialisierung des Modems vollzogen
67
SET_REG(17664,0b00001000);
68
SET_REG(17664,0b00000001);
69
SET_REG(17408,0b11101110);
70
SET_REG(17664,0b11110001);
71
SET_REG(19200,0b10100001);
72
SET_REG(8448,0b10000100);
73
SET_REG(8192,0b10000000);
74
SET_REG(9216,0b10000000);
75
SET_REG(8960,0b01110101);
76
SET_REG(8704,0b00110000);
77
_delay_ms(10);
78
SET_REG(9728,0b11000000);
79
SET_REG(9472,0b10010000);
80
SET_REG(10240,0b10000111);
81
SET_REG(9984,0b00001100);
82
_delay_ms(1);
83
84
SET_REG(17664,0b11110101);
85
86
while(1)//Hauptschleife
87
{
88
SET_REG(16640,0b00000111);//RESET
89
Status_1=GET_REG(16640);//Auslesen
90
_delay_us(10);
91
SET_REG(17152,0b10000011);//Mode Reg
92
_delay_ms(1);
93
SET_REG(16896,0b01011100);//Hier schrauben
94
_delay_ms(10);
95
SET_REG(16640,0b00010000);
96
_delay_us(10);
97
98
do
99
{
100
}while(Modem_INT!=1);//Die schwierigkeit könnte hier liegen
101
102
Modem_INT=0;
103
104
Status_1=GET_REG(16640);
105
_delay_us(20);
106
printf("/////////////////////////////////\n");
107
printf("Status 1: %i\n",Status_1);
108
Status_2=GET_REG(17152);
109
_delay_us(20);
110
printf("Status 2: %i\n",Status_2);
111
112
}
113
return0;
114
}
115
116
117
118
ISR(INT0_vect)
119
{
120
Modem_INT=1;//Flag setzen
121
}
Ich sitze schon mehrere Tage an dem Problem und bin langsam ratlos.
Wahrscheinlich ist es irgend ein Anfänger-Fehler den ich einfach nicht
sehe. Hoffe ihr könnt mir helfen, vielen Dank.
> Wenn ich zunächst das Bascom> Programm raufschreibe und ein Paar Interrupts provozere, und danach das> GCC Programm raufspiele, dann funktioniert es bis ich ein mal Reset> drücke. Danach werden wieder keine Interrupts ausgelöst. Wie gesagt, das> Bascom Programm läuft perfekt. Die Logik sagt mir dass ich irgend etwas> mit der Interrupt Initialisierung in GCC falsch mache.
Wahrscheinlicher, daß Basic- und C-Programm das Modem unterschiedlich
initialisieren.
Versuch mal folgendes:
1
voidSET_REG(uint16_tADDRESS,uint8_tValue)
2
{
3
volatileuint8_t*p;
4
p=(uint8_t*)ADDRESS;
5
*p=Value;
6
7
}
8
9
uint8_tGET_REG(uint16_tADDRESS)
10
{
11
uint8_tValue;
12
volatileuint8_t*p;
13
p=(uint8_t*)ADDRESS;
14
Value=*p;
15
_delay_us(20);
16
returnValue;
17
}
Also p jeweils volatile deklarieren.
> Anbei beide Quellcodes, die Header "LEDS.h" und "UART.h" dürften für das> Problem nicht von Belangen sein. Bei Bedarf poste ich die aber> ebenfalls.
Hallo,
Anbei die fehlenden Header. Das mit dem "volatile" werde ich in einer
Stunde ausprobiert haben, dann meld ich mich nochmal, hört sich aber
plausibel an, ich habe auch schon die Vermutung gehabt dass meine
Umsetzung der "Out"- und "Inp"-Bascom Befehle sich in C ein wenig
unterscheiden könnte. Danke erstmal.
Ohne volatile weiß der Compiler nicht, daß er die Zugriffe auf die
Modemregister nicht (weg-) optimieren darf. Die Adresse 17664 wird z.B.
4 mal beschrieben. Der Compiler schreibt ohne volatile aber nur den
letzen,
für ihn entgültigen Wert.
Lesen kann er sich ohne volatile ganz sparen, weil er ja weiß, was er
vorher
reingeschrieben hat, oder weil der Wert im weiteren Programmverlauf
nicht
verwendet wird.
> Bascom hat mein Gehirn zerfressen.g
Hier noch ein paar Vorschläge, damits noch weniger bascomisch und etwas
C-iger wird:
* In Headerdateien (*.h) nur Deklarationen, keine Funktionsdefinitionen.
Ausnahme: "static inline".
* Ausschließlich großgeschriebene Bezeichner nur für Makros (#define)
verwenden.
* Die Funktionen SET_REG() und GET_REG() braucht man nicht.
Wenn man sie doch verwenden will (Geschmacksache), dann aber klein
geschrieben, da es ja keine Macros sind.
Im Anhang sieht man vielleicht besser, was ich meine.
Du kannst die SET_REG und GET_REG Funktionen weglassen und das ganze
viel lesbarer machen, indem Du die Registeradressen über #defines
festlegst
Register im h-File definieren:
>Du kannst die SET_REG und GET_REG Funktionen weglassen und das ganze>viel lesbarer machen, indem Du die Registeradressen über #defines>festlegst
Das ergibt zudem deutlich kleineren und schnelleren Code als wenn Du es
mit Funktionen machst...
> Das ergibt zudem deutlich kleineren und schnelleren Code als wenn Du es> mit Funktionen machst...
Das nicht, da der Compiler aus den Funktionen den exakt gleichen Code
erzeugt.
Jedenfalls wenn er wie hier die Funktionen inlinen kann.