Forum: Mikrocontroller und Digitale Elektronik Funktionsparameter


von Marci (Gast)


Lesenswert?

Seid gegrüßt,

könnte mir event. jemand sagen, wo hier genau der Fehler liegen könnte?:
1
>Hauptprogramm
2
3
lcdScreen(0);
1
>lcdRoutines.h
2
3
void lcdScreen(uint8_t screenX)
4
{
5
    uint8_t xpos = 0;
6
    uint8_t ypos = 0;
7
8
    if(screenX == 0)
9
    {
10
        //lcdClear();
11
        lcdSetPos(86,0);
12
        lcdString8("[press >]");
13
14
        lcdSetPos(10,16);
15
        lcdString8("Dynasoft'");
16
17
        ypos = 24;
18
        lcdSetPos(19,ypos);
19
        for(uint8_t m=0; m<=2; m++)
20
        {
21
            for(uint8_t n=0; n<=90; n++)
22
            {
23
                lcdSendData(myFontStart[m][n]);
24
            }
25
            lcdSetPos(19,ypos += 8); // Y-Position um ein Byte (eine Zeile) weitersetzen
26
        }
27
    }
28
    else if(screenX == 1)
29
    {
30
        //lcdClear();
31
        xpos = 0;
32
        lcdSetPos(xpos,8);
33
        lcdString8("Neonröhre 1");
34
    }
35
}

Beim Starten des Programms wird lcdScreen(0) aufgerufen und wie 
gewünscht die erste if-Anweisung erfolgreich abgearbeitet (und eine 
Grafik auf das LCD gezeichnet).
Wird aber nun in der main.c, durch z.B. einen Taster, lcdScreen(1) 
aufgerufen, geschieht nix weiter (bzw. das LCD setzt kurz aus und lädt 
den Startbildschirm noch einmal).
Mittels eines USART_sendeByte()-Befehls wurde mir im Terminal "Dy" 
angezeigt - und ich habe nirgendwo etwas dazu gefunden.
Jemand eine Ahnung, was da los ist?
Aus irgendeinem Grund wird der Parameter "1" (bzw. überhaupt irgendein 
Parameter der Funktion) nicht übertragen?!??? - obwohl ich doch nach dem 
Kapitel "Funktionsdef./-deklarationen im C-Buch gearbeitet habe.

LG, Marcel

: Gesperrt durch User
von holger (Gast)


Lesenswert?

>könnte mir event. jemand sagen, wo hier genau der Fehler liegen könnte?:

Nein, hier sind keine Hellseher unterwegs.
Kompletten Sourcecode posten oder Fehler selber suchen.

von Marci (Gast)


Lesenswert?

Hier die Referenzen...

main.c
1
#ifndef F_CPU
2
#define F_CPU 16000000
3
#endif
4
/*******************************************************************************************************/
5
// Einbindung von Standardbibliotheken
6
#include <stdint.h>        // Datentypen (standardisiert)
7
#include <avr/io.h>        // Registernamen
8
#include <avr/interrupt.h>
9
#include <stdio.h>         // Rechenoperationen, etc.
10
#include <stdlib.h>
11
#include <string.h>        // Zeichenketten-Funktionen
12
#include <util/delay.h>
13
14
// Einbindung der Header-Files
15
#include "usart.h"
16
17
#include "lcdFonts.h"
18
#include "lcdRoutines.h"
19
20
/*******************************************************************************************************/
21
// Definition von PORTpins, Masken und Konstanten
22
#define KEY_DDR      DDRK
23
#define KEY_PORT     PORTK
24
#define KEY_PIN      PINK
25
#define KEY1         0
26
#define KEY2         1
27
#define KEY3         2
28
#define KEYU         3
29
#define KEYL         4
30
#define KEYX         5
31
#define KEYR         6
32
#define KEYD         7
33
#define ALL_KEYS     (1<<KEY1 | 1<<KEY2 | 1<<KEY3 | 1<<KEYU | 1<<KEYL | 1<<KEYX | 1<<KEYR | 1<<KEYD)
34
35
#define REPEAT_MASK  (1<<KEY1 | 1<<KEY2)
36
#define REPEAT_START 50
37
#define REPEAT_NEXT  20
38
39
#define LED_DDR      DDRL
40
#define LED_PORT     PORTL
41
#define LED0         0
42
#define LED1         1
43
#define LED2         2
44
#define LED3         3
45
#define LED4         4
46
#define LED5         5
47
#define LED6         6
48
#define LED7         7
49
50
volatile uint8_t key_state; // debounced and inverted key state: bit = 1: key pressed
51
volatile uint8_t key_press; // key press detect
52
volatile uint8_t key_rpt;   // key long press and repeat
53
/*******************************************************************************************************/
54
ISR(TIMER0_OVF_vect)                                          // every 10ms
55
{
56
    static uint8_t ct0, ct1, rpt;
57
    uint8_t i;
58
59
    TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
60
61
    i = key_state ^ ~KEY_PIN;                                 // key changed ?
62
    ct0 = ~(ct0 & i);                                         // reset or count ct0
63
    ct1 = ct0 ^ (ct1 & i);                                    // reset or count ct1
64
    i &= ct0 & ct1;                                           // count until roll over ?
65
    key_state ^= i;                                           // then toggle debounced state
66
    key_press |= key_state & i;                               // 0->1: key press detect
67
68
    if((key_state & REPEAT_MASK) == 0)                        // check repeat function
69
        rpt = REPEAT_START;                                   // start delay
70
    if(--rpt == 0)
71
    {
72
        rpt = REPEAT_NEXT;                                    // repeat delay
73
        key_rpt |= key_state & REPEAT_MASK;
74
    }
75
}
76
/*******************************************************************************************************/
77
// check if a key has been pressed. Each pressed key is reported
78
// only once
79
//
80
uint8_t get_key_press(uint8_t key_mask)
81
{
82
    cli();                                          // read and clear atomic !
83
    key_mask &= key_press;                          // read key(s)
84
    key_press ^= key_mask;                          // clear key(s)
85
    sei();
86
    return key_mask;
87
}
88
/*******************************************************************************************************/
89
// check if a key has been pressed long enough such that the
90
// key repeat functionality kicks in. After a small setup delay
91
// the key is reported beeing pressed in subsequent calls
92
// to this function. This simulates the user repeatedly
93
// pressing and releasing the key.
94
uint8_t get_key_rpt(uint8_t key_mask)
95
{
96
    cli();                                          // read and clear atomic !
97
    key_mask &= key_rpt;                            // read key(s)
98
    key_rpt ^= key_mask;                            // clear key(s)
99
    sei();
100
    return key_mask;
101
}
102
/*******************************************************************************************************/
103
uint8_t get_key_short(uint8_t key_mask)
104
{
105
    cli();                                          // read key state and key press atomic !
106
    return get_key_press(~key_state & key_mask);
107
}
108
/*******************************************************************************************************/
109
uint8_t get_key_long(uint8_t key_mask)
110
{
111
    return get_key_press(get_key_rpt(key_mask));
112
}
113
/*******************************************************************************************************/
114
uint16_t val_PWM5a;
115
uint16_t val_PWM5b;
116
117
/*******************************************************************************************************/
118
int main(void)
119
{
120
    KEY_DDR &= ~ALL_KEYS;         // Konfiguration der Taster auf "Eingang"
121
    KEY_PORT |= ALL_KEYS;         // PullUp-Festlegung
122
123
    TCCR0B = (1<<CS02)|(1<<CS00); // Einstellung von Timer/Vorteiler: 1024
124
    TIMSK0 = 1<<TOIE0;            // Aktivierung des Timer-Interrupts
125
126
    LED_DDR = 0xFF;               // Konfiguration der LEDs auf "Ausgang"
127
    LED_PORT = 0xFF;              // LEDs auf logisch 1 setzen
128
129
130
131
    DDRB = 0xff;
132
    /***************************************************************************************************/
133
    // PWM-Grundeinstellungen:
134
    // Modi-Festlegung der Timer/Counter auf nicht-invertierende 10-Bit PWMs:
135
  // COMnxn = Ausgabeart des PWM-Signals (pro PWM-Kanal)
136
  // WGMnn = Pulsweiten-Modulatorbits, um den PWM-Modus zu aktivieren (pro Timer)
137
//  TCCR5A = (1<<COM5A1) | (1<<COM5B1) | (1<<WGM52) | (1<<WGM51) | (1<<WGM50);
138
  // Generierung eines Taktes von CK/1024 (Vorteiler)
139
//  TCCR5B = (1<<CS52) | (1<<CS50);
140
    // Festlegung der PWM-Startwerte
141
//    val_PWM5a = 0;
142
//    val_PWM5b = 0;
143
  // Einstellung des Top- bzw. Compare-Wertes (jeweils in Relation zur Taktlänge):
144
  // OCRnx = Pulsbreite (pro PWM-Kanal)
145
//  OCR5A = val_PWM5a; //OCR5B = val_PWM5b;
146
    /***************************************************************************************************/
147
    // Initialisierung des Displays
148
    lcdInitPort();
149
  lcdInit();
150
  lcdClear();
151
  PortLcdCtrl |= 0b00100000; // Aktivierung der Hintergrundbeleuchtung
152
    // Laden des LCD-Startbildschirms
153
    lcdScreen(0);
154
    /***************************************************************************************************/
155
    // Initialisierung des USART
156
    USART_Init();
157
    USART_SendString("Dynasoft' autoDesk gestartet.");
158
    //USART_ReceiveByte();
159
    /***************************************************************************************************/
160
  while(1)
161
    {
162
        // USART-Abfrage
163
        /*if(UDR1 == 1)
164
        {
165
            PORTL ^= (1<<PL1);
166
        }
167
        else if(UDR1 == 2)
168
        {
169
            PORTL |= (0<<PL1);
170
        }*/
171
172
        if(get_key_short(1<<KEY1))
173
        {
174
            LED_PORT ^= 1<<LED1;
175
            lcdScreen(1);
176
        }
177
178
        if(get_key_long(1<<KEY1))
179
            LED_PORT ^= 1<<LED2;
180
181
        if(get_key_press(1<<KEY2) || get_key_rpt(1<<KEY2))
182
        {
183
            uint8_t i = LED_PORT;
184
185
            i = (i & 0x07) | ((i << 1) & 0xF0);
186
            if( i < 0xF0 )
187
                i |= 0x08;
188
            LED_PORT = i;
189
        }
190
191
   }
192
  return 0;
193
}
194
/*******************************************************************************************************/

lcdRoutines.h
1
/*******************************************************************************************************/
2
#ifndef lcdRoutines_h
3
#define lcdRoutines_h
4
/*******************************************************************************************************/
5
// LCD-Informationen:
6
// 
7
// PortC = LCD-Data
8
// PortA = LCD-Control
9
//         A7 = PS (std=High=parallel Mode)
10
//       A6 = C86 (std=High=6800 Mode)
11
//          A5 = unbenutzt
12
//       A4 = /RD = E (Schreibflanke H->L)
13
//       A3 = /WR = R/W (Low=Schreiben)
14
//         A2 = A0 (Low=ControlData; High=DisplayData)
15
//       A1 = /RES (Low=activ; std=High)
16
//       A0 = CS1 (ChipSelect=muss Low sein; std=High)
17
/*******************************************************************************************************/
18
#define sbi(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
19
#define cbi(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
20
/*******************************************************************************************************/
21
// Definition der PORTs
22
#define PortLcdData PORTC
23
#define PortLcdDataPIN PINC
24
#define PortLcdDataDDR DDRC
25
#define PortLcdCtrl PORTA
26
#define PortLcdCtrlDDR DDRA
27
/*******************************************************************************************************/
28
// Initialisierung der Ports
29
void lcdInitPort()
30
{
31
  // Port-C als Eingang ohne Pullup konfigurieren (für LCD-Data)
32
  // Port-C muß je nach Aktion die ausgeführt wird (schreiben oder lesen) als Ausgang oder Eingang konfiguriert werden
33
  PortLcdDataDDR = 0x00;
34
  PortLcdData = 0;
35
36
  // Port-A als Ausgang konfigurieren (für LCD-Control)
37
  // Bit0 = CS = ChipSelect Low-aktiv
38
  // Bit1 = R/W = Low=Schreiben
39
  // Bit2 = RS = Low=Control, High=Data
40
  // Bit3 = E = Schreibflanke H->L
41
  // Bit4 = Reset = Low-aktiv
42
  PortLcdCtrlDDR = 0xff;
43
  PortLcdCtrl = 0b1100011;
44
}
45
// PE: = Parameter Eingang 
46
// PA: = Parameter Ausgang
47
// initialisiert das LCD
48
void lcdInit();
49
// sendet ein Steuerkommando an das LCD
50
// PE: data = Steuerkommando
51
void lcdSendCmd(uint8_t data);
52
/*******************************************************************************************************/
53
// schreibt ein Byte an die aktuelle Position auf dem LCD (aktuelle Position wird weitergesetzt)
54
// PE: data = das Byte
55
void lcdSendData(uint8_t data);
56
/*******************************************************************************************************/
57
// liest ein Byte von der aktuellen Position auf dem LCD (aktuelle Position wird beibehalten)
58
// PA: das glesene Byte
59
uint8_t lcdReadData();
60
// Setzt die Position der nächsten Ausgabe, z.B. für Texte.
61
// Der y-Wert wird auf eine 8er Grenze abgerundet. (0,8,16,24...56)
62
// PE: x = x-Koordinate 0...127; y = y-Koordinate 0...63 
63
void lcdSetPos(uint8_t x, uint8_t y);
64
/*******************************************************************************************************/
65
// rückt die angegebenen Zeile zur aktuellen Zeile auf dem LCD (Rolleffekt)
66
// PE: line = Nummer der Linie zu der gerollt werden soll
67
void lcdGotoLine(uint8_t line);
68
/*******************************************************************************************************/
69
// löscht alle angezeigten Daten auf dem LCD
70
void lcdClear();
71
/*******************************************************************************************************/
72
// schaltet die Anzeige aus/ein
73
// PE: on = Ein/Aus 0/1; 0 = Anzeige an; 1 = Anzeige aus (komplett dunkel)
74
void lcdSendCmdOn(uint8_t on);
75
/*******************************************************************************************************/
76
// invertiert die Anzeige (dunkel auf hell/ hell auf dunkel)
77
// PE: on = Aus/Ein 0/1; 0 = Normal (dunkel auf hell); 1 = Invers (hell auf dunkel)
78
void lcdSendCmdReverse(uint8_t jn);
79
/*******************************************************************************************************/
80
// setzt ein Pixel an Position x,y auf dem LCD
81
// PE: x = x-Koordinate 0...127; y = y-Koordinate 0...63
82
void lcdSetPixel(uint8_t x, uint8_t y);
83
/*******************************************************************************************************/
84
// sendet daten an das LCD, wird von lcdSendData() benutzt
85
// PE: data = zu sendende Daten
86
void lcdSend(uint8_t data)
87
{
88
  // Bit 3 an Port-A löschen (Schreiben auf LCD)
89
  cbi(PortLcdCtrl,3);
90
  // Daten auf Port-C
91
  PortLcdData = data;
92
  // Port-C als Ausgang konfigurieren
93
  PortLcdDataDDR = 0xFF;
94
  // Bit 0 an Port-A löschen (ChipSelect = An)
95
  cbi(PortLcdCtrl,0);
96
  // Bit 4 an Port-A setzen; E = 1 (Schreiben mit HighPuls an E)
97
  sbi(PortLcdCtrl,4);
98
  // Inlineassembler: kurz warten
99
  __asm volatile ("nop \n nop \n nop \n");
100
  // Bit 4 an Port-A löschen; E = 0
101
  cbi(PortLcdCtrl,4);        
102
  // Bit 0 an Port-A setzten (ChipSelect = Aus)
103
  sbi(PortLcdCtrl,0);
104
}
105
/*******************************************************************************************************/
106
// initialisiert das LCD
107
void lcdInit()
108
{
109
  _delay_ms(1);  
110
  // Licht aus
111
  PortLcdCtrl &= ~0b00100000;
112
  // Bit 0 an Port-A setzten (ChipSelect = Aus)
113
  sbi(PortLcdCtrl,0);
114
  // Bit 7 an Port-A setzten (parallel on)
115
  sbi(PortLcdCtrl,7);
116
  // Bit 6 an Port-A setzten (6800 Modus)
117
  sbi(PortLcdCtrl,6);
118
119
  // Reset am LCD
120
  PortLcdCtrl &= ~0b00000010;
121
  _delay_ms(1);  
122
  PortLcdCtrl |= 0b00000010;
123
  _delay_ms(1);  
124
125
  // Eine Reihe von Steuerkommandos an das LCD senden (sihe Datenblatt)
126
  
127
  // internal Reset 
128
  lcdSendCmd(0xE2);
129
  // ADC select  
130
  lcdSendCmd(0xA0);
131
  // COM output scan direction = revers   
132
  lcdSendCmd(0xC8);
133
  // LCD drive voltage bias ratio   
134
  lcdSendCmd(0xA2);
135
136
  lcdSendCmd(0x2F);
137
138
  lcdSendCmd(0x26);
139
  // select booster ratio  
140
  lcdSendCmd(0xF8);
141
  
142
  lcdSendCmd(0x00);
143
  // set output voltage  
144
  lcdSendCmd(0x81);
145
146
  lcdSendCmd(0x09);
147
  // read-modify-write  
148
  lcdSendCmd(0xE0);  
149
  // display on
150
  lcdSendCmd(0xAF);  
151
}
152
/*******************************************************************************************************/
153
// sendet ein Steuerkommando an das LCD
154
// PE: data = Steuerkommando
155
void lcdSendCmd(uint8_t data)
156
{
157
    // Bit 2 an Port-A löschen (Datenart = Steuerkommando)
158
  cbi(PortLcdCtrl,2);
159
  // Senden
160
  lcdSend(data);
161
}
162
/*******************************************************************************************************/
163
// schreibt ein Byte an die aktuelle Position auf dem LCD (aktuelle Position wird weitergesetzt)
164
// PE: data = das Byte
165
void lcdSendData(uint8_t data)
166
{
167
  // Bit 2 an Port-A setzten (Datenart = Daten)
168
  sbi(PortLcdCtrl,2);
169
  // Senden
170
  lcdSend(data);
171
}
172
/*******************************************************************************************************/
173
// liest ein Byte von der aktuellen Position auf dem LCD (aktuelle Position wird beibehalten)
174
// PA: das Byte
175
uint8_t lcdReadData()
176
{
177
  uint8_t data;
178
179
  // Port-C als Eingang konfiguriren (für lesen)
180
  PortLcdDataDDR = 0x00;
181
  // Bit 2 an Port-A setzten (Datenart = Daten)
182
  sbi(PortLcdCtrl,2);
183
  // Bit 3 an Port-A setzten (lesen)
184
  sbi(PortLcdCtrl,3);
185
  // Bit 0 an Port-A löschen (ChipSelect = An)
186
  cbi(PortLcdCtrl,0);
187
188
  // ein DUMMY-lesen nach Adress-Änderung (MUSS SEIN!)
189
190
  // Bit 4 an Port-A setzten (Flanke vorbereiten)
191
  sbi(PortLcdCtrl,4);
192
  // Inlineassembler: kurz warten
193
  __asm volatile ("nop \n nop \n nop \n");
194
  // Bit 4 an Port-A löschen
195
  cbi(PortLcdCtrl,4);
196
197
  // Ende DUMMY-lesen
198
199
  // Bit 4 an Port-A setzten (Flanke vorbereiten)
200
  sbi(PortLcdCtrl,4);
201
  // Inlineassembler: kurz warten
202
  __asm volatile ("nop \n nop \n nop \n");
203
  // Daten an PIN-C holen
204
  data=PortLcdDataPIN;
205
  // Bit 4 an Port-A löschen
206
  cbi(PortLcdCtrl,4);        
207
208
  // Bit 0 an Port-A setzten (ChipSelect = Aus)
209
  sbi(PortLcdCtrl,0);
210
  // Port-C als Ausgang konfigurieren
211
  PortLcdDataDDR = 0xFF;
212
213
  return data;
214
}
215
/*******************************************************************************************************/
216
// Setzt die Position der nächsten Ausgabe, z.B. für Texte.
217
// Der y-Wert wird auf eine 8er Grenze abgerundet. (0,8,16,24...56)
218
// PE: x = x-Koordinate 0...127; y = y-Koordinate 0...63
219
void lcdSetPos(uint8_t x, uint8_t y)
220
{
221
  // x-Koordinate
222
  lcdSendCmd(0b00010000 + (x>>4));
223
  lcdSendCmd(0b00000000 + (x & 0x0f));
224
  // y-Koordinate
225
  lcdSendCmd(0b10110000 + (y>>3));
226
}
227
/*******************************************************************************************************/
228
// rückt die angegebenen Zeile zur aktuellen Zeile auf dem LCD (Rolleffekt)
229
// PE: line = Nummer der Linie zu der gerollt werden soll
230
void lcdGotoLine(uint8_t line)
231
{
232
  // Zeile initialisieren
233
  lcdSendCmd(0b01000000 + (line & 0b00111111));
234
}
235
/*******************************************************************************************************/
236
// löscht alle angezeigten Daten auf dem LCD
237
void lcdClear()
238
{
239
  // die Anzeige besteht 128 * 8 Bytes, welche senkrecht angeordnet sind
240
  // in jedem Byte liegt Bit0 oben und Bit7 unten
241
  // y-Schleife (senkrecht); 8 mal, da 64 Pixel aus 8 Bytes je 8 Bits bestehen  
242
  for(uint8_t y=0; y<64; y+=8)
243
  {
244
      // gehe zu Zeilenanfang
245
    lcdSetPos(0,y);
246
    // x-Schleife (waagerecht); 128 Pixel sind 128
247
    for(uint16_t x=0; x<128; x++)
248
      // Byte auf 0 setzen
249
      lcdSendData(0);
250
  }
251
  // aktuelle Position auf linksoben setzen (0,0)
252
  lcdSetPos(0,0);
253
}
254
/*******************************************************************************************************/
255
// invertiert die Anzeige (dunkel auf hell/ hell auf dunkel)
256
// PE: on = Aus/Ein 0/1; 0 = Normal (dunkel auf hell); 1 = Invers (hell auf dunkel)
257
void lcdSendCmdReverse(uint8_t jn)
258
{
259
  // Anzeige normal/revers
260
  lcdSendCmd(0b10100110 + jn);
261
}
262
/*******************************************************************************************************/
263
// schaltet die Anzeige aus/ein
264
// PE: on = Ein/Aus 0/1; 0 = Anzeige an; 1 = Anzeige aus (komplett dunkel)
265
void lcdSendCmdOn(uint8_t on)
266
{
267
  // Alle Pixel an/aus
268
  lcdSendCmd(0b10100100 + on);
269
}
270
/*******************************************************************************************************/
271
// setzt ein Pixel an Position x,y auf dem LCD
272
// PE: x = x-Koordinate 0...127; y = y-Koordinate 0...63
273
void lcdSetPixel(uint8_t x, uint8_t y)
274
{
275
  // gehe zur Position
276
  lcdSetPos(x,y);
277
  uint8_t data;
278
  // Bitmuster für Position  des Bits (Pixel) im Byte
279
  data = 1<<(y & 0b00000111);
280
  // Byte auslesen, Bit setzten, Byte zurückschreiben
281
  lcdSendData(lcdReadData()|data);
282
}
283
/*******************************************************************************************************/
284
void lcdChar8(int c) // c ist hier der jeweilige ASCII-Wert (z.B.: "A">65) des gesendeten Charakters
285
{
286
    for(uint8_t nColumn=1; nColumn<=7; nColumn++)
287
    {
288
        lcdSendData(myFont[c][nColumn]);
289
        if(nColumn == myFont[c][0]) // wenn das Ende des Charakters im Array erreicht ist...
290
        {
291
            lcdSendData(0x00); // ... ein 0-Byte (leere Spalte) senden...
292
            break; // ... und Funktion verlassen (bzw. nächsten Charakter einlesen)
293
        }
294
    }
295
}
296
/*******************************************************************************************************/
297
// Bildung einer Zeichenkette aus den einzelnen Charaktern:
298
void lcdString8(const char *data)
299
{
300
    while(*data != '\0')
301
        lcdChar8(*data++);
302
}
303
/*******************************************************************************************************/
304
// Auswahl der Screens
305
void lcdScreen(uint8_t screenX)
306
{
307
    uint8_t xpos = 0;
308
    uint8_t ypos = 0;
309
310
    if(screenX == 0) // Startbild
311
    {
312
        //lcdClear();
313
        lcdSetPos(86,0);
314
        lcdString8("[press >]");
315
316
        lcdSetPos(10,16);
317
        lcdString8("Dynasoft'");
318
319
        ypos = 24;
320
        lcdSetPos(19,ypos);
321
        for(uint8_t m=0; m<=2; m++)
322
        {
323
            for(uint8_t n=0; n<=90; n++)
324
            {
325
                lcdSendData(myFontStart[m][n]);
326
            }
327
            lcdSetPos(19,ypos += 8); // Y-Position um ein Byte (eine Zeile) weitersetzen
328
        }
329
    }
330
    else if(screenX == 1) // Testbild
331
    {
332
        //lcdClear();
333
        xpos = 0;
334
        lcdSetPos(xpos,8);
335
        lcdString8("Neonröhre 1");
336
    }
337
}
338
/*******************************************************************************************************/
339
#endif
340
/*******************************************************************************************************/

von Karl H. (kbuchegg)


Lesenswert?

> Wird aber nun in der main.c, durch z.B. einen Taster, lcdScreen(1)
> aufgerufen, geschieht nix weiter (bzw. das LCD setzt kurz aus und lädt
> den Startbildschirm noch einmal).

Klingt ganz danach, als ob dein Tastendruck einen Kurzschluss auslösen 
würde und dein Prozessor neu startet.


Mach doch mal am Anfang bei der ersten Gelegenheit eine Testausgabe 
rein, dann weißt du es genau
1
    lcdInitPort();
2
  lcdInit();
3
  lcdClear();
4
  PortLcdCtrl |= 0b00100000; // Aktivierung der Hintergrundbeleuchtung
5
6
//////////////////////////
7
  lcdString8( "Starting" );
8
  _delay_ms( 1000 );
9
  lcdClear();
10
//////////////////////////
11
12
    // Laden des LCD-Startbildschirms
13
    lcdScreen(0);

Wenn du die "Starting" Meldung siehst, dann ist dein µC aus irgendeinem 
Grund resettet worden.

von Falk B. (falk)


Lesenswert?

@  Marci (Gast)

>Hier die Referenzen...

patsch

Und hier die Watschn für soviel Ignoranz! Lies mal was über 
Netiquette!
Lange Quelltexte gehören in den ANHANG!

von Marci (Gast)


Lesenswert?

@ Karl Heinz:

Vielen lieben Dank für die schnelle Hilfe!;-)

Fazit:
Einmal wird das "Starting" kurz angezeigt und wechselt dann zum 
Startbildschirm.
Ein anderes Mal wird im Loop das "Starting" neu geladen.

Ich versteh, wie und warum? An welcher Stelle?

@ Falk:

Ok. Ich wußte dies nicht, werd´ich mir merken.
Code einfach zu "überblicken" war mir in der Regel auch selbst lieber, 
als erst irgendwelche Anhänge öffnen zu müssen.

LG, Marcel

von Karl H. (kbuchegg)


Lesenswert?

Marci schrieb:
> @ Karl Heinz:
>
> Vielen lieben Dank für die schnelle Hilfe!;-)
>
> Fazit:
> Einmal wird das "Starting" kurz angezeigt und wechselt dann zum
> Startbildschirm.
> Ein anderes Mal wird im Loop das "Starting" neu geladen.

Wenn du das "STarting" mehr als einmal siehst, dann wird dein µC aus 
irgendeinem Grund resettet. Da du weiter oben von Tasten gesprochen 
hast, wirst du wohl mit den Tasten beim Drücken einen Kurzschluss 
auslösen oder sonst irgendetwas schlimmes machen. (Ist nur eine 
Möglichkeit, eine andere wäre zb ein Stackoverflow)

