PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Funktionsaufrufen



PCMan
16.01.2008, 23:04
Hallo Forum,
ich muss schon sagen *leider* habe ich wieder ein nerviges Problem, und somit *leider* wieder eine kniffelige Frage für euch ;)

Kurzes Intro:
ATMega32
avr-gcc (GCC) 4.1.2 (WinAVR 20070525)

Okay, was nun passiert ist:
ich habe eine Globale Variable des Typs uint8_t Data.TRX_Indexer.

Zum Start des Programms lasse ich mein Board initialisieren. Dort wird auch der UART initialisiert. Dazu benutze ich die Funktionen von P. Fleury:


void avrboard_init(){
...
Data.TRX_Indexer = 0;
...
uart_init( UART_BAUD_SELECT_DOUBLE_SPEED(UART_BAUD_RATE,F_CPU ) );
... jede Menge anderes Gelump...
}


Danach wird der UART sozusagen von mir freigeschaltet.


void rs232_open() {
//alle unwichtigen interrupts beenden
led_busy_on();
RS232.Open=1;
Menue.Hold=1;
lcd_clr_scrollbar();
keypad_close();
lcd_clrscr();
lcd_puts("RS232: Verbinden");
rs232_puts("CON;ping?");
RS232.rtys=0;
RS232.Timeout=0;
return;
// ab jetzt eingehende Signale interpretieren
}

Wenn der Aufruf von rs232_open() fertig ist prüfe ich den Wert meiner Data.TRX_Indexer-Variablen in der Main.


int main(void)
{
avrboard_init();
rs232_open();

// TESTBLOCK START
lcd_clrscr();
lcd_puts("PC Autodetect");
lcd_gotoxy(0,1);
lcd_puts("RS232<->PC"); //10 chars
char puffer[33];
itoa(Data.TRX_Indexer, puffer, 10);
lcd_clrscr();
lcd_puts(puffer);
led_error_on(); for(;;);
//TESTBLOCK ENDE

... all das darunter wird nicht mehr ausgeführt
}


Und siehe da, obwohl ich die Variable mit 0 initialisiert habe (in der avrboard_init()) , hat sie auf einmal den Wert 7! Wieso 7?

Wenn ich den Quelltext innerhalb von TESTBLOCK START und TESTBLOCK ENDE an das Ende der Funktion rs232_open() setze, erhalte ich in der Data.TRX_Indexer den Wert 0, wie ich es auch erwarte.


void rs232_open() {
//alle unwichtigen interrupts beenden
led_busy_on();
RS232.Open=1;
Menue.Hold=1;
lcd_clr_scrollbar();
keypad_close();
lcd_clrscr();
lcd_puts("RS232: Verbinden");
rs232_puts("CON;ping?");
RS232.rtys=0;
RS232.Timeout=0;
// TESTBLOCK START
lcd_clrscr();
lcd_puts("PC Autodetect");
lcd_gotoxy(0,1);
lcd_puts("RS232<->PC"); //10 chars
char puffer[33];
itoa(Data.TRX_Indexer, puffer, 10);
lcd_clrscr();
lcd_puts(puffer);
led_error_on(); for(;;);
//TESTBLOCK ENDE

return;
}


Kann mir das jemand erklären, warum mir die Data.TRX_Indexer nach dem Aufruf von rs232_open() mit 7 überschrieben wird, nicht aber innerhalb der Funtkion?

Ihr werdet euch sicher fragen, wieso im Testbereich diese sache mit dem PC-Autodetect etc. steht. Tja, mir ist aufgefallen, wenn ich in der 2. Zeile des Displays nur ein Zeichen weniger anzeigen lasse (z.B. lcd_puts("RS232<->P");//9 chars), dann erhalte ich auch den Wert 0 in meiner Data.TRX_Indexer. Mein Display hat aber 2*16 Zeichen, das umfasst es eigentlich locker.

Bin auf eure Ideen gespannt, ich habe nämlich absolut keinen Schimmer mehr, wie ich weiter machen soll...

Viele Grüße und gute Nacht,
Simon

fumir
17.01.2008, 08:08
du solltest besser den ganzen code posten.
wenn der fehler so offensichtlich in diesen codeschnipseln zu erkennen wäre, wäre er dir vermutlich selbst aufgefallen.

PCMan
17.01.2008, 09:04
Hi,
okay, also hier die ganze Initialisierungsroutinen, Variablendefinitionen, etc. pp.



#define SND_PORT PORTD
#define SND_PIN PD5
#define SND_DDR DDRD
#define SND_PRESCALER 256
#define SND_OK 1
#define SND_ABORT 2
#define SND_PCCONNECTED 3
#define SND_ERROR 4

#define KEYPAD_ESC_PORT PORTD
#define KEYPAD_ESC_PIN PD6
#define KEYPAD_ESC_PINS PIND
#define KEYPAD_ESC_DDR DDRD
#define KEYPAD_OK_PORT PORTB
#define KEYPAD_OK_PIN PB1
#define KEYPAD_OK_PINS PINB
#define KEYPAD_OK_DDR DDRB
#define KEYPAD_DEC_PORT PORTD
#define KEYPAD_DEC_PIN PD7
#define KEYPAD_DEC_PINS PIND
#define KEYPAD_DEC_DDR DDRD
#define KEYPAD_INC_PORT PORTB
#define KEYPAD_INC_PIN PB0
#define KEYPAD_INC_PINS PINB
#define KEYPAD_INC_DDR DDRB
#define KEYPAD_SCANNING_FREQUENCY 1000 //0..65535
#define KEYPAD_DEBOUNCE_SLOW 200 //0..255
#define KEYPAD_DEBOUNCE_FAST 80

#define LCD_SCROLLING_ROW 1
#define LCD_SCANNING_FREQUENCY 75
#define LCD_DELAY_FACTOR 10
#define LCD_ROW_LENGTH 15

#define MOTOR_A_PORT PORTC
#define MOTOR_A_DDR DDRC
#define MOTOR_A_ENABLE_PIN PC5
#define MOTOR_A_CWCCW_PIN PC6
#define MOTOR_A_CLOCK_PIN PC7
#define MOTOR_B_PORT PORTC
#define MOTOR_B_DDR DDRC
#define MOTOR_B_ENABLE_PIN PC2
#define MOTOR_B_CWCCW_PIN PC3
#define MOTOR_B_CLOCK_PIN PC4
#define MOTOR_A_TOGGLE (MOTOR_A_PORT ^= (1 << MOTOR_A_CLOCK_PIN))
#define MOTOR_B_TOGGLE (MOTOR_B_PORT ^= (1 << MOTOR_B_CLOCK_PIN))
#define O2O 0 //MotA läuft rückwärts
#define l2O 1 //MotA läuft vorwärts
#define O2l 2 //MotB läuft vorwärts
#define l2l 3 //MotA und MotB 1 Schritt
#define l25 4 //MotA 1 Schritt, MotB 4 Schritte
#define l2lO 5 //MotA 1 Schritt, MotB 9 Schritte
#define l2lOO 6 //MotA 1 Schritt, MotB 99 Schritte
#define MOTOR_FAST 720
#define MOTOR_MEDIUM 480
#define MOTOR_SLOW 240

#define PHOT_LED_PORT PORTA
#define PHOT_LED_DDR DDRA
#define PHOT_LED_PIN PA6
#define phot_led_toggle() (PHOT_LED_PORT ^= (1<<PHOT_LED_PIN))
#define PHOT_CHANNEL 0b0111 //PORTA7 (ADC7)
#define PHOT_UREF 2.560

#define LED_BUSY_PORT PORTB
#define LED_BUSY_DDR DDRB
#define LED_BUSY_PIN PB4
#define LED_ERROR_PORT PORTB
#define LED_ERROR_DDR DDRB
#define LED_ERROR_PIN PB3
#define led_busy_on() (LED_BUSY_PORT |= (1<<LED_BUSY_PIN))
#define led_busy_off() (LED_BUSY_PORT &= ~(1<<LED_BUSY_PIN))
#define led_error_on() (LED_ERROR_PORT |= (1<<LED_ERROR_PIN))
#define led_error_off() (LED_ERROR_PORT &= ~(1<<LED_ERROR_PIN))

#define RS232_RETRY_THRESHOLD 10 //maximum = 32

#define SCREENSAVER 60 //maximum = 64
#define TIMEOUT 3 //maximum = 8

//--do not edit --
#define F_CPU 12000000UL

#define MODE_PC 0
#define MODE_STANDALONE 1

#define KEYPAD_KEYOK 1
#define KEYPAD_KEYESC 2
#define KEYPAD_KEYINC 3
#define KEYPAD_KEYDEC 4
#define KEYPAD_PRESCALER 256
#define LCD_PRESCALER 1024
#define PROG_INTERVALLMESSUNG 1
#define PROG_WACHSTUMSKURVE 2
#define PROG_LOESUNG_INDUZ 3
#define PROG_EXP_HALT 4
#define PROG_DATENTRANSFER 6
#define UART_BAUD_RATE 115200
#define UART_STR_LENGTH 40
#define EEPROM_CHIP_T 0b10100000
#define EEPROM_CHIP_V 0b10100010
//#define EEPROM_CHIP_V 0xA4
#define LOWBYTE(x) ((uint8_t)(x))
#define HIGHBYTE(x) ((uint8_t)((x) >> 8 ))
#define TOUINT16_T(x,y) (((x) << 8) | y)
#define stop_T1() (TCCR1B &= ~(1<<CS12))


//Fixdaten:

//-- globals --

volatile struct {
unsigned LCD_hold:1;
unsigned KEYPAD_close:1;
unsigned KEYPAD_keypressed:3;
unsigned Mode:1;
unsigned Screensaver:6;
unsigned Screen_Off:1;
} Status;

volatile struct {
unsigned Of:1;
uint8_t Counter;
uint8_t Counter_backup;
uint16_t Preloader;
} T0,T1,T2;

volatile struct {
unsigned Program:4;
unsigned Selection:3;
unsigned Hold:2;
unsigned Execute_Program_Nr:4;
float OD;
uint16_t Vol;
} Menue;

volatile struct {
uint8_t Interval; //in Minuten
float Df;
uint16_t Induz_Volume;
float Dilute_at_OD;
float Alarm_at_OD;
float Set_at_OD;
unsigned SIGA:1;
unsigned SIGB:1;
} Settings;

volatile struct {
unsigned Key:3;
float Blank;
float Abs;
uint16_t Eep_addr_counter;
uint16_t Eep_sc;
char Eep_str[40];
uint16_t Time_left; //in Sek bis zur nächsten Messg
uint8_t TRX_Indexer;
} Data;

volatile struct {
unsigned Open:1;
unsigned Cmd_Start:1;
unsigned Cmd_Complete:1;
unsigned Cmd_Received:1;
uint8_t i;
char Cmd[UART_STR_LENGTH];
unsigned rtys:5;
unsigned Pong:1;
unsigned Timeout:3;
} RS232;

volatile struct {
char Cmd[40];
char Par[40];
char Out[UART_STR_LENGTH];
uint8_t Par_l;
uint16_t crc;
} Command;


volatile char LCD_lauftext[100];
volatile char LCD_temp;


//-- forwards --

int main(void);
uint8_t strlength(const char* str);
void snd_init(void);
void motor_init(void);
void avrboard_init(void);
void delay_1s(void);
void start_T1(void);

void lcd_clr_scrollbar(void);
void lcd_scroll_text(char* text, uint16_t Hz, uint8_t delay_factor);

void keypad_init(void);
void keypad_open(uint16_t Hz, uint8_t debounce_factor);
void keypad_close(void);
uint8_t keypad_check(void);
void keypad_wait(uint8_t key);

void rs232_gets(void);
void rs232_puts(char* str);
void rs232_open(void);
void rs232_decode(void);
unsigned rs232_checkcrc(void);
void rs232_execute(void);
void rs232_close(void);

void snd_beep(uint16_t Hz, uint8_t time_index);
void snd_play(uint8_t Melody);

void led_init(void);

void menue_show(void);
void menue_select(void);

void phot_ReadAbs(void);
void phot_ReadBlank(void);
uint16_t phot_ReadADC(void);

void motor_stop(void);
unsigned motor_open(uint32_t Ticks, uint8_t Prog, uint16_t frequency);

uint16_t eeprom_readuint16_t(uint16_t eeprom_adress);
void eeprom_writeuint16_t(uint16_t eeprom_adress, uint16_t var16);
float eeprom_readfloat(uint16_t eeprom_adress);
void eeprom_writefloat(uint16_t eeprom_adress, float var32);
unsigned eeprom_add_data(uint16_t min, float value);
void eeprom_read_data(uint16_t eeprom_adress);
uint16_t eeprom_get_stopcodon(void);
void eeprom_close(void);
void eeprom_check(char err);

/*
uint8_t strlength(const char * str) {
uint8_t length=0;
while(str[length]!='\0'){
length++;
}
return length;
}*/

ISR(TIMER0_OVF_vect)
{
//Keypad-Abfrage
if (!(KEYPAD_OK_PINS & (1 << KEYPAD_OK_PIN))){
Status.KEYPAD_keypressed=KEYPAD_KEYOK;
} else
if (!(KEYPAD_ESC_PINS & (1 << KEYPAD_ESC_PIN))){
Status.KEYPAD_keypressed=KEYPAD_KEYESC;
} else
if (!(KEYPAD_INC_PINS & (1 << KEYPAD_INC_PIN))){
Status.KEYPAD_keypressed=KEYPAD_KEYINC;
} else
if (!(KEYPAD_DEC_PINS & (1 << KEYPAD_DEC_PIN))){
Status.KEYPAD_keypressed=KEYPAD_KEYDEC;
} else Status.KEYPAD_keypressed = 0;
T0.Of=1;
TCNT0=T0.Preloader;
}

ISR(TIMER1_OVF_vect) {
if (T1.Counter<255) T1.Counter++;
else T1.Counter=0;

if (Status.Screensaver < SCREENSAVER) Status.Screensaver++; //zählt bis 10 und stopp da.

if (RS232.Timeout < TIMEOUT) RS232.Timeout++;

T1.Of=1;
TCNT1=T1.Preloader;
}

ISR(TIMER2_OVF_vect)
{

if (Status.LCD_hold==0){
if (T2.Counter == 0) {

lcd_gotoxy(0,LCD_SCROLLING_ROW);

for (uint8_t i=0; i<=LCD_ROW_LENGTH; i++) {
lcd_putc(LCD_lauftext[i]);
}

LCD_temp=LCD_lauftext[0];
for (uint8_t i=0; i<=strlen((const char *)LCD_lauftext); i++) {
LCD_lauftext[i]=LCD_lauftext[i+1];
}
LCD_lauftext[strlen((const char *)LCD_lauftext)]=LCD_temp;

T2.Counter = T2.Counter_backup;
} else T2.Counter--;
}
T2.Of=1;
TCNT2=T2.Preloader;
}

void start_T1(){
T1.Preloader=18660; //für 1s, Prescaler ist 256
TCCR1B |= (1<<CS12); //256 als Vorteiler
TCNT1 = T1.Preloader;
TIMSK |= (1<<TOIE1);
T1.Of=0;
}
/*
void delay_1s(){
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
_delay_ms(20);_delay_ms(20);_delay_ms(20);_delay_m s(20);_delay_ms(20);
}
*/
void snd_init() {
SND_DDR |= (1<<SND_PIN); //PB0 als Ausgang
SND_PORT &= ~(1<<SND_PIN); //PB0 auf Low
}

void keypad_init() {
KEYPAD_OK_DDR &= ~(1<<KEYPAD_OK_PIN);
KEYPAD_OK_PORT |= (1<<KEYPAD_OK_PIN);

KEYPAD_ESC_DDR &= ~(1<<KEYPAD_ESC_PIN);
KEYPAD_ESC_PORT |= (1<<KEYPAD_ESC_PIN);

KEYPAD_INC_DDR &= ~(1<<KEYPAD_INC_PIN);
KEYPAD_INC_PORT |= (1<<KEYPAD_INC_PIN);

KEYPAD_DEC_DDR &= ~(1<<KEYPAD_DEC_PIN);
KEYPAD_DEC_PORT |= (1<<KEYPAD_DEC_PIN);
}

void motor_init() {
MOTOR_A_DDR |= (1<<MOTOR_A_ENABLE_PIN); //Ausgang
MOTOR_A_PORT &= ~(1<<MOTOR_A_ENABLE_PIN); //LOW

MOTOR_A_DDR |= (1<<MOTOR_A_CWCCW_PIN); //Ausgang
MOTOR_A_PORT &= ~(1<<MOTOR_A_CWCCW_PIN); //LOW

MOTOR_A_DDR |= (1<<MOTOR_A_CLOCK_PIN); //Ausgang
MOTOR_A_PORT &= ~(1<<MOTOR_A_CLOCK_PIN); //LOW

MOTOR_B_DDR |= (1<<MOTOR_B_ENABLE_PIN); //Ausgang
MOTOR_B_PORT &= ~(1<<MOTOR_B_ENABLE_PIN); //LOW

MOTOR_B_DDR |= (1<<MOTOR_B_CWCCW_PIN); //Ausgang
MOTOR_B_PORT &= ~(1<<MOTOR_B_CWCCW_PIN); //LOW

MOTOR_B_DDR |= (1<<MOTOR_B_CLOCK_PIN); //Ausgang
MOTOR_B_PORT &= ~(1<<MOTOR_B_CLOCK_PIN); //LOW
}

void led_init() {
LED_BUSY_DDR |= (1<<LED_BUSY_PIN); //Ausgang
LED_BUSY_PORT &= ~(1<<LED_BUSY_PIN); //LOW
LED_ERROR_DDR |= (1<<LED_ERROR_PIN); //Ausgang
LED_ERROR_PORT &= ~(1<<LED_ERROR_PIN); //LOW
}

void avrboard_init(){
motor_init(); //zuerst, saugt zu viel strom...
led_init();
led_busy_on();

//FIXDATEN
T0.Of=0;
T1.Of=0;
T1.Counter=0;
T2.Of=0;
RS232.Pong=0;
Status.LCD_hold=0;
Status.KEYPAD_close=0;
Status.Screensaver=0;
Status.Screen_Off = 0;
Status.Mode = MODE_PC;
RS232.Timeout=0;
Menue.Program=0;
Menue.Selection=0;
Menue.Hold=0;
RS232.i=0;
RS232.Open=0;
Data.Eep_addr_counter=0;
Data.Eep_sc = 0;
Data.TRX_Indexer = 0;
Data.Key = 0;
sei();

//Rest
keypad_init();
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_puts("Beginne Init.");
lcd_gotoxy(0,1);
lcd_puts("[OK] druecken!");
//keypad_wait(KEYPAD_KEYOK);

start_T1();
snd_init();

i2c_init();

PHOT_LED_DDR |= (1<<PHOT_LED_PIN); //Ausgang
PHOT_LED_PORT &= ~(1<<PHOT_LED_PIN); //LOW

#ifndef nors232
uart_init( UART_BAUD_SELECT_DOUBLE_SPEED(UART_BAUD_RATE,F_CPU ) );
#endif

led_busy_off();
keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW);
}





twimaster.c


/************************************************** ***********************
* Title: I2C master library using hardware TWI interface
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
* Target: any AVR device with hardware TWI
* Usage: API compatible with I2C Software Library i2cmaster.h
************************************************** ************************/
#include <inttypes.h>
#include <compat/twi.h>

#include <i2cmaster.h>


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 12000000UL
#endif

/* I2C clock in Hz */
#define SCL_CLOCK 100000L


/************************************************** ***********************
Initialization of the I2C bus interface. Need to be called only once
************************************************** ***********************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */

TWSR = 0; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */

}/* i2c_init */

...


Brauchst sonst nochwas?
Viele Grüße,
Simon

fumir
17.01.2008, 12:18
hat zwar jetzt nix mit dem thema zu tun, aber sind dir da wirklich keine besseren bezeichner eingefallen?

#define O2O 0 //MotA läuft rückwärts
#define l2O 1 //MotA läuft vorwärts
#define O2l 2 //MotB läuft vorwärts
#define l2l 3 //MotA und MotB 1 Schritt
#define l25 4 //MotA 1 Schritt, MotB 4 Schritte
#define l2lO 5 //MotA 1 Schritt, MotB 9 Schritte
#define l2lOO 6 //MotA 1 Schritt, MotB 99 Schritte

auf meinem editor sieht das alles fast wie 1 und 0 aus, also wie irgendwelche zahlen aus.
man kann sich das leben eben beliebig schwer machen!


hier fehlt die klammer um y :
#define TOUINT16_T(x,y) (((x) << 8) | y)

fumir
17.01.2008, 13:08
beim ersten drüberschauen nix gefunden.

ich würde versuchen die genaue stelle des überschreibens weiter einzuschränken.
am besten natürlich mit nem debugger.

ansonsten würd ich mal die version mit auftreten der mysteriösen 7 nehmen und von hinten anfangen:
- erst mal alles weglassen und direkt die gewünschte null ausgeben: lcd_puts("0");
- dann die "0" direkt in den buffer schreiben und ausgeben lassen
- dann die 0 mit itoa in den buffer schreiben und ausgeben lassen
- dann die 0 unmittelbar vor den ausgabebefehlen in Data.TRX_Indexer schreiben und ausgeben lassen.
- dann Data.TRX_Indexer=0; jeweils einen weiteren befehl im programmablauf nach vorne schieben bis du an der stelle ankommst, an der es eigentlich hingehört.

andere idee: ändere mal einige namen z.b mach aus Data einfach mal myData womöglich gibts nen namenskonflikt oder nen tipfehler.

andere idee: ändere die reihenfolge in der die globalen variablen angelegt werden. wenn irgend ein teil des programms wild im speicher rumschreibt, und dir dabei zufällig etwas in Data.*** schreibt sollte sich das dann ändern.

das ist natürlich alles blind im heuhaufen rumstochern, aber was besseres ist mir bis jetzt noch nicht eingefallen :-)

PCMan
17.01.2008, 16:52
Hallo Fumir, ich danke dir, dass du dir die Zeit nimmst. Ich weiß mein C ist nicht das schönste und viel Krams ist es auch noch.
Nun zum ersten:
Die definitionen sehen bekloppt aus, ist aber absichtlich so gewäht. Ursprünglich sollten da Verdünnungen stehen à la 1:1 1:5 1:10 1:100. Da hat der Compiler gemeckert. Ich habe verschiedene Varianten ausprobiert. Viele wurden vom Compiler nicht akzeptiert, deswegen habe ich mir diese Verdünnungsangaben mit Ls und Os zusammengefaked ;)

Das zweite: ich würde gerne debuggen. Die Frage ist nur: wie geht das. Hast du eine kleine Anleitung parat? Würde mich darüber sehr freuen.

Die anderen Varianten, die du aufzählst, habe ich noch nicht getestet. Werde ich mal machen.

Viele Grüße,
Simon

McJenso
17.01.2008, 17:58
Hallo,

so ganz finde ich durch die Codeteile noch nicht durch.
Was mir beim durchschauen aufgefallen ist.
Wo wird LCD_lauftext etwas zugewiesen.
Mit


for (uint8_t i=0; i<=strlen((const char *)LCD_lauftext); i++) {
LCD_lauftext[i]=LCD_lauftext[i+1];
}

erzeugst du, wenn es dumm läuft, einen Überlauf.

Edit: Die obige Aussage von mir ist Blödsinn. Du greifst zwar ausserhalb von LCD_lauflicht zu, schreibst aber nicht.

Wird Timer2 überhaupt gestartet?

Am Anfang der Funktion rs232_open steht der Kommentar:
//alle unwichtigen interrupts beenden
Wo machst du da was?

Schieße ich auch mal ins Blaue. Passiert der Fehler auch, wenn du sei() auskommentierst?

Gruß

Jens

PCMan
17.01.2008, 21:21
Hi,
ich habe das Spiel etwas weiter getrieben, bin aber immernoch bei dem gleichen Problem wie zu Beginn. Allerdings Data in myData umzubenennen habe ich noch nicht getestet.
Ich bin jetzt, wie fumir vorgeschlagen hat, vorgegangen. Die 0 direkt zu schreiben, in den Puffer zu schreiben oder in TRX_Idexer zu schreiben macht keinen Unterschied. Ich bekomme immer 0 auf's Display. Sobald ich aber mit Data.TRX_Indexer = 0 über die zeile lcd_pus("PC Autodetect"); komme, erscheint wieder die magische 7.
Das Lustige ist nun, wenn ich in die erste Zeile von lcd_puts Data-TRX_Indexer = 0 schreibe, dann habe ich nach wie vor meine gewollte 0.
Strange,
hier der Beweiscode:
in der Main:


int main(void)
{
avrboard_init();
rs232_open();
lcd_clrscr();

//<- wenn TRX_Indexer = 0 hier steht, dann 7 auf LCD
lcd_puts("PC Autodetect");
//wenn hier TRX-Indexer = 0 steht, dann 0 auf LCD
lcd_gotoxy(0,1);
lcd_puts("RS232<->PC?"); //10 chars
char puffer[33];
itoa(Data.TRX_Indexer, puffer, 10);
lcd_clrscr();
lcd_puts(puffer);
led_error_on(); for(;;);


in der lcd.c von p. fleury


void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
// wenn hier Data.TRX_Indexer = 0 steht, dann 0 auf dem LCD
register char c;

while ( (c = *s++) ) {
lcd_putc(c);
}
// wenn hier Data.TRX_Indexer steht, dann 0 auf dem LCD
}/* lcd_puts */


Mc Jenso:
Richtig erkannt, der Timer 2 wird garnicht erst gestartet. Er wird erst gestartet, wenn ich folgende von mir gebastelte Routine aufrufe:


void lcd_clr_scrollbar() {

TCCR2 &= ~(1<<CS22); //timer abstellen
TCCR2 &= ~(1<<CS21);
TCCR2 &= ~(1<<CS20);
lcd_gotoxy(0,LCD_SCROLLING_ROW);
lcd_puts(" ");
}

void lcd_scroll_text(char* text, uint16_t Hz, uint8_t delay_factor){

strcpy((char*)LCD_lauftext, text);

T2.Counter=delay_factor;
T2.Counter_backup=delay_factor;
TCCR2|=(1<<CS22)|(1<<CS21)|(1<<CS20); //Prescaler=1024
T2.Preloader=256-F_CPU/LCD_PRESCALER/Hz;
TCNT2=T2.Preloader;
TIMSK |= (1<<TOIE2);
T2.Of=0;
Status.LCD_hold=0;
}

Du siehst, der Überlauf ist eigentlich nicht möglich, weil ich immer einen String mitgebe, wenn der Timer startet.
Abgesehen davon wird die Lauftext-Routine noch nicht aufgerufen, bevor die magische 7 erscheint.

Zur rs232_open:
ist blöd formuliert im Kommentar, die Interrupts werden nicht beendet, sondern die timers. Das geschieht in den Routinen lcd_clr_scrollbar(); und keypad_close();
Die beiden Funktionen sind wie folgt implementiert:



void keypad_close(){
TCCR0 &= ~(1<<CS02); //timer abstellen
TCCR0 &= ~(1<<CS01);
TCCR0 &= ~(1<<CS00);
T0.Preloader=0;
}

void lcd_clr_scrollbar() { //steht oben schonmal

TCCR2 &= ~(1<<CS22); //timer abstellen
TCCR2 &= ~(1<<CS21);
TCCR2 &= ~(1<<CS20);
lcd_gotoxy(0,LCD_SCROLLING_ROW);
lcd_puts(" ");
}



Okay, was mir jetzt erst auffällt: ich beende den Timer2 obwohl er garnicht gestartet ist. Aber das sollte ja nix machen oder?

Was passiert, wenn ich sei() auskommentiere: die Magische 7 verschwindet. Wieso? Verstehe den zusammenhang nicht!
](*,)
Vielen Dank für's mitfiebern,
Simon :-)

Nachtrag: mir fällt gerade bei der lcd_clr_scrolling_row auf, dass ich da evtl ein Leerzeichen zu viel reinschreibe!? Aber ist das denn so schlimm!? Wenn ich ein Leerzeichen wegnehme und sei() nicht auskommentiere, ist die magische 7 auch weg ??!??

fumir
18.01.2008, 08:21
wie wärs mit
#define speed1zu1 3
#define speed1zu5 4

sieht so aus, als würde deine globale variable von etwas innerhalb der LCD bibliothek überschrieben. das kann aber auch nur so aussehen. solche fehler sind wirklich frickelig :-)

du solltest solche globalen variablen am besten gänzlich vermeiden. leg die daten wenigstens innerhalb main an, und gib wenn nötig nen zeiger drauf an deine routinen weiter.

das mit dem debuggen ist nicht so einfach. erst mal kommts drauf an, mit welchem system (betriebssystem, compiler, debugger) du arbeitest.
dann muss man sich mit dem verwendeten debugger erst mal vertraut machen.
für einen fehler wie von dir beschrieben, wird man auch etwas wissen über die abläufe hinter den kulissen benötigen.

womöglich hats mit nem fehler in einer der verwendeten bibliotheken oder dem interrupt zu tun (wenn da irgend ein anderer teil der software, den du nicht genau kennst aus irgend einem grund etwas in ne falsche speicherzelle schreibt, und diese dann zufällig zu deiner globalen variablen gehört, dann kannst du lange suchen. vor allem, wenn das schreiben durch interupts nicht synchron zu deinem eigentlichen programmablauf ist. da hilft dann auch ein normaler debugger nicht viel weiter).

ich hab aber weder das equipment, noch die nötige erfahrung mit dem controller und den bibliotheken, um dir da noch weiter helfen zu können.

PCMan
18.01.2008, 08:46
Vorallem was ich überhauptnicht blicke: für eine kleine Menüsteuerung habe ich eine Header geschrieben. Wenn ich die nicht einbinde, dann läuft das Pogramm ganz normal. Binde ich sie ein, bekomme ich diese Abstürze. Ich verstehe das aber nicht, weil die Aufrfe der Menübefehle ja noch garnicht stattfinden wen die Programmfehler auftauchen. Ich nehme mal an, dass durch die Menüheader der Code größer wird. Dadurch verschiebt sich der Ort, wo Data abgelegt wird. Und bei genau zufällig diesem Ort habe ich diese Fehlzugriffe von anderen Bibliotheken.
Damn das ist echt stressig :( muss ich jetzt alles neu schreiben!?
Simon

PCMan
18.01.2008, 08:48
Mal ne Frage: ich habe die c-files nicht in der Makefile angegeben. Kann das was ausmachen?

fumir
18.01.2008, 09:11
in einer header datei sollten eigentlich keine daten angelegt werden. bzw. sollte aus einer header datei eigentlich gar kein code entstehen (das ist natürlich nur ne richtlinie)

wenn das einbinden der headerdatei etwas mit dem fehler zu tun haben könnte, dann solltest du diese datei posten :-) ich glaube um den fehler zu finden, müßte man wirklich alle dateien, incl. der verwendeten bibliotheken haben. dazu die hardware. kurz: man müßte das programm selbst übersetzen und debuggen können, um dir weiter zu helfen.
vielleicht findest du jemanden, der sich auskennt, und mal zu dir nach hause kommt.

solange du den fehler nicht gefunden hast, machts wenig sinn alles neu zu schreiben, denn womöglich hast du den fehler dann immer noch drin.

wenn ne datei nicht im makefile angegeben ist, dann wird sie wohl schlimmstenfalls nicht compiliert oder gelinkt. aber da make so was wie ne eigene programiersprache ist, kommts eben drauf an, was genau im makefile drinsteht, wo deine dateien abgelegt sind, etc. etc.

PCMan
18.01.2008, 09:44
Hmm, also ich könnte die Menüheader posten. Aber ich sage gleich: die sieht extrem s chei sse aus, erstmal ewig lang und viel zu kompliziert. Ich kann sie einbinden und sie funktioniert auch. Nur, was mich eben so verrückt macht: die header ist zwar eingebunden, aber ich habe die funktionen darin noch überhaupt nicht aufgerufen und mein Programm stürzt ab.

Hier dennoch die header im Anhang.

Für alle ineteressierten: das ganze handelt sich um ein Projekt für die Naturwissenschaftliche Informatik an der Uni.

vG Simon

PCMan
18.01.2008, 11:20
hm mal so ne ganz doofe Frage: kann es sein, dass mein Programm irgendwo zuviel Speicher in Anspruch nimmt? Z.B. dass der RAM überfüllt wird. Könnte die ganzen Strings aus dem Menue in's Flash-Rom packen, ist eh Unsinn, dass die im Ram rumgeistern...
Hat jemand eine Idee?
Vielen Dank,
Simon

Edit:
Aus Mikrocontroller.net:

malloc() legt Speicherblöcke im Heap an, belegt man zuviel Platz, dann wächst der Heap zu weit nach oben und überschreibt den Stack, und der Controller kommt in Teufels Küche. Das kann leider nicht nur passieren wenn man insgesamt zu viel Speicher anfordert, sondern auch wenn man Blöcke unterschiedlicher Größe in ungünstiger Reihenfolge alloziert/freigibt (siehe Artikel Heap-Fragmentierung).
Kann es sein, dass ich mit meinen ganzen Bitfeldern ungünstige Speicheradressen belege?

PCMan
18.01.2008, 12:01
Noch ein kleiner Nachtrag: folgende Eingabe in der Konsole ergab etwas, dass mich überrascht hat:


>avr-size -C --mcu=atmega32 main.elf

AVR Memory Usage
----------------
Device: atmega32

Program: 20242 bytes (61.8% Full)
(.text + .data + .bootloader)

Data: 2125 bytes (103.8% Full)
(.data + .bss + .noinit)

Ich sehe, dass hier etwas zu voll ist. Jetzt bräuchte ich jemand, der mir erklärt WAS da zu viel Platz belegt. Oder wenn ihr einen Link kennt, der das alles beschribt, als her mit.
vG Simon :-)

fumir
18.01.2008, 19:42
zu viel zeug im RAM würde schon einiges erklären :-)
kann nicht schaden den bedarf an RAM zu überdenken und gegebenenfalls zu reduzieren, bevor du weiter nach anderen fehlern suchst.


also so was wie dein menü gehört wirklich nicht in ne headerdatei.
änder das mal schnell in menue.c bevor noch jemand lacht :-)

wenn du es nicht immer drin haben willst, dann mach das z.b. mit bedingter compilierung (#ifdef MENUE ... #endif oder so)

ein header enthält üblicherweise forward declarations, wird in mehrere quelltextdateien eingebunden und sollte deshalb nichts enthalten, was code oder daten erzeugt.

fumir
18.01.2008, 20:05
die strings der menüs sind doch konstanten und sollten daher ohnehin im FLASH landen. ins ram kämen die nur, wenn du sie in ne variable speichern würdest.

malloc oder sowas hab ich bis jetzt noch nirgens in deinem code gesehen.

im wissenbereich gibts wohl ne nette übersicht zu speicher bei avr-gcc.
die hast du dir doch angeschaut, oder?

McJenso
18.01.2008, 20:53
Hallo,

versuch doch mal das Programm soweit zu kastrieren, dass der Code möglichst klein wird, das Programm noch irgendwie lauffähig ist und der Fehler noch auftritt. Ob das Programm dann noch etwas Sinnvolles macht, ist dabei egal. Das hilft beim Fehlersuchen. Dann stell den GANZEN übriggebliebenen Code AM STÜCK hier rein, event. als Anhabng. Ich glaube nicht, das jemand die ganzen Schnipsel zu einem Programm zusammenfügt. Aber dann könnte man deinen Fehler vielleicht nachvollziehen.
Gruß
Jens

PCMan
21.01.2008, 16:42
Hallo Leute, entschuldigt die späte Antwort.
Zunächst: bitte nicht lachen. Andere sind auch nicht mit C als Muttersprache aufgewachsen. Im übrigem würde ich gerne verstehen, wieso Funktionsrümpfe NICHT in eine Headerdatei gehören, sondern in C-Files? Wenn ich die utils/delay.h aufmache, sehe ich auch Funtkionen und nicht nur Forwrds. Woher kommt diese Konvention? Was für einen Vorteil hat sie?
Dass das definitiv ein Speicherproblem sein muss ist für mich die einzige logische Erklärung. Ich habe heute auch im AVR-GCC-Tutorial von PROGMEM gelesen. leider war ich im Tutorial garnicht soweit fortgeschritten, daher war ich so "deppert" und habe einfach alle Strings belassen wie sie sind.
Weswegen ich nicht *alles* online stelle: naja es gibt headers, die zB für das IO des I2C-EEPROMs nötig sind. Und da ich dachte, die tun nix zur Sache, habe ich es einfach gelassen. Abgesehen davon sieht der Code ziemlich unschön aus und ist schlecht kommentiert. Ein Grund, weswegen er jetzt nochmal überarbeitet wird.
Ich danke euch jedenfalls vielmals für's mitdenken, bei schier unlösbaren Problemen melde ich mich wieder wie gewohnt ;)
vG Simon

P.S.: Wenn die Speicheroptimierung vorrüber ist poste ich nochmal ob's geklappt hat.

fumir
22.01.2008, 10:02
wie du schon sagst ist es nur ne konvention. prinzipiell kannst du die dateien natürlich benennen und auch reinschreiben was du willst (genauso wie man das komplette c-programm auch in ne einzelne zeile schreiben kann, oder das ganze programm mit präprozessordirektiven formulieren kann), solange es dann richtig übersetzt wird.
genaugenommen ist in der sprachdefinition von c/c++ nicht mal festgelegt, das der quelltext als text in einer datei stehen muss (mit nem entsprechenden editor/system könnte das programm z.b. direkt in einer baumstruktur gespeichert werden)

von einer headerdatei (*.h) nimmt man üblicherweise an, dass sie dinge enthält, die keinen code und daten erzeugen, und das man sie deshalb in mehrerer dateien oder auch mehrfach einbinden kann, ohne das es probleme gibt.

wenn du nun also trotzdem code und daten reinschreibst, und ein anderer verwendet die datei (oder schaut sich dein programm an) dann wird er eben wahrscheinlich unzutreffende annahmen über deine datei machen, was zu problemen führen kann.

es gibt wohl ne menge verschiedene gründe für diese konvention und vermutlich kenne ich nicht mal die hälfte davon.

in c++ ists üblich template-code in die *.h zu schreiben. teilweise muss man es sogar machen. aber templates sind auch etwas anderes als normaler c/c++ sourcecode.
bei templates wird erst code erzeugt, wenn das template verwendet wird.
wenn du jedoch ne normale funktion in ne header schreibst und diese dann mehrfach einbindest, dann wird mehrfach code für diese funktion erzeugt. normalerweise will man das nicht.

du kannst die datei doch auch einfach in *.c umbenennen und mit include einbinden. dann hast du praktisch nichts geändert, aber jeder der sich das anschaut, weiß sofort, das in der datei code und daten erzeugt werden.

ansonsten bestätigen ausnahmen die regel :-)