-         

Ergebnis 1 bis 10 von 10

Thema: Hat jemand eine Idee bevor ich verzweifel?

  1. #1
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414

    Hat jemand eine Idee bevor ich verzweifel?

    Anzeige

    Bei folgendem Code.. und c=0x00;
    Code:
    #define LCD_LL 0x0f
    
    static uint8_t lcd_cpos;
    static uint8_t lcd_line;
            c=0x00;
            lcd_line = 0x00;
            lcd_cpos = (c - (lcd_line * LCD_LL));
    Kommt bei mir in lcd_cpos immer 1 raus.. obwohl es 0 sein muss.
    Bei (lcd_line * LCD_LL) müsste es sich zu 0 x 15 also 0 berechnen was es nicht tut und bei c=0 dann 0 - (0 x 15) = 0 !!! nicht 1
    Erst hab ich gedacht, es liegt am casting weil c ein typ char ist und hab alles mit (uint8_t) versehen aber es ändert sich nichts.
    Es werden auch keine Bereichsgrenzen überschritten, keine Division durch 0.. oder sonstiger Unfug...

    Ist der Compiler defekt?
    Ich habs unter Amtel Studio 6.1 2730 SP2 im Sim laufen lassen und da kommt auch 1 raus. CPU Defekt ist damit auszuschließen.
    Da dieser Machinecode simuliert, scheint ja der Code nicht ok zu sein... hier mal eine Ausgabe mit -O0

    Code:
       596:         c=0x00;
    000008A1  STD Y+2,R1        Store indirect with displacement 
       597:         lcd_line=0x00;
    000008A2  STS 0x00BF,R1        Store direct to data space 
       599:         lcd_cpos = (c - (lcd_line * LCD_LL));
    000008A4  LDS R25,0x00BF        Load direct from data space 
    000008A6  LDI R24,0xF0        Load immediate 
    000008A7  MUL R25,R24        Multiply unsigned 
    000008A8  MOV R25,R0        Copy register 
    000008A9  CLR R1        Clear Register 
    000008AA  LDD R24,Y+2        Load indirect with displacement 
    000008AB  ADD R24,R25        Add without carry 
    000008AC  SUBI R24,0xFF        Subtract immediate 
    000008AD  STS 0x00BE,R24        Store direct to data space
    Und nu mit -O1

    Code:
       597:         lcd_line=0x00;
    00000257  STS 0x00BF,R1        Store direct to data space 
       599:         lcd_cpos = (c - (lcd_line * LCD_LL));
    00000259  LDI R24,0x01        Load immediate 
    0000025A  STS 0x00BE,R24        Store direct to data space
    In beiden Fällen kommt 1 raus, im letzten lädt er die 1 sogar einfach nur ins R24 und schreibt sie weg.
    Das er beim Optimierungslauf mit O1 die Multiplikation mal eben weg spart kann ich mir ja noch erklären - aber das er das mit einer 1 ersetzt.. nicht!

    Angaben zur Toolchain:
    Installed Packages: Atmel AVR (8 bit) GNU Toolchain Snapshot - 3.4.2.1000
    AVR Toolchain 8 Bit
    Version: AVR8_Toolchain_Version:3.4.2.974 GCC_VERSION:4.7.2
    Package GUID: 01BAAEB9-EC97-4398-95D1-633DB220CD77
    Company: Atmel
    HelpUrl:
    Release Description: AVR Toolchain For 8-Bit Devices

    Falls das wirklich ein Compilerfehler ist, dürfte das mehr Leute betreffen... und nicht nur RP6ler..
    Ich wollte es morgen mal mit der recht neuen 6.2 Studio Beta probieren.. in der Hoffnung, das da eine neuere Toolchain mit bei ist.

    Ich verstehs aber trotzdem nicht. HILFÄÄÄÄÄ


    (die 3.4.3 Toolchain, welche bei Atmel angeboten wird, ändert auch nichts daran... grade noch probiert...)
    Gruß
    Geändert von RolfD (14.05.2014 um 01:29 Uhr)
    Sind Sie auch ambivalent?

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.401
    Zitat Zitat von RolfD Beitrag anzeigen
    Bei folgendem Code.. und c=0x00;
    Code:
    #define LCD_LL 0x0f
    
    static uint8_t lcd_cpos;
    static uint8_t lcd_line;
            c=0x00;
            lcd_line = 0x00;
            lcd_cpos = (c - (lcd_line * LCD_LL));
    Kommt bei mir in lcd_cpos immer 1 raus.. obwohl es 0 sein muss.
    Ist der Compiler defekt?
    Mit Sicherheit nicht. Ein Compiler, bei dem die Integer-Multiplikation nicht funktioniert, kommt nicht durch die automatischen Regressionstests. Da braucht man nicht den Assemblercode anzuschauen. Ist Zeitverschwendung.

    Wenn ich der Compiler wäre, würde ich den ganzen gezeigten Code wegoptimieren. lcd_cpos wird zwar berechnet aber nie verwendet, also braucht es nicht berechnet zu werden. Außerdem ist alles außerhalb jeder Funktion und wird daher nie ausgeführt.

    Oder ernsthaft: zeig mehr von deinem Code, am besten auch die Zeile, in der der Fehler steckt.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  3. #3
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    @Klebwax
    Also im Prinzip stimme ich Dir ja zu... insbesondere die Aussage zu den Regressionstests.. aber Du kannst mir schon zutrauen, das ich das nicht in der Luft freihängend teste...
    Der Code sieht zum testen grade so aus:
    Code:
    int16_t lcd_putchar(char c)
    {
        static bool nl_seen;
        static bool cursor_seen;
        uint8_t i;
    
        if (cursor_seen) { // erstes Zeichen nach \v, Cursorposition also \v%c
            //if (c <= LCD_LL) lcd_line=0;
            c=0x00;
            lcd_line=0x00;
            //else lcd_line =  c % LCD_LL; //aus kumulierter Cursorpos Zeile und Spalte berechnen
            lcd_cpos = (c - (lcd_line * LCD_LL));
            lcd_data(LCD_SET_DDADR + LCDLineAdr[lcd_line] + lcd_cpos, LCD_CMD);
    // hier steht auch noch was code, der aber nichts zur Sache tut
            cursor_seen = false; //ok es geht weiter im String
            return 1; // darf nicht zur weiteren Auswertung gelangen.
        } else { // wenn keine Cursorposition, dann normales Zeichen
    //.. blabla.. hier gehts noch weiter
    Der Code sollte eigentlich später so aus sehen:
    Code:
    int16_t lcd_putchar(char c)
    {
        static bool nl_seen;
        static bool cursor_seen;
        uint8_t i;
    
        if (cursor_seen) { // erstes Zeichen nach \v, Cursorposition also \v%c
            if (c <= LCD_LL) lcd_line=0;
            else lcd_line = c % LCD_LL; //aus kumulierter Cursorpos Zeile und Spalte berechnen
            lcd_cpos = (c - (lcd_line * LCD_LL));
            lcd_data(LCD_SET_DDADR + LCDLineAdr[lcd_line] + lcd_cpos, LCD_CMD);
    // hier steht auch noch was code, der aber nichts zur Sache tut
            cursor_seen = false; //ok es geht weiter im String
            return 1; // darf nicht zur weiteren Auswertung gelangen.
        } else { // wenn keine Cursorposition, dann normales Zeichen
    //.. blabla.. hier gehts noch weiter
    die lcd_data(LCD_SET_DDADR + LCDLineAdr[lcd_line] + lcd_cpos, LCD_CMD);
    ist definiert als void lcd_data( uint8_t data, uint8_t mode ); , LCDLineAdr[] ist ein Array aus 4 ints
    Laut Breakpoints und Einzelschrittverfolgung ist vor Einsprung in lcd_data der Wert von lcd_cpos=1 wenn c=0.

    Ich versuche dort, aus einer uint8 Zahl die eine cursorposition auf einem langen String (bis 80 Zeichen, enthält letztlich Reihe und Spalte in einem Display) zu berechnen. Ich würde ja mit Modulo % arbeiten aber da hat jemand das erste Zeichen auf die 0.te Display Position definiert und modulo Operationen mit 0 erzeugen schon mal Div/0 Fehler... Also Suche ich einen weg um aus Angaben wie 0x14 die 2.te Zeile in der 4 Spalte zu berechnen wobei die Koordinaten dann aber leider Zeile 1, spalte 3 ist. Letzteres sind Vorgaben die ich so übernehmen muss um Code Compatibilität zu halten.

    Und zur Aussage "Da braucht man nicht den Assemblercode anzuschauen." .. ich würds selbst nicht glauben wenn ich es nicht mit eigenen Augen sehen würde!
    Gruß
    Geändert von RolfD (14.05.2014 um 07:24 Uhr)
    Sind Sie auch ambivalent?

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.401
    Sorry, wenn ich das so sage, aber von deinem Code krieg ich Augenkrebs. Da gehen Code und Kommentar so durcheinander, nach if oder else könnte man eine neue Zeile anfangen ....


    Aber zu deinem Problem mit Modulo:
    Code:
    #define LENGHT 20
    
    int main() {
        int i;
        int xpos;
        int line;
    
        for(i = 0; i < 80; i++) {
            xpos = i % LENGHT;
            line = i / LENGHT;
            printf("%d, %d, %d\n", i, xpos, line);
        }
    }
    Dieser Code sollte das machen, was du beschreibst und funktioniert ohne Probleme auf meinem PC. Ich probiere C-Code gerne auf dem PC aus (ich verwende keine Atmel und hab daher das Studio nicht)

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  5. #5
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.410
    Blog-Einträge
    101
    Zitat Zitat von RolfD Beitrag anzeigen
    Code:
    #define LCD_LL 0x0f
    
    static uint8_t lcd_cpos;
    static uint8_t lcd_line;
            c=0x00;
            lcd_line = 0x00;
            lcd_cpos = (c - (lcd_line * LCD_LL));
    Hat jemand eine Idee bevor ich verzweifel?
    Schnell meine Anteilnahme zeigen Hab zwar von C kaum Ahnung; mir erscheinen aber die beteiligten Variablen nicht passend.

    Eine Multiplikation mit zwei 8 Bit Variablen könnte eine 16Bit Variable füllen.
    Eine Subtraktion könnte eine negative Zahl ergeben.

    Geht es besser statt mit uint8_t mit int16_t oder noch größer und später lcd_cpos auf 8 Bit bringen?

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  6. #6
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Also die Version von Klebwax gibt bei
    lcd_cpos = c % LCD_LL;
    lcd_line = c / LCD_LL;

    und c=0 als Ergebnis für lcd_cpos UND lcd_line je = 255 bzw. vermutlich eher -1 aus obwohl alles uint8_t ist bzw. auf solches gecastet wurde.
    So hab ich das aber auch mal gelernt...
    In wie weit das mit int bzw. längeren vorzeichenbehafeten Zahlen anders wird, muss ich mir noch mal genauer ansehen.
    Übrigends lässt sich der Code von mir recht gut ohne Augenkrebs lesen wenn man sich den in ein Editor mit Syntax highligtning packt, Klebwax. Und zum Angucken war die Kurze Version aus Post 1 gedacht.
    Aber zu dem Progrämmchen...
    LCD_LL ist bei mir 15 und das was du auf 20 gesetzt hattest.
    Die Ausgabe dazu lautet:
    Code:
    [READY]
    0, 255, 255
    1, 0, 255
    2, 1, 255
    3, 2, 255
    4, 3, 255
    5, 4, 255
    6, 5, 255
    7, 6, 255
    8, 7, 255
    9, 8, 255
    10, 9, 255
    11, 10, 255
    12, 11, 255
    13, 12, 255
    14, 13, 255
    15, 14, 255
    16, 255, 0
    17, 0, 0
    18, 1, 0
    19, 2, 0
    20, 3, 0
    21, 4, 0
    22, 5, 0
    23, 6, 0
    24, 7, 0
    25, 8, 0
    26, 9, 0
    27, 10, 0
    28, 11, 0
    29, 12, 0
    30, 13, 0
    31, 14, 0
    32, 255, 1
    33, 0, 1
    34, 1, 1
    35, 2, 1
    
    ---3<---
    
    78, 13, 3
    79, 14, 3
    Man beachte, das die erste Ziffer die koordinate -1,-1 hat, und die ganze erste Line die line-1 ist. Also so dolle getestet, wie du sagst, war das auch nicht
    Der Weg funktioniert zwar... auch wenn da noch nicht alles auf 0 ausgeht... aber das kann man ja ggf. anpassen. Ich wollte aber explizit die Division und den Modulo Operator vermeiden wie ich auch schrieb! Allerdings kann so auch kein Div0 Fehler auftauchen wie ich befürchtete. In so fern.. deine Lösung funktioniert.
    Zudem erklärt das aber nicht, warum der Compiler 0 - (0 x 15) zu 1 und nicht wie richtig, zu 0 bringt.. und zwar unabhängig von der Optimierungsstufe.
    Ich denke auch nicht, das generell dem Compiler zu misstrauen ist, ich kann mir aber sehr gut vorstellen, das genau so ein Term in den regression Tests nicht getestet wird weil er eigentlich Unsinning ist. Es wäre zumindest nicht der erste Bug im gcc.
    Kann ja sein das ich noch irgend ein mitwirkenden Fehler drin habe.. will ich ja garnicht ausschließen... mir wär nur halt lieber, ich hätte eine schlüssige Erklärung für das (für mich) komische Ergebnis 1.
    Geändert von RolfD (14.05.2014 um 19:40 Uhr)
    Sind Sie auch ambivalent?

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.401
    Also die Version von Klebwax gibt bei
    lcd_cpos = c % LCD_LL;
    lcd_line = c / LCD_LL;

    und c=0 als Ergebnis für lcd_cpos UND lcd_line je = 255 bzw. vermutlich eher -1 aus obwohl alles uint8_t ist bzw. auf solches gecastet wurde.
    So hab ich das aber auch mal gelernt...
    Da kann ich dir nicht folgen. 0 geteilt durch was auch immer außer 0 gibt 0. Also 0 / 15 = 0, simple Bruchrechnung.
    So ist es auch bei modulo, das Ergebniss ist 0.

    Einen Zusammenhang mit der Größe der Variablen kann ich nicht erkennen.

    Code:
    #define LENGHT 16
    
    int main() {
        int i;
        uint8_t xpos;
        uint8_t line;
    
        for(i = 0; i < 80; i ++){
            xpos = i % LENGHT;
            line = i / LENGHT;
            printf("%d, %d, %d\n", i, xpos, line);
        }
        return 0;
    }
    Code:
    0, 0, 0
    1, 1, 0
    2, 2, 0
    3, 3, 0
    4, 4, 0
    5, 5, 0
    6, 6, 0
    7, 7, 0
    8, 8, 0
    9, 9, 0
    10, 10, 0
    11, 11, 0
    12, 12, 0
    13, 13, 0
    14, 14, 0
    15, 15, 0
    16, 0, 1
    .
    .
    77, 13, 4
    78, 14, 4
    79, 15, 4
    Das ganze erzeugt mit gcc. Ich hab das ganze auch mal auf einem PIC24 laufen lassen. printf() hab ich da nicht, aber auch der Debugger zeigt mir das gleiche wie oben. Der Compiler ist auch der gcc.
    Ich kann dir also nicht weiter helfen

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  8. #8
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    OK... Fehler gefunden... und er ist so blöd, das es schon fast peinlich ist.

    #define LCD_LL LCD_LINE_LENGTH-0x01

    Die Konstantendefinition für LCD_LL geht in die Hose denn durch die "PunktvorStrich" Regel ...
    wird dann

    lcd_cpos = (c - (lcd_line * LCD_LL));
    zu
    lcd_cpos = (c - (lcd_line * 16 - 1 ));
    und damit erklärt sich die "Fehlrechnung".

    Richtig wäre gewesen
    #define LCD_LL (LCD_LINE_LENGTH-0x01)
    ...
    Da hab ich mir dann doch nen kapitalen Bock geschossen Kommt davon wenn man im Halbschlaf irgendwas ausprobiert ohne nachzudenken. Ihr dürft mich nun alle mal auslachen
    Gruß und Danke fürs mitdenken helfen..
    Sind Sie auch ambivalent?

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.557
    ... Ihr dürft mich nun alle mal auslachen ...
    Ich jedenfalls bin nur vergnügt und beruhigt, weil solche Fehler bei mir nicht unüblich sind.
    Ciao sagt der JoeamBerg

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    938
    Zitat Zitat von RolfD Beitrag anzeigen
    ... Ihr dürft mich nun alle mal auslachen ...
    Ich stelle mich dazu: Ich habe dieser Tage ebenfalls verzweifelt an der falschen Stelle einen Fehler gesucht, bis ich die Ursache in meiner Unachtsamkeit und dem RAM-Paging des MidRange-PIC fand: HIGH-Byte und LOW-Byte des ADC-Ergebnisses liegen in verschiedenen RAM-Pages

Ähnliche Themen

  1. switch case aud union und struct gehen schief, hat einer eine Idee warum ???
    Von jdelphi im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 0
    Letzter Beitrag: 29.09.2011, 14:04
  2. Signalweiche mit Avr- jemand eine idee??
    Von spass-basti im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 14
    Letzter Beitrag: 23.04.2007, 16:21
  3. Potentialproblem. Jemand eine idee?
    Von sebastian.heyn im Forum Elektronik
    Antworten: 7
    Letzter Beitrag: 22.08.2005, 17:55
  4. Bild auf TV erzeugen - Jemand eine IDEE?
    Von sebastian.heyn im Forum AVR Hardwarethemen
    Antworten: 20
    Letzter Beitrag: 03.05.2005, 14:28
  5. Ports beim ATmega32 gehen nicht! warum?? jemand eine Idee!!
    Von raptor_79 im Forum AVR Hardwarethemen
    Antworten: 4
    Letzter Beitrag: 18.01.2005, 15:55

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •