Forum: Mikrocontroller und Digitale Elektronik Stellaris ARM Launchpad, UART, Timer, DHT11 Sensor SW


von Axel S. (axelac)


Angehängte Dateien:

Lesenswert?

Texas Instrument bietet mit dem Stellaris ARM Launchpad ein äußerst 
leistungfähiges Mikrocontrollerentwicklungsboard für einen
Preis um 5 Euro an. Günstiger gehts nicht. (auch in D erhältlich bei 
watterott electronic), insbesondere da dieses Board auch den Programmer 
und eine Spybywire Debugmöglichkeit enthält. Das Board wird mit einem 
USB Kabel mit dem Entwicklungsnotebook oder PC verbunden, damit ist die 
Stromversorgung gesichert, die Programmierung und die Debugmöglichkeit 
von der IDE erfolgt ebenfalls über diese USB Verbindung und weiterhin 
kann das Mikrocontrollerprogramm gleichzeitig über eine virtuelle COM 
Schnittstelle und einer der integrierten UART Schnittstellen serielle 
Ausgaben zu einem Terminalprogramm des Entwicklungsrechner schicken. 
(Natürlich erst nach der Installation der USB Treiber für das 
Launchpad).

Der Controller LM4F120H5QR basiert auf der ARM Cortex 32 Bit Architektur 
mit einer Vielzahl von internen Hardwarekomponenten (zB. 2 12 Bit ADC, 
12 Timer, 1 CAN, 1 USB,  8 UART) 256kB interner Flash und 32 kB RAM. 
(http://www.ti.com/lit/ds/symlink/lm4f120h5qr.pdf) Die wesentlichen 
Treiberfunktionen für die interne Hardware sind im internen ROM des 
Controllers bereits vorcompiliert enthalten. Die entsprechenden Routinen 
werden von TI in der Stellarisware Firmware frei zur Verfügung gestellt.
( http://www.ti.com/lit/ug/spmu019o/spmu019o.pdf ).

Als Entwicklungsumgebung gibt es verschiedene Möglichkeiten, ich habe 
mich für die IAR IDE entschieden, die einigermaßen einfach zu handhaben 
ist und in der frei verfügbaren Version bis zu 32 kB Code erzeugen kann, 
zum Testen also ausreichend. Mit dieser IDE habe ich auch bereits das 
MSP430 (Beitrag "MSP430 Launchpad lcd Ansteuerung, Vergleic. Atmel AVR") Launchpad getestet. 
TI bietet mit dem Code Composer Studio eine auf Eclipse basierende IDE 
an, die keine Einschränkungen hat, aber auch sehr Komplex zu handhaben 
ist. Die Installation der IDE und der notwendigen Treiber zur 
Kommunikation mit dem Board ist eine erste zu meisternde Klippe, die zu 
Problemen führen kann, wenn zB. das Programmverzeichniss und die 
Software nicht in den üblichen Stammverzeichnissen auf Laufwerk C 
sondern auf einer anderen
Festplattenpartition liegen soll.

Nun liegt es nahe, diese Platform mit dem im Hobbybereich gerne 
verwendeten 8 Bit Avr Microcontrollern zu vergleichen, da insbesondere 
die
integrierte Hardware reizt. Man darf aber nicht vergessen, das eine 
32Bit Architektur um Größenordnungen komplexer zu handhaben ist. 
Insbesondere
die integrierte Hardware muss verstanden sein. Andererseits braucht man 
sich wegen der Verfügbarheit der Stellarisware Firmware mit den 
Treiberfunktionen nicht mehr direkt um die einzelnen Hardwareregister zu 
kümmern (wie man dies häufig noch bei den 8 Bit Avr macht), sondern
kann die entsprechenden Stellariswarefunktionen benutzen. Aber auch 
diese müssen mit ihren vielen vordefinierten Parametern erst einmal 
beherscht werden, allein um die auf dem Launchpad vorhandenen 3 LEDs zum 
blinken zu bringen sind etliche Funktionsaufrufe erforderlich.

Für meine ersten Versuche habe ich eine Software entwickelt, welche mit 
einer Timerinterruptroutine die rote und die blaue LED im 5Hz und 0.5 Hz
Rhythmus blinken läßt. Alle 2 s wird außerdem der interne ADC 
ausgelesen, welcher den internen Temperatursensor digitalisiert. 
Außerdem
wird ein simpler DHT11 Temperatur und Feuchtigkeitssensor über die 1wire 
Schnittstelle ausgelesen, für das korrekte Timing waren hier einige
Experimente mit verschiedenen Verzögerungszeiten notwendig. Die 
ermttelten Werte werden mit einem der UARts über die virtuelle COM
Schnittstelle zum PC geschickt.

Sobald man sich mit den neuen Möglichkeiten vertraut gemacht hat, kommt 
einem die 8 Bit Welt sehr einfach vor. Allerdings um LEDs blinken zu 
lassen, ADC auszulesen und eine UART anzusprechen ist dies wie mit 
Kanonen auf Spatzen zu schiessen. Die eigentliche Leistungsfähigkeit der 
Platform
wird man erst bei rechenintensiven Problemen, wie zB. Mustererkennung, 
Sprachanalyse etc. durch die Verwendung der integrierten 
Fließkommarecheneinheit ausnutzen können. Auch die Verwendung von 
kleinen Echtzeitsbetriebsystemen wie zB. das frei verfügbare freeRTOS 
ist möglich.

Ich kann also dieses kleine Platinchen für eigene Experimente mit nach 
oben offener Leistungsfähigkeit nur empfehlen.

von Roland H. (batchman)


Lesenswert?

Danke, schönes Demoprogramm, das mit den umschaltbaren 
RAM-/ROM-Funktionen war mir so nicht bekannt.

Damit es mit einem "stand-alone" ARM GCC kompiliert, benötigt es noch 
ein #define. Kompiliert hat es dann mit
1
#define TARGET_IS_BLIZZARD_RA1

kann aber nicht prüfen, ob das stimmt (warte noch auf die Lieferung).

Fehlt da noch etwas:
1
// Timer0  IntHandler in startup_ewarm.c eingetragen!!

und beim UART sieht es so aus, als ob Interrupts aktiviert werden. 
Fehlen da evtl. die ISRs? Geht das nicht auch ohne die FIFOs?

> Man darf aber nicht vergessen, das eine
> 32Bit Architektur um Größenordnungen komplexer zu handhaben ist.

Man darf getrost diese Behauptung vergessen, denn sie ist nicht richtig. 
Oft wiederholt, meistens ohne Belege. Bitte immer PROGMEM, boot loader, 
fuses usw. einbeziehen und auch an die Klimmzüge oder Trampoline denken, 
welche bei > 64K Zugriffen nötig sind.

> Andererseits braucht man
> sich wegen der Verfügbarheit der Stellarisware Firmware mit den
> Treiberfunktionen nicht mehr direkt um die einzelnen Hardwareregister zu
> kümmern (wie man dies häufig noch bei den 8 Bit Avr macht), sondern
> kann die entsprechenden Stellariswarefunktionen benutzen.

Ist das ein Fortschritt? Das wird kontrovers diskutiert, sofern es um 
die Funktionen geht, welche nicht im ROM sind.

Die im ROM haben den Charme, dass man Flash sparen kann.

> allein um die auf dem Launchpad vorhandenen 3 LEDs zum
> blinken zu bringen sind etliche Funktionsaufrufe erforderlich.

Das ist nur die halbe Wahrheit: Es geht auch mit Null Funktionsaufrufen.
Ich warte immer noch auf meine Lieferung, deshalb weiß ich nicht, ob das 
folgende Fragment funktioniert:
1
// Enable the GPIO port
2
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
3
4
// direction as output, and enable the GPIO pin for digital function
5
GPIO_PORTF_DIR_R = 0x08;
6
GPIO_PORTF_DEN_R = 0x08;
7
8
// Turn on the LED.
9
GPIO_PORTF_DATA_R |= 0x08;
10
11
...
12
13
// Turn off
14
GPIO_PORTF_DATA_R &= ~(0x08);

> für das korrekte Timing waren hier einige
> Experimente mit verschiedenen Verzögerungszeiten notwendig.

Woran lag das? An den Timings oder an dem Korrekturfaktor?
SysCtlDelay() ist auch nur eine for-Schleife,
1
#if defined(codered) || defined(gcc) || defined(sourcerygxx)
2
3
void __attribute__((naked))
4
5
SysCtlDelay(unsigned long ulCount)
6
7
{
8
9
    __asm("    subs    r0, #1\n"
10
11
          "    bne     SysCtlDelay\n"
12
13
          "    bx      lr");
14
15
}
16
17
#endif

insofern ist
1
ms = ROM_SysCtlClockGet()/3000;
2
us = ms/1000;
3
4
ROM_SysCtlDelay( 20*ms );

nur bedingt korrekt.

Das Ding hat zwischen 12 und 25 Timer, da kann man sogar einen der 
64-Bit-Timer opfern, um die Verzögerungen sauber zu messen. Wenn ich 
richtig gerechnet habe, muss man sich da um Überlaufe keine Sorgen mehr 
machen ...

In InitTimer verwendest Du SysCtlClockGet() ohne ROM_ - Präfix.
Dieser Tippfehler kostet Dich 512 Byte Flash :-) Anders formuliert, die 
vier gesparten Zeichen im Quelltext kosten Dich 25% mehr Flash :-)

Die ROM-Variante kommt auf (4.6.2, -Os)

arm-none-eabi-size
   text     data      bss
   2188        0      513

also noch in der attiny/msp430 2k Flash Liga.

Die Flash-Variante kommt auf
   text     data      bss
   3964        0      513

M. W. haben die kleinsten Stellaris CM3 16k Flash, die CM4 32k Flash, 
insofern kann das schon interessant sein.

Bitte die "Mäkelei" nicht falsch verstehen, ich finde das Demoprogramm 
ziemlich gut. Kompakt und alles drin, was man benötigt, um das Ding zum 
Fliegen zu bringen (wenn es dann mal da ist).

von Axel S. (axelac)


Lesenswert?

Vielen Dank für die konstruktiven Anmerkungen. Dies sind meine ersten 
Erfahrungen mit der 32 Bit ARM Architektur. Da ich hier nur den UART Tx 
benötige, habe ich den ursprüngliche benutzten UART Interrupt, der 
ausgelöst wird wenn der Tx FIFO bis zu einem vorgegeben Limit geleert 
ist, dann nicht mehr benutzt. Hier kann also noch aufgeräumt werden.
Die Probleme mit dem Timing des DHT11 lagen nicht an den 
Verzögerungsroutinen, sondern an der mir nicht vollständig vorliegenden 
Dokumentation des vom DHT11 verwendeten 1wire Protokolls.
In der Interruptvektortabelle, die von der IAR IDE automatisch im 
Projekt als startup_ewarm.c eingebunden wird, muss anstelle eines 
vorhandenen default handlers die  Timer0 ISR eingetragen werden.
Der Tippfehler in der SysCtlClockGet() in InitTIMER (statt ROM_Sy... ) 
kostet natürlich nicht 25% des Flash Speichers, da wir im LM4F120H5 
256kB haben, sind die 512Byte natürlich vernachlässigbar ;-)

