www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Messchieber Programm


Autor: Remo Hug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich hab nun mal ein Programm in MikroC geschrieben, mit welchem ich die 
Billigmesschieber auslesen kann.

Das Programm funktioniert soweit.
Nun meine Fragen:

-Was würdet ihr anderst machen (Optimieren)?

Auch im Hinblick, dass ich 4 Messchieber einlesen will, den wert 
umrechnen und jeden wert auf einer separaten Achs-Anzeige anzeigen will.
Des weiteren sollte noch ständig eine Tastatur abgefragt werden.

-Wie würdet ihr das bei 4 Messchiebern lösen, wenn jeder Messchieber
 CLOCK- und DATA-Leitung hat und die an RB0 bis RB7 angeschlossen sind?



#include "Display_utils.h"

unsigned char Zaehler1 = 0;
unsigned char Wert_Lesen = 0;
unsigned char Read_Bit = 0;
unsigned char Minuswert = 0;
unsigned char Wert_Array[24];

unsigned long Wert_Eingelesen = 0;
unsigned long Rechnungswert = 0;
unsigned long Schlusswert = 0;

const float x = 806.299;


void interrupt(){
     
     if (INTCON.INTF){
        INTCON.INTF = 0;
        if (Wert_Lesen){
           Wert_Array[Read_Bit] = PORTB.F1;
           if (Read_Bit == 0){
              Wert_Lesen = 0;
              INTCON.GIE = 0;
           }
           --Read_Bit;

        }
        else{
           if (OPTION_REG.INTEDG){
              OPTION_REG.INTEDG = 0;
              TMR1H = 0xFE;
              TMR1L = 0x6F;
              T1CON.TMR1ON = 1;
           }
           else{
              OPTION_REG.INTEDG = 1;
              T1CON.TMR1ON = 0;
              PIR1.TMR1IF = 0;
           }
        }
     }
     
     if (PIR1.TMR1IF){
        PIR1.TMR1IF = 0;
        T1CON.TMR1ON = 0;
        Wert_Lesen = 1;
        Read_Bit = 23;
     }
     

}


void main()
{



    //* inizialisieren der PORT's *//
    ADCON1 = 0;
    TRISA = 0x00;                           // Set PORTA as output
    TRISB = 0xFF;                           // Set PORTB as input
    TRISD = 0x00;                           // Set PORTD as output
    PORTA = 0x00;
    PORTB = 0x00;
    PORTD = 0x00;

    //* Interrupts erlauben *//
    INTCON.GIE = 1;
    INTCON.PEIE = 1;
    INTCON.INTE = 1;

    //* inizialisieren des TIMER1 fuer 100us Interrupt *//
    PIE1.TMR1IE = 1;
    PIR1.TMR1IF = 0;
    T1CON.T1CKPS1 = 0;
    T1CON.T1CKPS0 = 0;
    T1CON.TMR1CS = 0;
    TMR1H = 0xFE;
    TMR1L = 0x6F;
    T1CON.TMR1ON = 0;

    //* Port RB0/INT für steigende Flanke Konfigurieren
    OPTION_REG.INTEDG = 1;

    //* main loop *//

    do {
    Zaehler1 = 0;
    Wert_Eingelesen = 0;
      do{
         if (Zaehler1 > 0){
            Wert_Eingelesen <<= 1;
            Wert_Eingelesen |= Wert_Array[Zaehler1];
            ++Zaehler1;
            }
         else{
            Minuswert = Wert_Array[Zaehler1];
            ++Zaehler1;
         }
      }while (Zaehler1 < 24);

      if (Minuswert){
         Rechnungswert = (~Wert_Eingelesen & 8388607);
      }
      else{
         Rechnungswert = Wert_Eingelesen;
      }


      Schlusswert = (Rechnungswert*100) / x;

      PORTD = mask(Schlusswert % 10u,0);
      PORTA = 0x01;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask((Schlusswert / 10u) % 10u,0);
      PORTA = 0x02;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask((Schlusswert / 100u) % 10u,1);
      PORTA = 0x04;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask(Schlusswert / 1000u,0);
      PORTA = 0x08;
      Delay_us(250);
      PORTA = 0x00;

      INTCON.GIE = 1;
    }while (1);
}


freundliche Grüsse

Remo

Autor: Remo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Das kann ja nicht sein, das ich ein Prog. schreibe, das nicht mehr
verbessert werden kann. ;-)

freundliche Grüsse

Remo

Autor: Helmut -dc3yc (dc3yc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht kannste noch dazuschreiben, für welche Umgebung das Ganze 
ist: Prozessor, Compiler, Meßschieber usw.usf....

Servus,
Helmut.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu deiner Interrupt Funktion kann ich nicht viel sagen, kenne deinen 
Prozessor nicht und weiß daher nicht, ob das so alles koscher ist. Die 
Routine selbst ist aber dem Ansehen nach ziemlich kurz und sieht soweit 
vernünftig aus.

Das hier
    do {
    Zaehler1 = 0;
    Wert_Eingelesen = 0;
      do{
         if (Zaehler1 > 0){
            Wert_Eingelesen <<= 1;
            Wert_Eingelesen |= Wert_Array[Zaehler1];
            ++Zaehler1;
            }
         else{
            Minuswert = Wert_Array[Zaehler1];
            ++Zaehler1;
         }
      }while (Zaehler1 < 24);

kannst du auch kürzer schreiben. den if-else in der innersten Schleife 
brauchst du im Grunde nicht, da gehts es ja nur darum, dass der erste 
Wert im Wert_Array anders behandelt wird. Das kannst du aber auch vor 
die Schleife ziehen
    Wert_Eingelesen = 0;
    Minuswert = Wert_Array[0];
    Zaehler1 = 1;
    do {
      Wert_Eingelesen <<= 1;
      Wert_Eingelesen |= Wert_Array[Zaehler1];
      ++Zaehler1;
    } while (Zaehler1 < 24);

Und damit könnte man dann auch die do-while Schleife gegen die 
universellere und hier wohl auch angebrachtere for-Schleife austauschen
    Wert_Eingelesen = 0;
    Minuswert = Wert_Array[0];
    for( Zaehler1 = 1; Zaehler1 < 24; ++Zaehler1 )
      Wert_Eingelesen = ( Wert_Eingelesen << 1 ) | Wert_Array[Zaehler1];

Zugegeben: die letzte Transformation ist mehr syntaktischer Zucker als 
sonst was.

Auch der Sinn der Variablen Minuswert ist dann etwas fraglich. Warum in 
eine andere Variable umkopieren und nicht in weiterer Folge nicht gleich 
Wert_Array[0] verwenden? OK. Der Compiler wird die Variable 
wahrscheinlich sowieso selbst rausschmeissen und diese Transformation 
machen, ich seh allerdings auch keinen wesentlichen dokumentarischen 
Wert in dieser Umkopiererei. Ein kleiner Kommentar an der Stelle
      if (Wert_Array[0]){           // wenn negativ
         Rechnungswert = (~Wert_Eingelesen & 8388607);
      }
      else{
         Rechnungswert = Wert_Eingelesen;
      }

erfüllt den gleichen Zweck und ist vielleicht klarer als der Umweg über 
eine Zwischenvariable.

Was du dir aber überlegen solltest (und da kommt jetzt wieder meine 
Unkentnis des Prozessors ins Spiel): Ich habe in main nichts gesehen, 
was mich an Interrupts zulassen/sperren erinnert. Was passiert 
eigentlich, wenn genau während dieser Ausleserei ein Interrupt zuschlägt 
und das Wert_Array verändert?

> Rechnungswert = (~Wert_Eingelesen & 8388607);

Das würde ich nicht so schreiben. Die Zahl 8399607 sieht da etwas 
seltsam aus. In Hex geschrieben, wäre das
   Rechnungswert = (~Wert_Eingelesen & 0x7FFFFF);

und jetzt sieht der kundige C-Leser dann auch, dass das offenbar eine 
Maskierung sein soll, die die untersten 23 Bits herausmaskiert. An 
dieser Stelle ist die Hex-Zahl dem Verständnis wesentlich zuträglicher 
als die Dezimalzahl.
(PS: Bist du dir sicher, dass negative Zahlen lediglich durch Bitumkehr 
dargestellt werden, also im Einerkomplement. Ist etwas unüblich. 
Normalerweise benutzt man das 2-er Komplement: Alle Bits umdrehen und 1 
dazuzählen.)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Auch im Hinblick, dass ich 4 Messchieber einlesen will, den wert
> umrechnen und jeden wert auf einer separaten Achs-Anzeige anzeigen will.
> Des weiteren sollte noch ständig eine Tastatur abgefragt werden.

Das hier
     PORTD = mask(Schlusswert % 10u,0);
      PORTA = 0x01;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask((Schlusswert / 10u) % 10u,0);
      PORTA = 0x02;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask((Schlusswert / 100u) % 10u,1);
      PORTA = 0x04;
      Delay_us(250);
      PORTA = 0x00;

      PORTD = mask(Schlusswert / 1000u,0);
      PORTA = 0x08;
      Delay_us(250);
      PORTA = 0x00;


soll offenbar sowas wie ein Multiplex des Anzeigen sein. Das würd ich 
als allererstes mal eliminieren. Die Wartezeiten bei der Ausgabe sind 
nicht schön. Dafür würd ich einen Timer einsetzen, der 
interruptgesteuert reihum die Anzeigen auf den neuesten Stand bringt.

Damit bist du dann auch erst mal dein wesentliches Zeitbestimmendes 
Problem in der Hauptschleife los und kannst dich neuen Schandtaten 
widmen :.-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

> Zugegeben: die letzte Transformation ist mehr syntaktischer Zucker als
> sonst was.

Summa summarum würde sich dann beispielsweise folgender Code ergeben
  do {
    Wert_Eingelesen = 0;
    for( Zaehler1 = 1; Zaehler1 < 24; ++Zaehler1 )
      Wert_Eingelesen = ( Wert_Eingelesen << 1 ) | Wert_Array[Zaehler1];

    if (Wert_Array[0])           // wenn negativ, dann positiv machen
      Wert_Eingelesen = ~Wert_Eingelesen & 0x7FFFFF;

    Schlusswert = (unsigned long)( 100 * Wert_Eingelesen / x + 0.5 );

    PORTD = mask(Schlusswert % 10u,0);
    PORTA = 0x01;
    ....

Ist kürzer ohne dass die Übersichtlichkeit darunter gelitten hat.

Die Zahl 806.99 in x (warum heist das eigentlich x und nicht irgendein 
sinnvoller Name, der mir sagt von welchen Einheiten in welche 
umgerechnet wird) ist mir auch noch nicht ganz koscher. Wahrscheinlich 
ist das ja irgendein Quotient aus den technischen Daten des Schiebers. 
Wenn dein Proz eine Gleitkommaeinheit hat, ist das ok. Wenn nicht würde 
ich die Division tatsächlich hier in den Code mit reinziehen und auf 
Floating Point verzichten.

Autor: Remo Hug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl

Danke für deine ausführungen.

Der Prozessor ist ein PIC16F877A.

@Helmut:

Compiler: wie geschrieben MikroC
Messchieber: Wabeco -> Produkte -> Zubehör -> Messwerkzeuge -> Digitale 
Längenmessleisten (geht leider nicht zum verlinken)

freundliche Grüsse

Remo Hug

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.