Professionelle MC-Programmierung kann in Assembler oder in C erfolgen.

Hier wird demonstriert, an welche zusätzlichen Dinge herkömmliche C-Entwicklung im Vergleich zur Arduino-Programmierung am Beispiel der blinkenden LED berücksichtigen muss:

Betrachten wir zunächst eine sogenannte Header-Datei, die vom Hauptprogramm inkludiert, d.h. eingebunden wird:

  1. #ifndef LED_H   // damit diese Datei in größeren Projekten
  2. #define LED_H   // ohne Fehler auch mehrfach inkludiert werden könnte
  3.  
  4.  
  5. // Pins der angeschlossenen LEDs
  6. // (Quasi-Konstante wird durchgehend groß geschrieben)
  7.  
  8. #define LED1 6
  9.  
  10. #define ON 1
  11. #define OFF 0
  12.  
  13.  
  14. #endif /* LED_H */

Quellcode led.h

Hier wird neben ON und OFF der Pin an dem die LED angeschlossen wird, definiert. (So muss man sich keine Pin-Nummern merken.)

Nun folgt das Hauptprogramm, dass unter anderem diese Header-Datei einbindet:

  1. // Header-Dateien einbinden
  2. #include <avr/io.h>             // allg. MC-Definitionen
  3. #include "../../led/led/led.h"  // unsere Definitionen
  4.  
  5. #define F_CPU 12000000UL        // Taktfrequenz, des MC
  6. #include <util/delay.h>         // damit hier die richtige Länge des Delay bereichnet werden kann
  7.  
  8. // Das Richtungsregister des PIN wird auf Ausgang geschaltet
  9. void ledInit()
  10. {
  11.     DDRD |= (1 << LED1);
  12. }
  13.  
  14. // Schaltet die LED ein oder aus
  15. void ledSwitch(int led, int onOff)
  16. {
  17.     if (onOff == ON)
  18.         PORTD |= (1 << led);
  19.     else
  20.         PORTD &= ~(1 << led);
  21. }
  22.  
  23. // Hauptprogramm
  24. int main(void)
  25. {
  26.     ledInit();
  27.     while(1)  // Endlosschleife
  28.     {
  29.         ledSwitch(LED1,ON);
  30.         _delay_ms(1000);
  31.         ledSwitch(LED1,OFF);
  32.         _delay_ms(1000);
  33.     }
  34. }


Im Vergleich zum Arduino-Programm erspart man sich

  • Probleme mit dem Heraussuchen und Konfigurieren der richtigen Header-Dateien (delay)
  • die Hauptfunktion (wird automatisch generiert)
  • die Konfigurierung des PIN auf Ausgang und das Schalten des PIN sind viel einfacher, weil dies Funktionen größtenteils schon vordefiniert sind.
    Eine Erklärung dieser Konfiguration mit Hilfe der Bit-Operatoren folgt für fortgeschrittene Programmierer weiter unten.


Bit-Operatoren


Operator

Beispiel

Bedeutung

<< 
i << 2

2x Linksschieben (Multiplikation mit 2er-Potenzen)

>> 
i >> 1

1x Rechtsschieben (Division durch 2er-Potenzen)

&
i & 7

bitweises UND mit 0000 00111

^
i ^ 7

bitweises XOR

|
i | 7

bitweises ODER

~
~7

Bitweise Negation

<<=
i <<= 3

i = i << 3

>>=
i >>= 3

i = i >> 3

&=
i &= 3

i = i & 3

^=
i ^= 3

i = i ^ 3

|=
i |= 3

i = i | 3















Beispiel:

#include <avr/io.h>

#define MEINBIT 2

PORTA |= (1 << MEINBIT);    // Setzt Bit 2 an Port A auf 1 (ohne die anderen Bits zu beeinflussen)
PORTA &= ~(1 << MEINBIT);   // löscht Bit 2
an Port A

Mit dieser Methode lassen sich auch mehrere Bits eines Registers gleichzeitig setzen und löschen:

#include <avr/io.h>

DDRA &= ~((1<<PA0) | (1<<PA3));   // PA0 und PA3 als Eingaenge
PORTA |= (1<<PA0) | (1<<PA3);   // (Interne Pull-Up fuer beide einschalten)


Last modified: Wednesday, 8 September 2021, 10:03 AM