> Ich versteh, wie und warum? An welcher Stelle?

Wenn du innerhalb der Loop keinen Text "Starting" ausgibst, dann KANN 
diese Ausgabe nur von einem Neustart des Prozessors stammen. Genau das 
war der Sinn der Übung das herauszufinden.

von Marci (Gast)


Lesenswert?

Ps.:

Upps, da hatt´ich doch glatt das NICHT vergessen.;-)

Hmmmm... der Grund, warum ich es ned versteh´ ist, dass die Anweisungen 
IN der lcdScreen-Funktion ja direkt in main.c-main aufgerufen, ja 
einwandtfrei funktionieren.

LG, Marcel

von Marci (Gast)


Lesenswert?

Hmmmm... aber der Taster an sich funktionert ja. 1000e Male schon in der 
Anwendung getestet!?

LG, Marcel

von Marci (Gast)


Lesenswert?

Ich kann mir eigentlich nur vorstellen, dass die untenstehende Funktion 
nichtdefinierte Typen, etc. einen Fehler verursacht...


Mit dem Parameter 0 in folgender Funktion...
1
lcdScreen(0);

... müßte doch screenX als Wert 0 haben, oder hab´ ich 
Funktionsdeklarationen nicht ganz verstanden?
1
void lcdScreen(uint8_t screenX)
2
{
3
4
}

LG, Marcel

von holger (Gast)


Lesenswert?

>Ich kann mir eigentlich nur vorstellen, dass die untenstehende Funktion
>nichtdefinierte Typen, etc. einen Fehler verursacht...

Und ich könnte mir vorstellen das da wohl eine
Sonneneruption stattfindet wenn du auf die Taste drückst.

Oben wird ja noch was per UART ausgegeben.
Zeig deine UART Routinen. Vermutlich wird da
irgendwo ein Interrupt freigegeben für den
es keine Interruptroutine gibt.

von Marci (Gast)


Lesenswert?

Hallo Holger,

versteh´ dies jetzt bitte nicht falsch, aber dein Zynismus gehört nicht 
an einen Platz, an dem erwachsene Menschen zivilisiert miteinander 
kommunizieren möchten. Schlaue Sprüche übrigens auch nicht.

Ich bin kein Anfänger, sondern habe schon langjährige Erfahrungen in 
ActionScript, StarBasic, VBA und teils auch PHP.
Glaub mir bitte, wenn ich dir hiermit mitteile, dass ich es recht gut 
abschätzen kann, dir Codeschnipsel vorzuenthalten, von denen ich der 
Meinung bin, dass sie irrelevant bezüglich eines bestimmten Kontextes 
sind und desweiteren die Übersicht sowie auch Effektivität hier im Forum 
noch weiter beeinträchtigen würden.

Die USART-Funktionen laufen reibungslos. Mich wundert aber, dass du die 
lcdFonts.h gar nicht erwähnst - diese hat nämlich mehrere Hundert Zeilen 
Code.;-)) > ist aber auch nicht von Bedeutung.

Wenn du mir immer noch helfen möchtest...
... ich habe herausgefunden, dass die Funktion soweit bestens 
funktioniert, seltsamerweise ist die Bedingung dafür aber der Parameter 
0: sprich, sobald die Funktion lcdScreen() einen anderen Parameter als 0 
übergeben bekommt, stürzt das Programm ab und lädt von neuem. Ich hab 
zudem mal kurz auf Wikipedia ein paar Zeilen über "Überlauf" gelesen... 
und das klingt irgendwie nach dem Problem. Zumal es mir so vorkommt, als 
ob der Funktion anscheinend kein Parameter-Wert übergeben wird und bei 
"0" ganz einfach nur die erste if-Anweisung durchlaufen werden könnte.

Ich weiß es auch nicht.:(

Vielleicht aber einer von euch.

LG, Marcel

von Karl H. (kbuchegg)


Lesenswert?

Marci schrieb:

> Vielleicht aber einer von euch.

Nein, von uns weiß das auch keiner, solange du uns kein vollständiges 
Programm gibst, das man mal durch den Compiler jagen könnte und sich zb 
die Speicherauslastung ansehen kann.

> Ich hab zudem mal kurz auf Wikipedia ein paar Zeilen über "Überlauf"
> gelesen... und das klingt irgendwie nach dem Problem.

Stacküberlauf könnte sein. Dann passiert alles mögliche.
Der Überlauf, der dir da im Hinterstübchen vorschwebt, ist es nicht.

von holger (Gast)


Lesenswert?

>versteh´ dies jetzt bitte nicht falsch, aber dein Zynismus gehört nicht
>an einen Platz, an dem erwachsene Menschen zivilisiert miteinander
>kommunizieren möchten. Schlaue Sprüche übrigens auch nicht.

Ich bin nicht zynisch, ich hab dir einen Tipp gegeben.
Der könnte falsch sein. So what?

>Ich bin kein Anfänger,

Ich auch nicht.

> sondern habe schon langjährige Erfahrungen in
>ActionScript, StarBasic, VBA und teils auch PHP.

Kannst dir die Zertifikate dazu bei uC an die Wand kleben.

>Glaub mir bitte, wenn ich dir hiermit mitteile, dass ich es recht gut
>abschätzen kann, dir Codeschnipsel vorzuenthalten,

Dann behalte sie für dich und stell hier keine Fragen mehr.

> von denen ich der
>Meinung bin, dass sie irrelevant bezüglich eines bestimmten Kontextes
>sind und desweiteren die Übersicht sowie auch Effektivität hier im Forum
>noch weiter beeinträchtigen würden.

Ich bevorzuge komplette Quellcodes. Die dürfen durchaus sehr komplex
und groß sein. Was irrelevant ist wird sich noch rausstellen.

>Mich wundert aber, dass du die
>lcdFonts.h gar nicht erwähnst - diese hat nämlich mehrere Hundert Zeilen
>Code.;-)) > ist aber auch nicht von Bedeutung.

Die habe ich nicht erwähnt weil ich sie NIE gesehen habe;)

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Stacküberlauf könnte sein.

Da würde ich auch mein Geld drauf setzen, denn offensichtlich hat er ja 
in lcdFonts.h ganze Fonts im RAM liegen.

Marci schrieb:
> Mich wundert aber, dass du die
> lcdFonts.h gar nicht erwähnst - diese hat nämlich mehrere Hundert Zeilen
> Code.;-)) > ist aber auch nicht von Bedeutung.

Aber seiner Meinung nach ist die Datei ja nicht von Bedeutung.
Ach, es ist doch immer wieder "schön", wenn "erfahrene Programmierer" 
vorbei schauen, die zwar selber nicht in der Lage sind den Fehler zu 
finden, aber trotzdem meinen, den Hilfswilligen einhämmern zu müssen, wo 
der Fehler auf keinen Fall zu suchen ist.

@Marci:
> Die USART-Funktionen laufen reibungslos.
Sowas ist absolut kein Argument Code vorzuenthalten. Wo du doch ein ach 
so erfahrener Programmierer bist, müsstest du doch eigentlich wissen, 
dass das keinesfalls bedeutet "sind garantiert fehlerfrei". Es bedeutet 
lediglich, dass in den bisher getesteten Konstellationen keine Probleme 
aufgetaucht sind. Vielleicht waren bisher einfach Interrupts nur nie 
global freigeschaltet, und schon wird aus "laufen (bisher) reibungslos" 
ein "hier desaströs", sollte dort z.B. der TXC-Interrupt freigeschaltet 
werden. Ich selber vermute zwar die Stack-Kollision, aber die Nachfrage 
von holger zum UART-Code war berechtigt.

von Marci (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jungs^^,

ich habe wohl gerade meine Läuterung erfahren?!;-)
Bitte entschuldigt, es war nicht meine Absicht, schlechtes Karma zu 
verbreiten oder irgendjemandem auf den Schlips zu treten. Sorry.

Ich wollte einfach nur Unnötiges vermeiden - aber dies ist sicher eine 
Frage des Standpunktes bzw. der Erfahrung.^^

Also wenn mir immer noch jemand helfen mag (bitte, BITTE!), hier die 
Dateien...

LG, Marcel

von achja (Gast)


Lesenswert?

langjährige Erfahrung? Ich will ja nicht böse sein aber...

Die Definition von char myFont[256][8] in einer Headerdatei???? Und ohne 
"const"? Und so dass alles im RAM landet? (Da müsste ein Schlüsselwort 
hin, "PROGMEM" glaube ich).

von Marci (Gast)


Lesenswert?

Hey ho;-),

"langjährig" heißt nicht unbedingt "tiefgreifend".
Zudem ist C, mit samt seinen externen Files, auch nicht unbedingt leicht 
verdaubar. Mit z.B. "Bitoperationen" und überhaupt hardwarenaher 
Programmierung, mußte ich mich bis heuer noch niemals auseinandersetzen.

Also wenn du genauere Informationen dazu hast, nur heraus damit.;-)
Ich habe nämlich erst vor einigen Tagen mit dem Kapitel header-Files 
angefangen...

LG, Marcel

Ps.: Bei der Erstellung des mehrdimensionalen Arrays hatten mir sogar 
einige Moderatoren geholfen... wenn dort also etwas nicht stimmt, wissen 
wir, wohin wir uns wenden müssen.;-))))

von achja (Gast)


Lesenswert?

AIAIAI, die anderen beide Header enthalten ja auch Code.
Und dann das da
> // Einbindung der Header-Files
> #include "lcdFonts.h"
> #include "lcdRoutines.h"
> #include "usart.h"
Ich glaub dir mangelt es an Grundlagen über Code-/Headerdateien und die 
C-Toolchain!

von Marci (Gast)


Lesenswert?

Dies entspricht absolut der Wahrheit. Wie gesagt... ich habe erst vor 
Tagen damit angefangen.^^

LG, Marcel

von holger (Gast)


Lesenswert?

Na da haben wir ja schon einen Fehler im unwichtigen UART Code;)

// Senden von Zeichenketten (Strings)
void uartPutChar(char data)
{
    while (!(UCSR1A & 103));
    UDR1 = data;
}

Die 103 gehört da bestimmt nicht hin.

von Marci (Gast)


Lesenswert?

Hey Holger,

die 103 ist ein Parameter für UBRR (16MHz; 9600Baud; U2xn=0) und der 
Aufbau aller USART-Anweisungen ist DIREKT aus der Betriebsanleitung 
meines ATmega übernommen.

von Marci (Gast)


Lesenswert?

Ps.: Ach ne, Schmarrn... die String-Funktion hab´ ich durch Hilfe der 
Moderatoren gebastelt.^^

von holger (Gast)


Lesenswert?

>die 103 ist ein Parameter für UBRR (16MHz; 9600Baud; U2xn=0) und der
>Aufbau aller USART-Anweisungen ist DIREKT aus der Betriebsanleitung
>meines ATmega übernommen.

Und was hat die Baudrate mit UCSR1A zu tun?

von Marci (Gast)


Lesenswert?

Hallo Holger,

du scheinst es irgendwie mit meiner USART-Funktion zu haben, was?;-))

Hm... also von meinem Board-Hersteller habe ich folgende Kommentierung 
zu der Codezeile:

//warte bis UDR leer ist UCSR0A / USR bei z.B.: 2313

Mehr weiß ich bis dato auch nicht.

Ist bis jetzt aber auch nicht wichtig. Diese Funktion geht erst einmal 
und hat nichts mit meinem Problem zu tun. Komplett OHNE USART stürzt der 
Chip trotzdem ab.

LG, Marcel

von holger (Gast)


Lesenswert?

>Hallo Holger,
>
>du scheinst es irgendwie mit meiner USART-Funktion zu haben, was?;-))

Naja, sie ist falsch. Daran kannst du noch arbeiten.

>Hm... also von meinem Board-Hersteller habe ich folgende Kommentierung
>zu der Codezeile:
>
>//warte bis UDR leer ist UCSR0A / USR bei z.B.: 2313

He,he. Da hat der dir ne Antwort drauf gegeben? Was bedeutet 2313?

>Ist bis jetzt aber auch nicht wichtig. Diese Funktion geht erst einmal

Glaub ich nicht. Dein Post:

>Mittels eines USART_sendeByte()-Befehls wurde mir im Terminal "Dy"
>angezeigt

Das liegt sehr wahrscheinlich an der falschen UART Routine.
Die Ausgabe wird nicht komplett beendet.

>und hat nichts mit meinem Problem zu tun. Komplett OHNE USART stürzt der
>Chip trotzdem ab.

Kommen wir mal zur Ausgangsfrage:

>Wird aber nun in der main.c, durch z.B. einen Taster, lcdScreen(1)
>aufgerufen, geschieht nix weiter

Ich sehe in deinem aktuellen Programm kein lcdScreen(1).
Wo ist das hin?

Im Sourcecode steht das Programm ist für einen ATmega2560.
Hast du das Programm für einen ATMega2560 übersetzt?
Benutzt du einen ATMega2560?

Der RAM Bedarf liegt bei 2,5kB. Sollte mit einem Atmega2560
also kein Problem sein.

von Marci (Gast)


Lesenswert?

Hallo Holger...

danke für das Feedback.
Wahrscheinlich hast du Recht. Das mit dem "Dy" fand ich schon recht 
seltsam^^.
Ich hab gestern nochmal die USART-Source-Codes für den 2560 von Atmel 
durchstöbert und da sind die Routinen etwas anders. Dort gibt es 
allerdings auch keine Routine für eine String-Verarbeitung.

Jepp, du hast Recht. Ich hatte ja zwischenzeitlich diverse Versuche 
gemacht und scheinbar vor dem POST nicht mehr umgestellt. In der Abfrage 
von KEY1 muß natürlich lcdScreen(1) stehen.

Ich habe das Programm gestern in eine einzige .c-Datei geschrieben und 
bis auf die Tasterabfrage und die lcdScreen()-Funktion alles 
herausgenommen und voilá, das Problem besteht weiterhin...:(
Es scheint (wie auch schon mal vorher angedeuted) an der 
String-Funktion...
1
void lcdChar8(int c) // c ist hier der jeweilige ASCII-Wert (z.B.: "A">65) des gesendeten Charakters
2
{
3
    for(uint8_t nColumn=1; nColumn<=7; nColumn++)
4
    {
5
        lcdSendData(myFont[c][nColumn]);
6
        if(nColumn == myFont[c][0]) // wenn das Ende des Charakters im Array erreicht ist...
7
        {
8
            lcdSendData(0x00); // ... ein 0-Byte (leere Spalte) senden...
9
            break; // ... und Funktion verlassen (bzw. nächsten Charakter einlesen)
10
        }
11
    }
12
}

... zu liegen (ist auch die einzige Funktion, die ich bis dato komplett 
ohne Hilfe schrieb).
Diese Funktion bekommt (sollte zum.^^) ja von lcdString8 einen Charakter 
übergeben und sollte dann für die Dekrement-Routine in der Schleife 
direkt mit dem dazugehörigen ASCII-Wert weiterrechnen können.
Kann da der Fehler drin sein.

LG, Marcel

Ps.: Und jepp, hab´s versucht, soweit ich es verstanden habe, auf den 
2560 anzugleichen.

von Marci (Gast)


Lesenswert?

Hey Jungs,

niemand einen Rat?

LG

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hast Du denn Deinen Code schon mal in einem Debugger laufen lassen?

von Marci (Gast)


Lesenswert?

Hab´s schon mal versucht, aber ich komm mit AVR Studio nocht nicht so 
gut zurecht.

LG

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann üb' das. Vor dem Rennen kommt das Laufen.

von holger (Gast)


Lesenswert?

>Dann üb' das. Vor dem Rennen kommt das Laufen.

Und vor dem Laufen kommt das Gehen;)

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.