www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 ADS7888 RS232


Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe da ein paar Fragen.

Benutzt wird der MSP430F149, Takt 7,3728 MHz (ACLK), IAR Software. 
ADS7888 (8bit ADC)

Funktionsweise des Programms:
Programm soll den Timerwert hochzählen und danach jeweils die Daten aus 
dem ADC auslesen und dann zum PC über RS232 schicken.


Das Programm (siehe Anhang) läuft durch, wenn man segmentweise 
durchgeht, aber nicht, wenn es alleine durchlaufen soll (run). Leider 
wird kein Fehler angezeigt, deswegen bin ich aufgeschmissen. Kann jemand 
helfen

Danke im Voraus

Rico

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das Programm (siehe Anhang) läuft durch, wenn man segmentweise
>durchgeht, aber nicht, wenn es alleine durchlaufen soll (run).
Was heißt segmentweise?
Debug-Modus Einzelschritt oder mit Breakpoints oder was?

Überprüfe Deinen Code nochmal auf "groben Unfug" oder bei der 
Formatierung ist was schiefgelaufen...
Einige Ungereimtheiten:
//Timereinstellungen 
CCR0  = 0;                               // z�hlt bis 500                      
TACTL = TASSEL_1 + MC_2;                // ACLK, upmode
CCTL0 = CCIE;                           // CCR0 timer interrupt enabled
das zählt alles mögliche aber bestimmt nicht 500 !

//Wenn interrups nicht zur�ckgesetzt werden l�uft die ISR immer weiter
{
  
  TACCR0 += 7372800;                          // ACLK/1000 = ca 7372 f�r 1000                     
                                                 Samples pro sekunde
Was hast Du denn für'n Super-MSP erwischt ;-)
Mein Timer_A hat nur 16-bit, also maximal 65535

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Was heißt segmentweise?

Damit ist das Schrittweise weitergehen im Debug-Modus gemeint. Das mit 
den Zählerständen habe ich gestern Abend geändert, natürlich ist es 
ziemlicher Unfug, aber ich denke nicht, dass es wirklich daran liegt. 
Sondern irgendwas mit den Interrupts nicht funktioniert.

Im Debug-Modus liest er die gewandelten U-Werte aus dem ADC und schickt 
sie danach zum PC.

Der MSP soll, solange wie er funktionstüchtig ist, in der ISR bleiben 
und nur das eine machen.... (erstmal)

Mittlerweile habe ich das Programm umgeändert und habe jetzt die Stelle 
an der es "stockt" und zwar sendet er immer noch nicht und ich glaube es 
hat was mit den folgenden Zeilen zu tun. Oder muss ich irgendwelche 
Zeiten einhalten oder noch andere Register umschreiben?

hier >>UCTL0 &= ~SWRST;                     // USART freigeben
       IE1   |= UTXIE0;                     // + UTXIE0 TX- und 
RX-interrupts anschalten
    zeigerText = & (ADC_results[(sample_count)]);
    while (!(IFG1 & UTXIFG0));
    TXBUF0 = (*zeigerText++);

    UCTL0 = 0x11;
    IE1   = 0x00;

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich wette mal, dass deine ISR so lange dauert, dass in der 
Zwischenzeit schon wieder der Timer rumgekommen ist. Wenn ich das 
richtig sehe, hast du jetzt 7,3728MHz / 65000, das bedeutet, dein 
Timer-Int kommt alle 8,8ms.

Und woher soll deine UART-Sende-Routine eigentlich wissen, wieviele 
Bytes sie versenden soll? Da dieht irgendwie kein Schwein durch. Der 
Kompiler müsste doch auch zumindest jede Menge Warnungen ausspucken, was 
soll bitte "volatile unsigned transmit" darstellen?

Alles in die ISR zu packen, ist grober Unsinn, sowas macht man indem man 
in der ISR ein Flag setzt, und in der Hauptschleife dann schaut, was zu 
tun ist.

Das Bitegeschiebe kannst du dir sparen, wenn du gleich 2 Pointer auf ein 
Result-Register machst und die direkt beschreibst. Und dann aus dem 
Result-Register in das Array kopieren. Geht viel schneller. Mit viel 
Glück optimiert das der Compiler so hin, aber nur mit Glück.

Miss mal nach, wie lange deine ISR dauert.

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Volantine:
Zur Optimierung von Rechenprozessen versucht der Compiler, so viele 
Werte wie moeglich in den Prozessor-Registern zu halten. Das kann unter 
Umstaenden in die Hose gehen, weil sich Speicherinhalte auch ohne Wissen 
des Compilers aendern koennen (z.B. Timer). Mit "volatile" wird der 
Compiler angewiesen, einen Code zu erzeugen, der jedesmal bei Benutzung 
der volatile-Variablen direkt auf die Speicheradresse zugreift und diese 
niemals in einem Prozessor-Register haelt


Fehler/Warnungen wurden nicht angezeigt!

Ich kürzte mal mein Programm und grenzte den Fehler ein. Dieser löst 
aus, wenn diese beiden Befehle

1. _BIS_SR(GIE);
2. IE1 |= UTXIE0 ;

zusammentreffen.


Irgendwie vertragen die beiden sich nicht. Wenn der 1. gesetzt ist dann 
unterbricht das Programm, wenn der 2. Befehl ausgeführt wird....
wenn ich 2. raus nehme dann funktioniert es (siehe main3).

Wie misst man die Dauer eines Programmdurchlaufs? Mache das gerade mit 
dem Oszilloskop. Wieviel Takte benötigen eigentlich die einzelnen 
Befehle? Kann das irgendwo nachgelesen werden?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>1. _BIS_SR(GIE);
>2. IE1 |= UTXIE0 ;
>Irgendwie vertragen die beiden sich nicht.
Hä?
2. aktiviert den USART Transmit-Interrupt
1. ist die globale Interruptfreigabe, ohne die geht 2. auch nicht!
Die müssen sich vertragen und tun das auch, weil's so gewollt ist!
Der Fehler liegt wo anders!

>Wie misst man die Dauer eines Programmdurchlaufs? Mache das gerade mit
>dem Oszilloskop.
GPIO an Anfang des Programabschnitts setzen und am Ende zurücksetzen. 
Impulsbreite mit Oszi messen = Dauer

>Wieviel Takte benötigen eigentlich die einzelnen
>Befehle? Kann das irgendwo nachgelesen werden?
Sicher doch! Im User-Guide am Ende des Kapitels "Instruction Set"

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>2. IE1 |= UTXIE0 ;
>Irgendwie vertragen die beiden sich nicht. Wenn der 1. gesetzt ist dann
>unterbricht das Programm, wenn der 2. Befehl ausgeführt wird....
Hmm... und wo ist die ISR für UTXIFG ?
Vergessen zu posten oder keine definiert?
Falls nicht definiert, ist klar dass sich der µC aufhängt, weil er ins 
Nirwana springt...

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Hä?
Hä?

habe ja nicht so viel code geschrieben. ging daher nochmals die register 
im datenblatt durch. habe keinen weiteren fehler gefunden.

ich habe noch eine frage und zwar, wenn IE1 |= UTXIE0; nicht gesetzt 
ist, kann dann der msp überhaupt daten über die uart senden? was macht 
der UTXIE0 interrupt?

Autor: rico (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe den letzten kommentar nicht gelesen, dann hat sich meine frage 
erledigt. denke ich. ich glaube ich habe es gerafft...

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rico wrote:

> Zur Optimierung von Rechenprozessen versucht der Compiler, so viele
> Werte wie moeglich in den Prozessor-Registern zu halten. Das kann unter
> Umstaenden in die Hose gehen, weil sich Speicherinhalte auch ohne Wissen
> des Compilers aendern koennen (z.B. Timer). Mit "volatile" wird der
> Compiler angewiesen, einen Code zu erzeugen, der jedesmal bei Benutzung
> der volatile-Variablen direkt auf die Speicheradresse zugreift und diese
> niemals in einem Prozessor-Register haelt

Das weiß ich selbst. Ich meinte eher das Weglassen des eigentlichen 
Typs. "volatile unsigned transmit" wird laut C-Standard als int 
angenommen, aber willst du das?

Und was willst denn mit dem TX-Interrupt? Der kommt, wenn ein Byte 
fertig über die USART geschickt wurde. Wenn du da keine ISR deklariert 
hast, und du aktiviert den GIE, krachts natürlich beim Eintreffen des 
TX-Interrupts.

Autor: rico (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile nutzte wegen des flags, welches ich in der ISR setzte, aber 
durch den fehlerhaften Interrup "IE1 |= UTXIE0;" kam der flag nicht wie 
erwartet und das wollte ich mit "volatile unsigned transmit" 
erschlagen....


aber ich habe noch ein anderes porblem und zwar bezieht sich das auf den 
ADS7888. das im programm (main5.c) läut im debug-modus einwandfrei 
durch, aber im run-modus kommen am µC nur 0x00 an. Wieso?

ich schrieb noch ein anderes programm , welches nur 100 werte 
hintereinander aus  dem ADC  lies und speichert. das funktioniert! 
komisch, weil ich ja auch nicht unbedingt was anderes mache.

vielleicht durchen die beiden uart, die nicht gleichzeitig initaliliert 
sein dürfen oder?????

Gruß R

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Error: main5.c missing

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rico wrote:

> aber ich habe noch ein anderes porblem und zwar bezieht sich das auf den
> ADS7888. das im programm (main5.c) läut im debug-modus einwandfrei
> durch, aber im run-modus kommen am µC nur 0x00 an. Wieso?

Hmmm...meine Glaskugel sagt immer noch, dass deine ISR viel zu lange 
dauert und in der Zwischenzeit der Timer noch paar mal überläuft. Aber 
meine Glaskugel kann sich auch täuschen.

Man kann problemlos beide USARTs nutzen, man muss nur aufpassen, dass 
man sich mit den ISRs nicht verhaspelt.

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
dauerte ein wenig, da ich die datei zerstörte und noch mal schreiben 
musste.....

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
do 
{
  IFG2 &=~ URXIFG1;                    // URXIFG1 = 0 in IFG2 register
} while (URXIFG1 & IFG2);       
ADC_Byte1=RXBUF1;
Was soll das machen?
Du setzt URXIFG1 zurück und überprüfst in while (URXIFG1 & IFG2) 
praktisch sofort danach, ob's schon wieder gesetzt wurde. Wenn nicht, 
wird do-while beendet! D.h. Du wartest nicht wirklich auf die Antwort 
vom ADS7888!

Besser:
IFG2 &=~ URXIFG1; 
while (~(URXIFG1 & IFG2));  // solange warten, bis Byte komplett empfangen
ADC_Byte1=RXBUF1;

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hiermit funktioniert es. habe das programm genommen, welches die daten 
hintereinander ausliest und so umgemodelt.... (main6.c)

Wieso es jetzt funktiniert, dass weiß ich nicht. ich denkemal, ein bit 
in einem register oder so.


wäre gut zu wissen wo der fehler lag.


danke für die hilfen und antworen :) hilft ja immer weiter, wenn mal 
andere gedanken ins hirn kommen ....

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>hiermit funktioniert es.
Ganz ehrliche Antwort?
Glaub ich nicht!

Übrigens, ich korrigiere mein letzes Posting:
while (!(IFG2 & UTXIFG1));   // USART1 TX buffer ready?
IFG2 &=~ URXIFG1;            // RX-Flag löschen
TXBUF1 = 0x00;               // Byte senden
while (~(URXIFG1 & IFG2));   // solange warten, bis Byte komplett empfangen     
ADC_results[2*(sample_count)]=RXBUF1;

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
habe es gerade nochmal ausprobiert und es geht immer noch. ich 
verkleiner die Spannung am ADC input und der gewandelte wert ändert sich 
wie erwartet .....

was soll ich tun?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mach das immer so: (für einen LTC1864L)
volatile UINT16 ActualSample;
volatile unsigned char* pRawSampleHigh = (unsigned char*)&ActualSample;
volatile unsigned char* pRawSampleLow = (unsigned char*)(&ActualSample)+1;

void SPIGetData(void)
{
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
        TXBUF1 = 0x00;
        do
        {
          IFG2 &=~ URXIFG1;
        }
        while (URXIFG1 & IFG2); 

        *pRawSampleHigh = RXBUF1;
        
        while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?  
        TXBUF1 = 0x00;      
        
        do
        {
          IFG2 &=~ URXIFG1;
        }
        while (URXIFG1 & IFG2);
    
        *pRawSampleLow = RXBUF1;

}

Das aktuelle 16-Bit Sample steht dann in ActualSample.

Diese komische do while Schleife ist schon wichtig, ist auch in den 
TI-Beispielen so. Interessiert aber nur, wenn man das Chip-Select dann 
wieder bedienen muss. Das CS ist beim LTC1864 gleichzeitig der 
Sample-Start, das bediene ich mit dem Timer A und einer geschickten 
Verknüpfung der Output-unit mit 2 CCR Registern und dem CCR-Interrupt. 
Somit hab ich eine äquidistante Abtastung, weil das CS in Hardware 
generiert wird.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arrghhhhh!!!!
Jaja...SPI ist ja synchron, war irgendwie bei UART....

Sicher braucht man eine Abfrage, ob die Daten schon komplett empfangen 
wurden, aber diese ominöse do-while Schleife halte ich nach wie vor für 
falsch, auch wenn TI sie postuliert! Oder steh ich jetzt total auf'm 
Schlauch???
do
{
  IFG2 &=~ URXIFG1;
}while (URXIFG1 & IFG2); 
Zuerst lösche ich URXIFG1 und frage gleich danach ab, ob's wieder 
gesetzt wurde. Wenn der Code schneller durchläuft, als die 
SPI-Datenübertragung braucht, dann bin ich in der while-Abfrage, bevor 
die Daten komplett übertragen wurden, URXIFG1 ist dann noch nicht 
gesetzt und ich verlasse do-while --> Fehler!

Ich glaube das Programm funktioniert trotzdem, weil die SPI mit hoher 
Baudrate betrieben wird und do-while einfach als Delay wirkt... wäre 
aber genausogut durch ein paar NOP's erledigt!

Die für mich richtige Implementierung ist immer noch:
TXBUF1 = 0x00;               // Byte senden
while (~(URXIFG1 & IFG2));   // solange warten, bis Byte komplett empfangen 

Autor: rico (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeit:

Habe jetzt die zeiten durchgemessen: 11,3 µs für ads_results, 10,3 µs 
für bitoperatonen,fürden der rest der if schleife kommen ca .9µs drauf. 
insgesamt braucht der prozess aber 9"ms" wieso dauert der teil so lange. 
bekommt der µC die ISR und die if (k == 1){..} nicht schneller hin? Was 
passiert in der Zeit?  Hat man da irgedwelchen einfluss, dass schneller 
zu machen?

Autor: rico (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
jetzt dauert der prozess seine 1ms. bin aber mit dem programm (main7.c) 
wieder in die isr gewandert :/. toll finde ich das auch nicht.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>jetzt dauert der prozess seine 1ms.
Nö, der "Prozess" (was auch immer Du damit genau meinst) ist 
wesentlich schneller!
Überschlagsmäßig dauert Deine SPI-Kommunikation 16Bit*2/7,3728MHz = 
4,34µs.
Die UART zum PC (8+2)Bit/115200 = 86,8µs
"Echte" Wartezeiten in den while-Schleifen dürfte es nicht geben, da die 
Kommunikation ja ansonsten nicht stattfindet. Und der Rest ist 
Krims-Krams (10-20µs vielleicht). Kommst'de insgesamt auf ca. 100µs.
Aber das Toggeln der LED (dessen Periodendauer Du wahrscheinlich misst) 
geschieht ja auch in Deiner ISR und die wird von Dir genau alle 1ms 
aufgerufen!

>bin aber mit dem programm (main7.c)
>wieder in die isr gewandert :/. toll finde ich das auch nicht.
Was spricht dagegen?
Bei ISR's muss man sich nur darüber im Klaren sein, dass das was man 
darin ausführt erledigt sein muss, bevor der nächste IRQ die ISR 
startet!

Autor: rico (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK,

dann lasse ich es so wie es ist....


Die Zeit, die das Programm (Prozess) "main6.c" für einen Durchlauf, 
sprich das Auslösen des Interrupts und abarbeiten der Befehle, dauert 
über 9 ms. Und das verstehe ich nicht ganz. Nur weil ich das Programm 
nicht in der ISR durchführe?


Danke nochmals an alle Mitwirkende


Rico:

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.