www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wie String im Software-Interrupt zerhacken und characterweise ausgeben?


Autor: Markus B. (ysr)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich programmiere derzeit eine Lageerkennung für eine Art Wippe. Die 
interruptgesteuerte Zustandserkennung funktioniert soweit tadellos. Den 
Zustand gebe ich derzeit über "t" für zu tief, "h" für zu hoch und "w" 
für in Waage interruptgesteuert über die serielle Schnittstelle aus, 
sobald das USART Data Register leer ist.
Nun möchte ich den Zustandausgabe gerne mit einen String realisieren. 
Leider funktioniert die Zeichenzerhackung des Strings während des 
Interrupts nicht bzw. kommt gleich die Fehlermeldung "status has an 
incomplete type".
Ich verwende derzeit einen Atmega16 (mit 4Mhz) auf einem STK500 und die 
serielle Übertragung läuft mit 8N2 (8Datenbits, no parity und 2 
stopbits) bei 9600 Baud ab.

Hier ein Auszug aus dem Quellcode der main.c, wobei denke ich nur der 
untere Teile interessant ist im ISR (USART_UDRE_vect):

#include <avr/io.h>                  // Namen der IO Register
#include <avr/interrupt.h>

#define F_CPU 4000000UL              // CPU-Takt muss vor der <util/delay.h> stehen!
#include <util/delay.h>
#include "uart.h"

// INT0 = zu tief -->LED0, INT2 = zu hoch -->LED2, waage (Standard, bei Abweichung wird IRQ ausgelöst) -->LED1
volatile char zustand;
volatile char status[];
volatile int flag_tief, flag_hoch;
//volatile char text[] = "Hallo Welt." CR;


void start_Uebertragung(void)
{
  UCSRB |= (1<<UDRIE);      // wenn UDRIE = 1 dann Interrupt weil Data Register Empty

}

void stop_Uebertragung(void)
{
  UCSRB &= ~(1<<UDRIE);      // wenn UDRIE = 0 dann Interrupt stoppen, weil Data Register Full
  PORTB |= (1<<PB7);      // Status für serielle Übertragung auschalten

  PORTB |= (1<<PB0)|(1<<PB1)|(1<<PB2);  // LED0, LED1 und LED2 aus
}

int main(void)
{
     DDRB |= 0b11111111;             //PORTB als Ausgang definieren
     PORTB |= 0b11111111;          //PORTB auf Low setzen (Leds aus)
  
  uart_init();          // UART initialisieren

  GICR = (1<<INT0) | (1<<INT1);  // IRQ an INT0 und INT1 aktivieren
  MCUCR =(1<<ISC00) | (0<<ISC01) | (1<<ISC10) | (0<<ISC11);  // LOGICAL CHANGE an INT0 bzw. INT1 -->IRQ

  while(1)
  {
    cli();
    
    if(/*zustand == 't' && */flag_tief == 1)
    {
    PORTB |= (1<<PB1)|(1<<PB2);  // LED1 und LED2 aus
    PORTB &= ~(1<<PB0);      // LED0 an für zu tief
    start_Uebertragung();
    }
    else if(/*zustand == 'h' && */flag_hoch == 1)
    {
    PORTB |= (1<<PB1)|(1<<PB2);  // LED1 und LED2 aus
    PORTB &= ~(1<<PB2);      // LED2 an für zu hoch
    start_Uebertragung();
    }
    else if(flag_hoch == 0 && flag_tief == 0)
    {
    zustand = 'w';

    start_Uebertragung();

    PORTB |= (1<<PB0)|(1<<PB2);  // LED0 und LED2 aus --> gerade kein Interrupt!
    PORTB &= ~(1<<PB1);      // LED1 anschalten --> Wippe in der Waage
    }
    
    GICR = (1<<INT0) | (1<<INT1);  
    sei();  
  }
}

ISR (INT0_vect)            // Interrupt "zu tief" durch den rechten Taster (Switch 2)
  {  
    GICR &= (0<<INT0);

    if(PIND & ~(1 << PD2))      // wenn aktueller Pegel LOW...
    {
    zustand = 'h';
    flag_hoch = 1;
    flag_tief = 0;
    }
    if(PIND & (1 << PD2))      // wenn aktueller Pegel HIGH...
    {
    zustand = 'w';
    flag_tief = 0;
    flag_hoch = 0;
    }
  }

ISR (INT1_vect)            // Interrupt "zu hoch" durch den linken Taster (Switch 3)
  {
    GICR &= (0<<INT1);

    if(PIND & ~(1 << PD3))      // wenn aktueller Pegel LOW...
    {
    zustand = 't';
    flag_tief = 1;
    flag_hoch = 0;
    }
    if(PIND & (1 << PD3))      // wenn aktueller Pegel HIGH...
    {
    zustand = 'w';
    flag_tief = 0;
    flag_hoch = 0;
    }
  }

ISR (USART_UDRE_vect)        // USART Data Register Empty
  {
    /*  UDR = zustand;        // Sende "zustand"  --> funktioniert!

      PORTB &= ~(1<<PB7);      // Status-LED für serielle Übertragung ein

      stop_Uebertragung();*/
    int i = 0;

    if(zustand == 'w')
    {
    status = "in Waage";
/*    status[0] = 'i';
    status[1] = 'n';
    status[2] = ' ';
    status[3] = 'W';
    status[4] = 'a';
    status[5] = 'a';
    status[6] = 'g';
    status[7] = 'e';
*/    }
    if(zustand == 't')
    {
    status = "zu tief";
/*    status[0] = 'z';
    status[1] = 'u';
    status[2] = ' ';
    status[3] = 't';
    status[4] = 'i';
    status[5] = 'e';
    status[6] = 'f';
    status[7] = ' ';
*/    }
    if(zustand == 'h')
    {
    status = "zu hoch";
/*    status[0] = 'z';
    status[1] = 'u';
    status[2] = ' ';
    status[3] = 'h';
    status[4] = 'o';
    status[5] = 'c';
    status[6] = 'h';
    status[7] = ' ';
*/    }

    while(status[i] != '\0')
      {                             
        UDR = status[i]; 
          i++;
      }
      PORTB &= ~(1<<PB7);            // Status-LED für serielle Übertragung ein
    stop_Uebertragung();
  }

Kenne mich mit der seriellen Übertragung im Speziellen noch nicht so gut 
aus, hoffe ihr könnt mir da ein wenig helfen bzw. kleine Hinweise 
gebenwie man es mit dem incomplete type und der Zeichenzerhackung 
hinbekommt. Sitze nun schon den ganzen Sonntag an der Aufgabe, 
durchforste das Forum, stehe aber so langsam aufm Schlauch...

Vielen Dank im Voraus für eure Hilfe!

Viele Grüße
Markus

Autor: Joachim K. (minifloat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst Strings nicht zuweisen. Die müssen Zeichenweise reinkopiert 
werden.
Auf dem PC nimmt man dazu strcpy() aus der string.h

Ich würde das anders machen:

static char meldungen[3][9] =
{
   {"zu hoch"},
   {"zu tief"},
   {"in waage"}
}

char *zgr;

und nachher einfach
zgr = &meldungen[0][0]; //Zeiger zeigt auf das z von "zu hoch"
zgr = &meldungen[1][0]; //Zeiger zeigt auf das z von "zu tief"
zgr = &meldungen[2][0]; //Zeiger zeigt auf das i von "in waage"

oder
zgr = meldungen[0]; //Zeiger zeigt auf das z von "zu hoch"
zgr = meldungen[1]; //Zeiger zeigt auf das z von "zu tief"
zgr = meldungen[2]; //Zeiger zeigt auf das i von "in waage"

mfg mf
ps: nachher dann

while(*zgr)//'\0' ist gleich 0x00, Schleife läuft bis Nullzeichen da 
ist.
{
   UDR = *zgr;
   zgr++;
}

Autor: Matthias N. (nippey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, was mir gerade als erstes auffällt:
volatile char status[];
ohne Größenangabe für das Array wird Status nur als Pointer 
initialisiert, du würdest bei folgenden Operationen wild in anderen 
Daten rum schreiben.
Wenn du folgendes machst:
status = "zu hoch";
Müsste der Compiler was dagegen haben, du hast leider nicht geschrieben 
auf welche Programmzeile sich die Fehlermeldung bezieht.

Am besten initialisierst du das Array status ausreichend groß:
volatile char status[15];

und nutzt zum Speichern von Strings entweder die von dir auskommentierte 
Methode oder
[code]strcpy(status, "zu hoch");[/copy]

Autor: Joachim K. (minifloat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und eine Bremse beim UART-Beschreiben wäre super.
sowas hier z.B.
while(! (UCSRA & (1 << UDRE)) )
      ;
 mfg mf

Autor: Matthias N. (nippey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Mini Float:
Die Methode gefällt mir noch besser! ;)
Ist gerade bei Interrupt Anwendungen viel besser, da schneller.

@ Markus
Du solltest nur Sicherstellen das eine Manipulation des Text-Zeigers 
verhindert wird, wenn gerade eine Übertragung läuft.
Bei deiner aktuellen Programmstruktur ist das aber unbedenklich.

Autor: Markus B. (ysr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,
vielen vielen Dank für eure Hilfe. Habe es nun zum Laufen bekommen, 
klappt super! ;)

Viele Grüße
Markus

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.