von Uwe Bonnes (Gast)


Lesenswert?

Bei CM3 hat man meistens den SysTick Timer laufen. Damit lassen sich gut 
Verzoegerungen realisieren, die recht unabhaengig von Takt und 
0ptimierungsgrad des Kompilers sind: Man zaehlt die Differenzen des 
Zeahlerstandes des SysTickTimers. Oder man macht das mit dem DWT Timer.

von Roland H. (batchman)


Lesenswert?

Axel Schnell schrieb:
> kostet natürlich nicht 25% des Flash Speichers, da wir im LM4F120H5
> 256kB haben, sind die 512Byte natürlich vernachlässigbar ;-)

In der Text-Sektion des Kompilats schon. Die "ROM-optimierte" Version 
belegt ca. 2k. Die "nicht optimierte" 2.5k.

Ja, das ist in dem Fall Haarspalterei :-)

Im Fall von 16k/32k Flash ... in größeren Stückzahlen ... wenn der Flash 
knapp wird ... das hat schon was mit den ROM-Funktionen. Das macht in 
diesem Beispiel 50% oder 2k aus.

Uwe Bonnes schrieb:
> meistens den SysTick Timer

Der ist schön portabel, macht nur leider bei 24-Bit schon Feierabend :-)

von Uwe Bonnes (Gast)


Lesenswert?

Abver Du hast doch 32-bit Variable um die Differenzen der 24 bit 
aufzuaddieren.

Aus den NutOs Quellen:
void NutMicroDelay(uint32_t us)
{
#ifdef _NUT_EMULATION_
    usleep(us);
#elif defined(_CORTEX_)
    int32_t start_ticks;
    int32_t current_ticks, summed_ticks=0;
    int32_t end_ticks;

    start_ticks = SysTick->VAL;
    end_ticks = (us * (SysTick->LOAD +1))/NUT_TICK_FREQ;
/* Systick counts backwards! */
    while (summed_ticks < end_ticks)
    {
        current_ticks = SysTick->VAL;
        summed_ticks += start_ticks - current_ticks ;
        if (current_ticks > start_ticks)
            summed_ticks += (SysTick->LOAD +1);
        start_ticks = current_ticks;
    }
#elif defined(_AVR_LIBC_VERSION_)

von Roland H. (batchman)


Lesenswert?

Uwe Bonnes schrieb:
> Abver Du hast doch 32-bit Variable um die Differenzen der 24 bit
> aufzuaddieren.

Das war meinerseits nicht wirklich ernst gemeint, ich schiebe nur 
"Frust" wg. der verlorenen 8-Bit :-)

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Wenn es 32 Bit sein soll, dann schalte den DWT Zähler ein. Der hätte 
aber auch gerne 64 Bit haben können ;-)

von Lutz (Gast)


Lesenswert?

Uwe Bonnes schrieb:
> Bei CM3 hat man meistens den SysTick Timer laufen. Damit lassen sich gut
> Verzoegerungen realisieren, die recht unabhaengig von Takt und
> 0ptimierungsgrad des Kompilers sind: Man zaehlt die Differenzen des
> Zeahlerstandes des SysTickTimers. Oder man macht das mit dem DWT Timer.

Bei "wirklich großen" delays (die ein vielfaches des SysTick-Intervalls 
haben; also gaaanz viele ms), kann man das so machen. Oft braucht man 
aber gerade bei Sensoren etwas im µs-Bereich, und da muß man dann schon 
einen "richtigen" Timer benutzen.

von Uwe Bonnes (Gast)


Lesenswert?

Lutz schrieb:
> Oft braucht man
> aber gerade bei Sensoren etwas im µs-Bereich, und da muß man dann schon
> einen "richtigen" Timer benutzen.

Und? Warum soll da das pollen auf die Differenz im Systick Counter nicht 
funktionieren?

von Lutz (Gast)


Lesenswert?

Lutz schrieb:
> Bei "wirklich großen" delays (die ein vielfaches des SysTick-Intervalls
> haben; also gaaanz viele ms), kann man das so machen. Oft braucht man
> aber gerade bei Sensoren etwas im µs-Bereich, und da muß man dann schon
> einen "richtigen" Timer benutzen.

Weil:
For delays below 100 microseconds, the deviation may increase above 
200%.
Bis zu Faktor 4 Fehler läßt wohl so ziemlich jedes Timing versagen.

von Roland H. (batchman)


Lesenswert?

Lutz schrieb:
> For delays below 100 microseconds, the deviation may increase above
> 200%.

Interessant. Quelle?

von Lutz (Gast)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.