Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * @file main.c
- * @brief Programm zur Demonstration der Verwendung des Beschleunigungssensors MMA7660FC im
- * Zusammenspiel mit der I²C Master Schnittstelle des MSP430G2553 und dem MSP430 launchpad.
- * Das Programm liest die X-, Y- und Z-Komponente des Beschleunigungssensors ein und
- * gibt die Daten im Sekundentakt auf die RS232 Schnittstelle des launchpads aus, so dass
- * die Daten über das virtuelle COM-Port des launchpads auf einem PC eingelesen werden können.
- * @author stesStd
- * @date 07.06.2015
- *
- * @todo
- * - Fehlerbehandlungen einbauen:
- * # I2C-Kommunikation
- * # Zeitüberschreitungen bei den states der main-loop: bisher Einschalten der roten LED
- * - MMA7660 LPM ausnutzen: der Sensor läuft momentan ohne Nutzung seiner Power Optimierung
- * - Erweiterung des Ansatzes zur zeitgleichen Nutzung mehrerer I²C-slaves unter Verwendung
- * von vorgegebenen Slave Adressen
- * - Vervollständigung der Doxygen Dokumentation
- *
- */
- #include <stdint.h>
- #include <stdbool.h>
- /*
- * ======== Standard MSP430 includes ========
- */
- #include <msp430.h>
- /*
- * ======== Grace related includes ========
- */
- #include <ti/mcu/msp430/Grace.h>
- /*
- * ======== Project related includes ========
- */
- #include "i2cSM.h"
- #include "rs232_SM.h"
- /*
- * ======== main ========
- */
- //timekeeping registers
- #define DS3231_TIME_CAL_ADDR 0x00
- #define DS3231_ALARM1_ADDR 0x07
- #define DS3231_ALARM2_ADDR 0x0B
- #define DS3231_CONTROL_ADDR 0x0E
- #define DS3231_STATUS_ADDR 0x0F
- #define DS3231_AGING_OFFSET_ADDR 0x10
- #define DS3231_TEMPERATURE_ADDR 0x11
- /** Datenstruktur zur Übergabe einer Registeradresse und eines Datenbytes */
- typedef union {
- struct ts {
- uint8_t sec; /* seconds */
- uint8_t min; /* minutes */
- uint8_t hour; /* hours */
- uint8_t mday; /* day of the month */
- uint8_t mon; /* month */
- int16_t year; /* year */
- uint8_t wday; /* day of the week */
- uint8_t yday; /* day in the year */
- uint8_t isdst; /* daylight saving time */
- uint8_t year_s; /* year in short notation*/
- #ifdef CONFIG_UNIXTIME
- uint32_t unixtime; /* seconds since 01.01.1970 00:00:00 UTC*/
- #endif
- };
- uint8_t val[2]; /**<Datenarray für I2C Datenübertragung */
- } TUnion_Register;
- int itoa(int n, char s[]);
- int main(void)
- {
- /** Einzelstati, die im Hauptprogramm durchlaufen werden. */
- static enum {
- MMA_initDeactivate, /**< Sensor in standby schalten, damit Steuerregister geschrieben werden können */
- MMA_initCtrlReg, /**< Sensor Steuerregister initialisieren */
- MMA_initActivate, /**< Sensor nach Schreiben der Steuerregister wieder aktivieren */
- MMA_setReadStartReg, /**< Registeradresse für Leseoperation übertragen */
- MMA_readDataReg, /**< Lesen der Ergebnisregister starten */
- MMA_w4Res, /**< auf Abschluss der Leseoperation warten */
- RS232_writeRes, /**< auf Abschluss der RS232 Schreiboperation warten */
- N_cnt /**< letzter enum gibt an, wieviele states definiert sind */
- } eMMA7660state = MMA_initDeactivate;
- /** 7-Bit Adresse des MMA7660FC-Sensors: Dieser Wert muss in das Steuerregister des MSP430
- * eingetragen werden. DEr MSP430 ergänzt das 8. Bit (LSB) mit einer 0 oder einer 1, je
- * nachdem, ob auf den Sensor geschrieben oder vom Sensor gelesen werden soll */
- const uint8_t mmA7660_sensorAddr = 0x68; //ersetzen durch RTC als var name
- /** Definition der an die Steuerregister zu übertragenden Werte (siehe Application note) */
- const uint8_t mma7660InitData[] = {
- 0x05, //00: Adresse des ersten Control Registers
- 0x00, //02: Einstellung für Sleep Count
- 0x04, //03: Einstellung für Interrupt Setup
- 0x00, //04: Einstellung für Mode: der bleibt während der Initialisierung auf inaktiv
- 0x00, //05: Einstellung für SR-Register
- 0x74, //06: Schwelle für Tap Detection: gemäß Appl.-note: 0x6C
- 0x0B //07: Tap Debounce Count: gemäß Appl.-note: 0x08
- };
- /** Datenpuffer zur Aufnahme einer Registeradresse und eines Datenwertes */
- TUnion_Register singleByteDataBuf;
- /** Datenpuffer zum Einlesen der Ergebnisregister */
- uint8_t readBuf[8];
- /** substate vom RS232_writeRes - State */
- static uint16_t m_uiRS232_writeRes_SubState;
- /** Counter, der bei jedem durch den mit Timer A0 realisierten System-Tick inkrementiert wird */
- static volatile uint16_t m_uiTimerCnt = 0;
- Grace_init(); // Activate Grace-generated configuration
- while (1) {
- m_uiTimerCnt++; //System-Tick Zähler inkrementieren
- P1OUT |= BIT5; //P1.5 aktivieren: diese bleibt im on-state, solange die
- //main-loop im active state ist und wird deaktiviert, sobald
- //der sleep mode aktiviert wird: Auf diese Weise kann mit einem
- //Oszi das On/Off -Verhältnis der CPU bestimmt werden.
- ProcessI2C(); //abarbeiten der seit dem letzten Timer-Tick aufgelaufenen I2C-Events
- switch (eMMA7660state) {
- case MMA_initDeactivate:
- //Warten bis Programm gestartet wird, damit der Sensor zur Konfiguration
- //deaktiviert werden kann:
- singleByteDataBuf.s.reg = DS3231_TIME_CAL_ADDR;
- singleByteDataBuf.s.data = 0x00;
- if (!i2cSendData(mmA7660_sensorAddr, 2, NO_RESTART, (const uint8_t*)&singleByteDataBuf)) {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- else {
- eMMA7660state++;
- }
- break;
- case MMA_initCtrlReg:
- //Warten, bis der Sensor deaktiviert wurde, damit anschließend die Übertragung
- //der Konfigurationsdaten gestartet werden kann:
- if (!i2cSendData(mmA7660_sensorAddr, sizeof(mma7660InitData), NO_RESTART, mma7660InitData)) {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- else {
- eMMA7660state++;
- }
- break;
- case MMA_initActivate:
- //Warten, bis die Konfigurationsdaten übertragen sind, damit anschließend der
- //Sensor wieder aktiviert werden kann:
- singleByteDataBuf.s.reg = MODE_REG;
- singleByteDataBuf.s.data = 0x01;
- if (!i2cSendData(mmA7660_sensorAddr, 2, NO_RESTART, (const uint8_t*)&singleByteDataBuf)) {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- else {
- eMMA7660state++;
- }
- break;
- case MMA_setReadStartReg:
- //Warten, bis der Sensor aktiviert ist, damit anschließend die Adresse des
- //ersten zu lesenden Ergebnisregister übertragen werden kann:
- //Wichtig: der Sensor löscht die übertragene Leseadresse, wenn die Schreiboperation
- //mit einem STOP-Signal abgeschlossen wird. Aus diesem Grund darf die Übertragung
- //der Startadresse nicht mit einem STOP-Signal abgeschlossen werden, so dass die
- //nächste Datensequenz (Aufforderung zum Lesezugriff) mit einem RESTART begonnen
- //werden kann (siehe Datenblatt des MMA7660)
- singleByteDataBuf.s.reg = XOUT_REG;
- if (!i2cSendData(mmA7660_sensorAddr, 1, RESTART, (const uint8_t*)&singleByteDataBuf)) {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- else {
- eMMA7660state++;
- }
- break;
- case MMA_readDataReg:
- //Warten, bis die Startadresse übertragen ist, damit anschließend mit dem Einlesen
- //der Ergebnisdaten begonnen werden kann:
- if (!i2cReceiveData(mmA7660_sensorAddr, 8, readBuf)) {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- else {
- eMMA7660state++;
- }
- break;
- case MMA_w4Res:
- //Warten, bis die Startadresse übertragen ist, damit anschließend auf den
- //Abschluss des Einlesens der Ergebnisdaten gewartet werden kann:
- if (i2cGetRdyState() == true) {
- m_uiRS232_writeRes_SubState = 0;
- eMMA7660state++;
- }
- else {
- //Fehlermeldung: rote LED anschalten
- //Zeitintervall des Systemtimers hat für Datenübertragung nicht gereicht!
- P1OUT |= BIT0;
- }
- break;
- }
- //P1.5 ausschalten, bevor in den Sleep-Modus gewechselt wird
- P1OUT &= ~BIT5;
- LPM1;
- }
- return (0);
- }
- int itoa(int n, char s[])
- {
- int ii, signedVal;
- if ((signedVal = n) < 0) {
- n = -n; /* Betrag bilden */
- }
- ii = 0;
- do {
- s[ii++] = n % 10 + '0'; /* 10er Dezimale in ASCII wandeln */
- } while ((n /= 10) > 0);
- if (signedVal < 0) {
- s[ii++] = '-'; /* Vorzeichen zuweisen */
- }
- else if (signedVal > 0) {
- s[ii++] = '+';
- }
- else {
- //nix
- }
- //s[ii] = '\0';
- return ii;
- }
- //********************************************************************************************************/
- /*! @fn function signature
- * @brief short description of function
- * @author stesStd
- * @version x
- *
- * @date __Version x (ab 20yy-mm-dd)__
- * - geändert: 20yy-mm-dd (stesStd)
- * - Kommentierung der Änderungen
- * - Test und Freigabe: 20yy-mm-dd (stesStd)
- * - Testresultate
- *
- * @date __Version 1 (ab 20yy-mm-dd)__
- * - erstellt: 20yy-mm-dd (stesStd)
- * - Erstausgabe der Funktion
- * - Test und Freigabe: 20yy-mm-dd (stesStd)
- * - Testergebnisse
- * @param [in] Name (Typ): Beschreibung oder leer
- * @param [out] Name (Typ): Beschreibung oder leer
- * @param [in,out] Name (Typ): Beschreibung oder leer
- * @return Typ: Beschreibung oder void
- *
- * Zweck:
- * ------
- * -# Zweck x(n)
- * - Zweck x(n).y
- * -# Zweck x(n+1)
- * - Zweck x(n+1).y
- *
- * Umsetzung:
- * ----------
- * - Beschreibung (n)
- * - Beschreibung (n+1)
- *
- * @sa Referenzen auf andere Funktionen oder löschen
- *
- * @init Schritte zur Vorbereitung des Funktionsaufrufs oder nicht erforderlich
- *
- * @test Prüfen, ob nach dem Aufruf:
- * - Test 1
- - Test ...
- * - Test n
- *
- * @code
- * kein Beispielcode
- * @endcode
- *
- * @warning - Warnhinweis 1 oder nicht belegt
- *
- * @riskman - RM-Hinweis 1 oder keine Hinweise zum Risikomanagement
- *
- * @todo
- *
- ************************************************************************************************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement