Skip to content

Hinweise zur C-Programmierung

Viele nützliche Hinweise zur C-Programmierung in Michael Barr - Embedded C Coding Standard (siehe 1. Kapitel)

Namenskonventionen

  • Alle Variablen, Funktionen und Module werden im snake_case geschrieben.
  • Datentypen bekommen zusätzliche den Präfix _t: Beispiel uint8_t
  • Globale Funktionen sollten immer mit den zugehörigen Modulnamen beginnen.
  • Konstanten verwenden großgeschreiben: SNAKE_CASE

Module

  • Aufteilen des Programm-Codes in mehrere Module!
  • Ein Modul besteht in der Regel aus einer Header- und einer C-Datei.
  • Diese Tragen den gleichen Namen!

Aufteilung des Quellcodes in C- und Header-Datei

Inhalt C-Datei bsp.c Header bsp.h
Kopf
// Benötige Bibliotheken
#include <msp430.h>
#include <stdint.h>

// Eigenen Header-Datei
#include "bsp.h"
// Include guard
#ifndef BSP_H_
#define BSP_H_
Globale Variablen
// Globale Variablen
const uint8_t bsp_liste[] = { 1, 2, 3 };
uint8_t bsp_zahl = 3;
// Deklaration der globalen Variablen
extern const uint8_t bsp_liste[];
extern uint8_t bsp_zahl;
Lokale Variablen
// Lokale Variablen
static uint8_t *pointer;
---
Prototypen lokaler Funktionen
// Prototypen
static void set_output(uint8_t pattern);
---
Globale Funktionen
// Globale Funktionen
void bsp_init(uint8_t x) {
  P1DIR = 0xFF;  // Alle Pin als Ausgänge
  P1OUT = 0x00;   // Alle Ausgänge auf Low
}

uint8_t bsp_show() {
  set_output(*pointer);
  return 1;
}
// Prototypen der globale Funktionen
void bsp_init(uint8_t x);
uint8_t bsp_show();
Lokale Funktionen
// Lokale Funktionen
static void set_output(uint8_t pattern) {
  P1OUT = pattern;
}
---
  ---
#endif /* BSP_H_ */

Konstanten

  • Verwenden von Macros:

    • Beispiel: #define TEST (0x04)
    • Macros besitzten keine Datentypen und werden durch den Präcompiler 1:1 in den Quelltext eingefügt.
    • Immer zusätzliche Klammern setzen!

    Beispiel einer fehlerhaften #define-Anweisung

    #define X 1+2
    #define Y 2*X  // -> 2*1+2 = 4
    ...
    #define X (1+2)
    #define Y (2*X)  // -> (2*(1+2)) = 6
    

    - Macros können global in Header definiert werden, oder lokal in der C-Datei.
    - Im Header sollte der Name immer mit dem Modulnamen beginnen BSP_X um Kollisionen mit anderen Modulen zu verhindern.
    - Verwenden von const:
    - Beispiel: const uint8_t KONSTANTE = 0x55;
    - Eine echte Konstante mit Datentyp!
    - Global: "doppelte" Definition
    - In C-Datei: const uint8_t BSP_KONSTANTE = 0x55;
    - In Header const extern uint8_t BSP_KONSTANTE;
    - Lokal: static hinzufügen!: static const uint8_t KONSTANTE = 0x55;
    - Praxis-Beispiel: Registermap eines SPI-Slaves als eigene Header-Datei: https://github.com/jhester/msp430-cc1101/blob/master/registers.h

Enumerations

  • Enumerations sind eigenen Datentypen in C, die eine Liste von Konstanten enthalten, die automatisch von C-Compiler durchnummeriert werden können.
  • Beispiel:

Automatisch nummeriertes Enum mit Längenangabe

typedef enum {
  ALARM_BATTERY_LEVEL = 0,
  ALARM_WATCHDOG,
  ALARM_KEY_PRESSED,
  ALARM_BATTERY,
  ALARM_LENGTH
} alarms_t;

  • Enumations können auch eigene Werte zugewiesen werden.
  • Auf diese Art und Weise können Bitfelder definiert werden.

Enum für ein Bitfeld

typedef enum {
  ISR_WDT = (1 << 0),
  ISR_I2C_UPDATE = (1 << 1),
  ISR_BUTTON_PRESSED = (1 << 2),
  ISR_BATTERY_READY = (1 << 3),
  ISR_ALARM_BATTERY_LEVEL = (1 << 5),
  ISR_ALARM_WATCHDOG = (1 << 6),
  ISR_BUTTON2_PRESSED = (1 << 7)
} isr_flags_t;

Structs

  • Der Struct ist ein eigener Datentyp, in dem mehrere Variablen verschiedenen Types in ein Objekt zusammengefasst werden können.

Beispiel-Struct

typedef enum {
  GENDER_MALE = 1, GENDER_FEMALE = 2
} gender_t;

typedef struct {
  uint8_t age;
  gender_t gender;
  uint16_t size_mm;
  char name[8];
  uint32_t day_of_birth;
} person_t;

const person_t my_person = { .age = 23, .gender = GENDER_MALE, .size = 0x2233,
    .name = "Robert", .day_of_birth = 0xaabbccdd };

  • So kann z. B. die Übergabe eines Stucts in einer Funktion erfolgen, ohne dass die Daten einzeln übergeben werden müssen.
  • Organisation von komplexen Datenstrukturen!

Quellcode-Dokumentation mit Doxygen