From 362251773d94393cf46084106b6975758d72669a Mon Sep 17 00:00:00 2001 From: Frederik Beimgraben Date: Wed, 2 Jul 2025 21:21:47 +0200 Subject: [PATCH] feat: LCD working! --- .settings/org.eclipse.core.resources.prefs | 2 + Board.h | 248 +++++++++++++++++++++ Debug/.clangd/compile_commands.json | 17 +- constants.h | 16 +- i2c.c | 149 +++++++++++++ i2c.h | 44 ++++ i2c_lcd.c | 132 ----------- i2c_lcd.h | 18 -- keypad.c | 28 ++- lcd.c | 86 +++++++ lcd.h | 35 +++ main.c | 158 +++++++------ 12 files changed, 684 insertions(+), 249 deletions(-) create mode 100644 Board.h create mode 100644 i2c.c create mode 100644 i2c.h delete mode 100644 i2c_lcd.c delete mode 100644 i2c_lcd.h create mode 100644 lcd.c create mode 100644 lcd.h diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 31af992..24a2c3d 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -3,6 +3,8 @@ encoding//Debug/driverlib/MSP430FR2xx_4xx/subdir_rules.mk=UTF-8 encoding//Debug/driverlib/MSP430FR2xx_4xx/subdir_vars.mk=UTF-8 encoding//Debug/jsmn/subdir_rules.mk=UTF-8 encoding//Debug/jsmn/subdir_vars.mk=UTF-8 +encoding//Debug/latex/subdir_rules.mk=UTF-8 +encoding//Debug/latex/subdir_vars.mk=UTF-8 encoding//Debug/makefile=UTF-8 encoding//Debug/objects.mk=UTF-8 encoding//Debug/sources.mk=UTF-8 diff --git a/Board.h b/Board.h new file mode 100644 index 0000000..939e298 --- /dev/null +++ b/Board.h @@ -0,0 +1,248 @@ +/* --COPYRIGHT--,BSD + * Copyright (c) 2017, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * --/COPYRIGHT--*/ +/** + * === + * Board.h + * === + * This file is meant to provide generic GPIO selection definitions that allows + * DriverLib to be used portably across different LaunchPads. The same module + * pin might not be populated on the same physical port and pin on different + * LaunchPads. + * + * This file is intended to be modified and updated by individual users based + * on application need. It will be initially populated according to common + * peripherals available on a LaunchPad board, but by all means not complete. + * + * GPIO_PRIMARY_MODULE_FUNCTION indicates Port SEL bits are 01 + * GPIO_SECONDARY_MODULE_FUNCTION indicates Port SEL bits are 10 + * GPIO_TERNARY_MODULE_FUNCTION indicates Port SEL bits are 11 + * If the Port SEL bits are 00, the FUNCTION bits should be ignored + * Please consult device datasheet for more info, under "Input/Output Diagrams" + * + **/ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#ifdef __MSP430FR4133__ + +#define GPIO_PORT_LED1 GPIO_PORT_P1 +#define GPIO_PIN_LED1 GPIO_PIN0 +#define GPIO_PORT_LED2 GPIO_PORT_P4 +#define GPIO_PIN_LED2 GPIO_PIN0 +#define GPIO_PORT_S1 GPIO_PORT_P1 +#define GPIO_PIN_S1 GPIO_PIN2 + +#define GPIO_PORT_ADC7 GPIO_PORT_P1 +#define GPIO_PIN_ADC7 GPIO_PIN7 +#define GPIO_FUNCTION_ADC7 GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_MCLK GPIO_PORT_P1 +#define GPIO_PIN_MCLK GPIO_PIN4 +#define GPIO_FUNCTION_MCLK GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_SMCLK GPIO_PORT_P8 +#define GPIO_PIN_SMCLK GPIO_PIN0 +#define GPIO_FUNCTION_SMCLK GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_ACLK GPIO_PORT_P8 +#define GPIO_PIN_ACLK GPIO_PIN1 +#define GPIO_FUNCTION_ACLK GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_UCA0TXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0TXD GPIO_PIN0 +#define GPIO_FUNCTION_UCA0TXD GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCA0RXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0RXD GPIO_PIN1 +#define GPIO_FUNCTION_UCA0RXD GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_UCB0SCL GPIO_PORT_P5 +#define GPIO_PIN_UCB0SCL GPIO_PIN3 +#define GPIO_FUNCTION_UCB0SCL GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCB0SDA GPIO_PORT_P5 +#define GPIO_PIN_UCB0SDA GPIO_PIN2 +#define GPIO_FUNCTION_UCB0SDA GPIO_PRIMARY_MODULE_FUNCTION + +#endif // __MSP430FR4133__ + +#ifdef __MSP430FR2311__ + +#define GPIO_PORT_LED1 GPIO_PORT_P1 +#define GPIO_PIN_LED1 GPIO_PIN0 +#define GPIO_PORT_LED2 GPIO_PORT_P2 +#define GPIO_PIN_LED2 GPIO_PIN0 +#define GPIO_PORT_S1 GPIO_PORT_P1 +#define GPIO_PIN_S1 GPIO_PIN1 + +#define GPIO_PORT_ADC7 GPIO_PORT_P1 +#define GPIO_PIN_ADC7 GPIO_PIN7 +#define GPIO_FUNCTION_ADC7 GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_MCLK GPIO_PORT_P2 +#define GPIO_PIN_MCLK GPIO_PIN6 +#define GPIO_FUNCTION_MCLK GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_SMCLK GPIO_PORT_P1 +#define GPIO_PIN_SMCLK GPIO_PIN0 +#define GPIO_FUNCTION_SMCLK GPIO_SECONDARY_MODULE_FUNCTION +#define GPIO_PORT_ACLK GPIO_PORT_P1 +#define GPIO_PIN_ACLK GPIO_PIN1 +#define GPIO_FUNCTION_ACLK GPIO_SECONDARY_MODULE_FUNCTION + +#define GPIO_PORT_UCA0TXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0TXD GPIO_PIN7 +#define GPIO_FUNCTION_UCA0TXD GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCA0RXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0RXD GPIO_PIN6 +#define GPIO_FUNCTION_UCA0RXD GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_UCB0SCL GPIO_PORT_P1 +#define GPIO_PIN_UCB0SCL GPIO_PIN3 +#define GPIO_FUNCTION_UCB0SCL GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCB0SDA GPIO_PORT_P1 +#define GPIO_PIN_UCB0SDA GPIO_PIN2 +#define GPIO_FUNCTION_UCB0SDA GPIO_PRIMARY_MODULE_FUNCTION + +#endif // __MSP430FR2311__ + +#ifdef __MSP430FR2433__ + +#define GPIO_PORT_LED1 GPIO_PORT_P1 +#define GPIO_PIN_LED1 GPIO_PIN0 +#define GPIO_PORT_LED2 GPIO_PORT_P1 +#define GPIO_PIN_LED2 GPIO_PIN1 +#define GPIO_PORT_S1 GPIO_PORT_P2 +#define GPIO_PIN_S1 GPIO_PIN3 +#define GPIO_PORT_S2 GPIO_PORT_P2 +#define GPIO_PIN_S2 GPIO_PIN7 + +#define GPIO_PORT_ADC7 GPIO_PORT_P1 +#define GPIO_PIN_ADC7 GPIO_PIN7 +#define GPIO_FUNCTION_ADC7 GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_MCLK GPIO_PORT_P1 +#define GPIO_PIN_MCLK GPIO_PIN3 +#define GPIO_FUNCTION_MCLK GPIO_SECONDARY_MODULE_FUNCTION +#define GPIO_PORT_SMCLK GPIO_PORT_P1 +#define GPIO_PIN_SMCLK GPIO_PIN7 +#define GPIO_FUNCTION_SMCLK GPIO_SECONDARY_MODULE_FUNCTION +#define GPIO_PORT_ACLK GPIO_PORT_P2 +#define GPIO_PIN_ACLK GPIO_PIN2 +#define GPIO_FUNCTION_ACLK GPIO_SECONDARY_MODULE_FUNCTION + +#define GPIO_PORT_UCA0TXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0TXD GPIO_PIN4 +#define GPIO_FUNCTION_UCA0TXD GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCA0RXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0RXD GPIO_PIN5 +#define GPIO_FUNCTION_UCA0RXD GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_UCB0SCL GPIO_PORT_P1 +#define GPIO_PIN_UCB0SCL GPIO_PIN3 +#define GPIO_FUNCTION_UCB0SCL GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCB0SDA GPIO_PORT_P1 +#define GPIO_PIN_UCB0SDA GPIO_PIN2 +#define GPIO_FUNCTION_UCB0SDA GPIO_PRIMARY_MODULE_FUNCTION + +#endif // __MSP430FR2433__ + +#ifdef __MSP430FR2355__ + +#define GPIO_PORT_LED1 GPIO_PORT_P1 +#define GPIO_PIN_LED1 GPIO_PIN0 +#define GPIO_PORT_LED2 GPIO_PORT_P6 +#define GPIO_PIN_LED2 GPIO_PIN6 +#define GPIO_PORT_S1 GPIO_PORT_P4 +#define GPIO_PIN_S1 GPIO_PIN1 +#define GPIO_PORT_S2 GPIO_PORT_P2 +#define GPIO_PIN_S2 GPIO_PIN3 + +#define GPIO_PORT_ADC7 GPIO_PORT_P1 +#define GPIO_PIN_ADC7 GPIO_PIN7 +#define GPIO_FUNCTION_ADC7 GPIO_TERNARY_MODULE_FUNCTION + +#define GPIO_PORT_XIN GPIO_PORT_P2 +#define GPIO_PIN_XIN GPIO_PIN_P7 +#define GPIO_FUNCTION_XIN GPIO_SECONDARY_MODULE_FUNCTION +#define GPIO_PORT_XOUT GPIO_PORT_P2 +#define GPIO_PIN_XOUT GPIO_PIN_P6 +#define GPIO_FUNCTION_XOUT GPIO_SECONDARY_MODULE_FUNCTION + +#define GPIO_PORT_MCLK GPIO_PORT_P3 +#define GPIO_PIN_MCLK GPIO_PIN0 +#define GPIO_FUNCTION_MCLK GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_SMCLK GPIO_PORT_P3 +#define GPIO_PIN_SMCLK GPIO_PIN4 +#define GPIO_FUNCTION_SMCLK GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_ACLK GPIO_PORT_P1 +#define GPIO_PIN_ACLK GPIO_PIN1 +#define GPIO_FUNCTION_ACLK GPIO_SECONDARY_MODULE_FUNCTION + +#define GPIO_PORT_UCA0TXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0TXD GPIO_PIN7 +#define GPIO_FUNCTION_UCA0TXD GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCA0RXD GPIO_PORT_P1 +#define GPIO_PIN_UCA0RXD GPIO_PIN6 +#define GPIO_FUNCTION_UCA0RXD GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_UCB0SCL GPIO_PORT_P1 +#define GPIO_PIN_UCB0SCL GPIO_PIN3 +#define GPIO_FUNCTION_UCB0SCL GPIO_PRIMARY_MODULE_FUNCTION +#define GPIO_PORT_UCB0SDA GPIO_PORT_P1 +#define GPIO_PIN_UCB0SDA GPIO_PIN2 +#define GPIO_FUNCTION_UCB0SDA GPIO_PRIMARY_MODULE_FUNCTION + +#define GPIO_PORT_SACOA0O GPIO_PORT_P1 +#define GPIO_PIN_SACOA0O GPIO_PIN1 +#define GPIO_FUNCTION_SACOA0O GPIO_TERNARY_MODULE_FUNCTION +#define GPIO_PORT_SACOA0N GPIO_PORT_P1 +#define GPIO_PIN_SACOA0N GPIO_PIN2 +#define GPIO_FUNCTION_SACOA0N GPIO_TERNARY_MODULE_FUNCTION +#define GPIO_PORT_SACOA0P GPIO_PORT_P1 +#define GPIO_PIN_SACOA0P GPIO_PIN3 +#define GPIO_FUNCTION_SACOA0P GPIO_TERNARY_MODULE_FUNCTION + +#define GPIO_PORT_SACOA2O GPIO_PORT_P3 +#define GPIO_PIN_SACOA2O GPIO_PIN1 +#define GPIO_FUNCTION_SACOA2O GPIO_TERNARY_MODULE_FUNCTION +#define GPIO_PORT_SACOA2N GPIO_PORT_P3 +#define GPIO_PIN_SACOA2N GPIO_PIN2 +#define GPIO_FUNCTION_SACOA2N GPIO_TERNARY_MODULE_FUNCTION +#define GPIO_PORT_SACOA2P GPIO_PORT_P3 +#define GPIO_PIN_SACOA2P GPIO_PIN3 +#define GPIO_FUNCTION_SACOA2P GPIO_TERNARY_MODULE_FUNCTION + +#define GPIO_PORT_COMP0O GPIO_PORT_P2 +#define GPIO_PIN_COMP0O GPIO_PIN0 +#define GPIO_FUNCTION_COMP0O GPIO_SECONDARY_MODULE_FUNCTION + +#endif // __MSP430FR2355__ + +#endif // __BOARD_H__ + diff --git a/Debug/.clangd/compile_commands.json b/Debug/.clangd/compile_commands.json index 57ae898..73eeb4e 100644 --- a/Debug/.clangd/compile_commands.json +++ b/Debug/.clangd/compile_commands.json @@ -119,11 +119,6 @@ "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", "file" : "/home/frederik/workspace_ccstheia/ESR-11/jsmn/jsmn.c" }, - { - "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", - "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", - "file" : "/home/frederik/workspace_ccstheia/ESR-11/main.c" - }, { "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", @@ -132,11 +127,21 @@ { "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", - "file" : "/home/frederik/workspace_ccstheia/ESR-11/i2c_lcd.c" + "file" : "/home/frederik/workspace_ccstheia/ESR-11/main.c" }, { "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", "file" : "/home/frederik/workspace_ccstheia/ESR-11/morse.c" + }, + { + "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", + "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", + "file" : "/home/frederik/workspace_ccstheia/ESR-11/i2c.c" + }, + { + "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", + "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", + "file" : "/home/frederik/workspace_ccstheia/ESR-11/lcd.c" } ] diff --git a/constants.h b/constants.h index 94dc64a..d6a2b87 100644 --- a/constants.h +++ b/constants.h @@ -1,6 +1,18 @@ +/* ========================================================================== */ +/* constants.h */ +/* ========================================================================== */ /** - * @file constants.h - * @brief Reused constants not included in the std-Headers. + * @file constants.h + * @brief Projektweite Konstanten + * @author Frederik Beimgraben + * @author Minh Dan Cam + * @author Luis Meyer + * @date 02.07.2025 */ +#ifndef CONSTANTS_H +#define CONSTANTS_H + #define NULL 0 + +#endif /* CONSTANTS_H */ diff --git a/i2c.c b/i2c.c new file mode 100644 index 0000000..75d49eb --- /dev/null +++ b/i2c.c @@ -0,0 +1,149 @@ +/* ========================================================================== */ +/* I2C.c */ +/* ========================================================================== */ +/** + * @file I2C.c + * @author wehrberger + * @date 31.05.2025 + * + * @brief Implementierung eines minimalen blockierenden I²C-Master-Treibers. + */ + +#include "i2c.h" +#include "msp430fr2355.h" +#include +#include + +/** Pointer auf das aktuell zu übertragende Byte. */ +static char *packet; + +/** Index des nächsten zu übertragenden Bytes. */ +static unsigned int dataCount; + +/** Anzahl der Bytes in @ref packet. */ +static unsigned int packetLength; + +/** Speicher für das zuletzt vom ISR empfangene Byte. */ +static char dataIn; + +static volatile bool i2cDone = false; + +void I2C_init(void) +{ + // USCI in Reset setzen um Konfiguration zu ermöglichen + UCB0CTLW0 |= UCSWRST; + + // SMCLK wählen und durch 20 teilen → 50 kHz SCL + UCB0CTLW0 |= UCSSEL_3; + UCB0BRW = 20; + + // I²C Master, 7-Bit Adressierung + UCB0CTLW0 |= UCMODE_3 | UCMST; + + // Automatischer STOP nach Byte-Zähler (UCB0TBCNT) erreicht Null + UCB0CTLW1 |= UCASTP_2; + + // Port-Mapping: P1.2 = SDA, P1.3 = SCL + P1SEL1 &= ~(BIT2 | BIT3); + P1SEL0 |= BIT2 | BIT3; + + // Modul aktivieren + UCB0CTLW0 &= ~UCSWRST; + + // Interrupts: RX, TX, STOP, NACK + UCB0IE |= UCRXIE0 | UCTXIE0 | UCSTPIE | UCNACKIE; + + __enable_interrupt(); +} + +void I2C_write(uint8_t slaveAddress, char data[], uint8_t length) +{ + UCB0I2CSA = slaveAddress; + packet = data; + packetLength = length; + dataCount = 0; + + // Master-Transmit-Modus + UCB0CTLW0 |= UCTR; + UCB0TBCNT = length; + + // START generieren, dann schlafen bis STOP + UCB0CTLW0 |= UCTXSTT; + + i2cDone = false; + while (!i2cDone) + { + LPM3; // Warten auf STOP → ISR weckt uns auf + } +} + +char I2C_read_reg(uint8_t slaveAddress, uint8_t registerAddress) +{ + // Registeradresse zuerst senden + char addressBuffer[1] = {registerAddress}; + I2C_write(slaveAddress, addressBuffer, 1); + + // In Empfangsmodus wechseln und 1 Byte anfordern + UCB0CTLW0 &= ~UCTR; + UCB0TBCNT = 1; + + UCB0CTLW0 |= UCTXSTT; // Repeated START + + i2cDone = false; + while (!i2cDone) + { + LPM3; // Warten auf STOP → ISR weckt uns auf + } + + return dataIn; +} + +/* ========================================================================== */ +/* Interrupt Service Routine */ +/* ========================================================================== */ + +/** + * @brief Vereinheitlichte ISR für alle USCI_B0 I²C-Ereignisse. + * + * Nur vier Interrupt-Ursachen werden derzeit behandelt: + * - UCNACKIFG : Kennzeichnet fehlendes ACK (nur Debug-Hook) + * - UCSTPIFG : STOP erkannt → LPM3 verlassen + * - UCRXIFG0 : Ein Byte empfangen + * - UCTXIFG0 : Sendepuffer bereit für nächstes Byte + * + * Alle anderen Ursachen fallen durch zum default. + */ +#pragma vector = EUSCI_B0_VECTOR +__interrupt void EUSCI_B0_I2C_ISR(void) +{ + switch (__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) + { + case USCI_I2C_UCNACKIFG: + // NACK → CPU aufwecken (LPM3 verlassen) + i2cDone = true; + __bic_SR_register_on_exit(LPM3_bits); + break; + + case USCI_I2C_UCSTPIFG: + // STOP → CPU aufwecken (LPM3 verlassen) + i2cDone = true; + __bic_SR_register_on_exit(LPM3_bits); + break; + + case USCI_I2C_UCRXIFG0: + // Empfangenes Byte speichern + dataIn = UCB0RXBUF; + break; + + case USCI_I2C_UCTXIFG0: + // Nächstes Datenbyte senden oder Übertragung beenden + UCB0TXBUF = packet[dataCount++]; + if (dataCount >= packetLength) + dataCount = 0; // Für nächste Transaktion zurücksetzen + break; + + default: + // Unbehandelter Vektor – nichts zu tun + break; + } +} \ No newline at end of file diff --git a/i2c.h b/i2c.h new file mode 100644 index 0000000..ecf741f --- /dev/null +++ b/i2c.h @@ -0,0 +1,44 @@ +/* ========================================================================== */ +/* I2C.h */ +/* ========================================================================== */ +/** + * @file I2C.h + * @author wehrberger + * @date 31.05.2025 + * + * @brief Schnittstelle für einen minimalen blockierenden I²C-Master-Treiber. + */ + +#ifndef I2C_H +#define I2C_H + +#include +#include + +/** + * @brief Initialisiert das I²C-Modul als Master (SMCLK/20 → 50 kHz). + */ +void I2C_init(void); + +/** + * @brief Sendet ein Datenpacket an einen I²C-Slave. + * + * @param slaveAddress 7-Bit I²C-Adresse des Zielgeräts. + * @param data Zeiger auf zu sendende Bytes. + * @param length Anzahl der zu sendenden Bytes. + */ +void I2C_write(uint8_t slaveAddress, char data[], uint8_t length); + +/** + * @brief Liest ein einzelnes Byte aus einem Register eines I²C-Slaves. + * + * Führt zunächst einen Schreibvorgang durch, um die Registeradresse zu senden, + * und liest dann per Repeated START ein Byte zurück. + * + * @param slaveAddress 7-Bit I²C-Adresse des Zielgeräts. + * @param registerAddress Adresse des auszulesenden Registers. + * @return Das gelesene Byte. + */ +char I2C_read_reg(uint8_t slaveAddress, uint8_t registerAddress); + +#endif /* I2C_H */ diff --git a/i2c_lcd.c b/i2c_lcd.c deleted file mode 100644 index 62cce02..0000000 --- a/i2c_lcd.c +++ /dev/null @@ -1,132 +0,0 @@ -#include "i2c_lcd.h" -#include -#include - -/* Adjust to your module’s I²C address (often 0x27 or 0x3F) */ -#define LCD_I2C_ADDR 0x27 - -/* PCF8574 pin ↔ LCD pin mapping (change if your backpack is different) */ -#define P_RS 0x01 /* P0 → RS */ -#define P_RW 0x02 /* P1 → RW */ -#define P_EN 0x04 /* P2 → E */ -#define P_BL 0x08 /* P3 → Backlight */ -#define DATA_MASK 0xF0 - - -/** spin until BUS not busy, or timeoutCycles hits zero */ -static bool waitI2CBusyClear(uint32_t timeoutCycles) -{ - /* keep looping while the BUSY bit remains set */ - while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE) == EUSCI_B_I2C_BUS_BUSY) - && --timeoutCycles) - ; - return (timeoutCycles != 0); -} - -static void i2cWriteByte(uint8_t b) -{ - /* make sure bus is free */ - if (!waitI2CBusyClear(50000)) return; - - /* generate START + send first byte */ - EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, b); - - /* wait until the byte is actually out and bus goes busy→idle */ - if (!waitI2CBusyClear(50000)) return; - - /* STOP to free the bus again */ - EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE); - - /* optional small delay for the expander to settle */ - __delay_cycles(50); -} - -static void pulse(uint8_t data) -{ - i2cWriteByte(data | P_EN); - __delay_cycles(200); - i2cWriteByte(data & ~P_EN); - __delay_cycles(200); -} - -/* send upper or lower nibble with control bits */ -static void write4(uint8_t nibble, uint8_t control) -{ - uint8_t out = (nibble << 4) & DATA_MASK; - out |= control | P_BL; - i2cWriteByte(out); - pulse(out); -} - -static void send(uint8_t value, uint8_t mode) -{ - write4(value >> 4, mode); - write4(value & 0x0F, mode); -} - -/** Commands (mode = 0), data (mode = P_RS) */ -static inline void cmd(uint8_t c) { send(c, 0); } -static inline void data(uint8_t d){ send(d, P_RS); } - -void lcdInit(void) -{ - /* 1) Init the MSP I²C peripheral on B0 (P1.6=SCL, P1.7=SDA) */ - GPIO_setAsPeripheralModuleFunctionInputPin( - GPIO_PORT_P1, - GPIO_PIN6 | GPIO_PIN7, - GPIO_PRIMARY_MODULE_FUNCTION - ); - - EUSCI_B_I2C_initMasterParam i2cCfg = { - .selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK, - .i2cClk = CS_getSMCLK(), - .dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS, - .byteCounterThreshold = 1, - .autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP, - }; - EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &i2cCfg); - EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, LCD_I2C_ADDR); - EUSCI_B_I2C_enable(EUSCI_B0_BASE); - - __delay_cycles(50000); - /* 4-bit init sequence */ - write4(0x03, 0); - __delay_cycles(50000); - write4(0x03, 0); - __delay_cycles(50000); - write4(0x03, 0); - __delay_cycles(50000); - write4(0x02, 0); - __delay_cycles(50000); - - /* function set: 2-line, 5×8 dots */ - cmd(0x28); - /* display off */ - cmd(0x08); - /* clear */ - cmd(0x01); - __delay_cycles(20000); - /* entry mode: cursor moves right */ - cmd(0x06); - /* display on, cursor off, blink off */ - cmd(0x0C); -} - -void lcdPrint(const char *str) -{ - while (*str) { - data((uint8_t)*str++); - } -} - -void lcdPutChar(char c) -{ - data((uint8_t)c); -} - -void lcdSetCursor(uint8_t row, uint8_t col) -{ - /* DDRAM addresses: 0x00 + col for row0, 0x40 + col for row1 */ - uint8_t addr = (row == 0 ? 0x00 : 0x40) + col; - cmd(0x80 | addr); -} diff --git a/i2c_lcd.h b/i2c_lcd.h deleted file mode 100644 index 9414b34..0000000 --- a/i2c_lcd.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef I2C_LCD_H -#define I2C_LCD_H - -#include - -/** Call once at startup to power up the I²C bus and init the LCD controller. */ -void lcdInit(void); - -/** Print a NUL-terminated string at the current cursor position. */ -void lcdPrint(const char *str); - -/** Send a single character. */ -void lcdPutChar(char c); - -/** Move the cursor to (row, col), 0-based. */ -void lcdSetCursor(uint8_t row, uint8_t col); - -#endif // I2C_LCD_H diff --git a/keypad.c b/keypad.c index 326990b..9bcd2bb 100644 --- a/keypad.c +++ b/keypad.c @@ -39,12 +39,12 @@ static const char keys[ROWS][COLS] = { /** Row port and pin definitions */ static const uint8_t rowPort[ROWS] = { GPIO_PORT_P6, GPIO_PORT_P6, GPIO_PORT_P6, GPIO_PORT_P6 }; -static const uint16_t rowPin [ROWS] = { GPIO_PIN1, GPIO_PIN2, GPIO_PIN3, GPIO_PIN4 }; +static const uint16_t rowPin [ROWS] = { GPIO_PIN0, GPIO_PIN1, GPIO_PIN2, GPIO_PIN3 }; /** Column port and pin definitions */ enum { COL0 = 0, COL1, COL2, COL3 }; -static const uint8_t colPort[COLS] = { GPIO_PORT_P3, GPIO_PORT_P2, GPIO_PORT_P3, GPIO_PORT_P3 }; -static const uint16_t colPin [COLS] = { GPIO_PIN7, GPIO_PIN4, GPIO_PIN3, GPIO_PIN2 }; +static const uint8_t colPort[COLS] = { GPIO_PORT_P3, GPIO_PORT_P1, GPIO_PORT_P3, GPIO_PORT_P1 }; +static const uint16_t colPin [COLS] = { GPIO_PIN0, GPIO_PIN1, GPIO_PIN2, GPIO_PIN4 }; /** User callback invoked on confirmed key press */ static KeypadCallback_t keyCallback = NULL; @@ -130,15 +130,23 @@ static void handleColumnInterrupt(uint8_t colIdx) /** * @brief Interrupt Service Routine for PORT2 (handles COL1 on P2.4) */ -#pragma vector=PORT2_VECTOR -__interrupt void PORT2_ISR(void) +#pragma vector=PORT1_VECTOR +__interrupt void PORT1_ISR(void) { - uint16_t status = GPIO_getInterruptStatus(GPIO_PORT_P2, colPin[COL1]); + uint16_t mask = colPin[COL1] | colPin[COL3]; + uint16_t status = GPIO_getInterruptStatus(GPIO_PORT_P1, mask); + if (status & colPin[COL1]) { handleColumnInterrupt(COL1); - GPIO_clearInterrupt(GPIO_PORT_P2, colPin[COL1]); __bic_SR_register_on_exit(LPM0_bits); } + + if (status & colPin[COL3]) { + handleColumnInterrupt(COL3); + __bic_SR_register_on_exit(LPM0_bits); + } + + GPIO_clearInterrupt(GPIO_PORT_P2, colPin[COL1]); } /** @@ -154,14 +162,12 @@ __interrupt void PORT3_ISR(void) handleColumnInterrupt(COL0); __bic_SR_register_on_exit(LPM0_bits); } + if (status & colPin[COL2]) { handleColumnInterrupt(COL2); __bic_SR_register_on_exit(LPM0_bits); } - if (status & colPin[COL3]) { - handleColumnInterrupt(COL3); - __bic_SR_register_on_exit(LPM0_bits); - } + GPIO_clearInterrupt(GPIO_PORT_P3, mask); } diff --git a/lcd.c b/lcd.c new file mode 100644 index 0000000..87897c8 --- /dev/null +++ b/lcd.c @@ -0,0 +1,86 @@ +#include "lcd.h" +#include "i2c.h" /* Ihr I²C-Master-Treiber */ +#include /* für __delay_cycles() */ +#include + +/* --- Interne Helfer: sendet eine 4-Bit-Halbnibble plus Control-Bits --- */ +static void lcd_write_nibble(uint8_t nibble, uint8_t control) +{ + char buf[1]; + + /* High-Nibble in die oberen 4 Bits */ + buf[0] = (nibble << 4) | control | LCD_BACKLIGHT; + /* EN=1 */ + I2C_write(LCD_I2C_ADDR, buf, 1); + buf[0] |= LCD_ENABLE; + I2C_write(LCD_I2C_ADDR, buf, 1); + __delay_cycles(500); /* ca. 50 µs @ 1 MHz */ + /* EN=0 */ + buf[0] &= ~LCD_ENABLE; + I2C_write(LCD_I2C_ADDR, buf, 1); + __delay_cycles(500); +} + +/* Sendet ein volles Byte (2×4-Bit) als Befehl (RS=0) */ +static void lcd_send_cmd(uint8_t cmd) +{ + lcd_write_nibble(cmd >> 4, 0x00); + lcd_write_nibble(cmd & 0x0F, 0x00); +} + +/* Sendet ein volles Byte als Daten (RS=1) */ +static void lcd_send_data(uint8_t data) +{ + lcd_write_nibble(data >> 4, LCD_RS); + lcd_write_nibble(data & 0x0F, LCD_RS); +} + +void lcd_init(void) +{ + /* Wartezeit nach Power-Up */ + __delay_cycles(50000); /* ca. 50 ms */ + + /* Initial­sequenz 8-Bit-Befehle (3×) */ + lcd_write_nibble(0x03, 0x00); + __delay_cycles(20000); + lcd_write_nibble(0x03, 0x00); + __delay_cycles(5000); + lcd_write_nibble(0x03, 0x00); + __delay_cycles(2000); + + /* In 4-Bit-Modus schalten */ + lcd_write_nibble(0x02, 0x00); + __delay_cycles(2000); + + /* Funktion: 4-Bit, 2 Zeilen, 5×8 Punkte */ + lcd_send_cmd(0x28); + /* Display off */ + lcd_send_cmd(0x08); + /* Clear */ + lcd_send_cmd(0x01); + __delay_cycles(2000); + /* Entry mode: Cursor++ */ + lcd_send_cmd(0x06); + /* Display on, Cursor off, Blink off */ + lcd_send_cmd(0x0C); +} + +void lcd_clear(void) +{ + lcd_send_cmd(0x01); + __delay_cycles(2000); +} + +void lcd_set_cursor(uint8_t row, uint8_t col) +{ + uint8_t addr = (row == 0 ? 0x00 : 0x40) + (col & 0x0F); + lcd_send_cmd(0x80 | addr); +} + +void lcd_print(const char *str) +{ + while (*str) + { + lcd_send_data((uint8_t)*str++); + } +} diff --git a/lcd.h b/lcd.h new file mode 100644 index 0000000..f7935ab --- /dev/null +++ b/lcd.h @@ -0,0 +1,35 @@ +#ifndef LCD_I2C_H +#define LCD_I2C_H + +#include + +/* PCF8574 I²C-Expander Adresse */ +#define LCD_I2C_ADDR 0x27 + +/* PCF8574 P-Pins → LCD Control */ +#define LCD_BACKLIGHT 0x08 +#define LCD_ENABLE 0x04 +#define LCD_RW 0x02 +#define LCD_RS 0x01 + +/** + * @brief Initialisiert das LCD (4-Bit-Modus, 2 Zeilen, 5×8 Punkte). + */ +void lcd_init(void); + +/** + * @brief Löscht das Display und setzt Cursor auf Home. + */ +void lcd_clear(void); + +/** + * @brief Setzt den Cursor auf (row, col). Zero-based: row=0..1, col=0..15. + */ +void lcd_set_cursor(uint8_t row, uint8_t col); + +/** + * @brief Schreibt einen C-String ins Display an der aktuellen Cursor-Position. + */ +void lcd_print(const char *str); + +#endif /* LCD_I2C_H */ diff --git a/main.c b/main.c index 437d86f..6d1d450 100755 --- a/main.c +++ b/main.c @@ -15,72 +15,13 @@ #include #include "keypad.h" #include "morse.h" - -/** UART port/pin definitions */ -#define UART_TX_PORT GPIO_PORT_P1 /** UART TX port */ -#define UART_TX_PIN GPIO_PIN2 /** UART TX pin */ -#define UART_RX_PORT GPIO_PORT_P1 /** UART RX port */ -#define UART_RX_PIN GPIO_PIN3 /**< UART RX pin */ - -/** UART baudrate configuration for 9600 @ 1MHz SMCLK */ -#define BAUDRATE_PRESCL 6U /**< UCBR */ -#define BAUDRATE_FIRSTM 8U /**< UCBRF */ -#define BAUDRATE_SECONDM 0U /**< UCBRS */ +#include "i2c.h" +#include "Board.h" /** On-board LED port and pin (used by Morse module) */ #define LED_PORT GPIO_PORT_P1 /**< On-board LED port */ #define LED_PIN GPIO_PIN0 /**< On-board LED pin */ -/** Shared buffer for last key press and ready flag (set in ISR) */ -volatile char g_lastKey = 0; /**< Last key pressed */ -volatile bool g_keyReady = false; /**< Flag indicating key available */ - -/** - * @brief Initialize UART module for console output at 9600 baud. - */ -static void initSerial(void) -{ - EUSCI_A_UART_initParam uartCfg; - - /* Configure TX/RX pins for UART function */ - GPIO_setAsPeripheralModuleFunctionInputPin( - UART_TX_PORT | UART_RX_PORT, - UART_TX_PIN | UART_RX_PIN, - GPIO_PRIMARY_MODULE_FUNCTION - ); - - /* Populate UART configuration structure */ - uartCfg.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK; - uartCfg.clockPrescalar = BAUDRATE_PRESCL; - uartCfg.firstModReg = BAUDRATE_FIRSTM; - uartCfg.secondModReg = BAUDRATE_SECONDM; - uartCfg.parity = EUSCI_A_UART_NO_PARITY; - uartCfg.msborLsbFirst = EUSCI_A_UART_LSB_FIRST; - uartCfg.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT; - uartCfg.uartMode = EUSCI_A_UART_MODE; - uartCfg.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION; - - /* Apply configuration and enable UART */ - EUSCI_A_UART_init(EUSCI_A0_BASE, &uartCfg); - EUSCI_A_UART_enable(EUSCI_A0_BASE); -} - -/** - * @brief Transmit a null-terminated string over UART. - * @param s Pointer to string to send - */ -static void serialPrint(const char *s) -{ - const char *ptr = s; - while (*ptr) { - /* Send next character */ - EUSCI_A_UART_transmitData(EUSCI_A0_BASE, *ptr++); - /* Wait until transmission completes */ - while (EUSCI_A_UART_queryStatusFlags( - EUSCI_A0_BASE, EUSCI_A_UART_BUSY)); - } -} - /** * @brief Keypad callback invoked on key press interrupt. * @param key ASCII character of pressed key @@ -89,11 +30,55 @@ static void serialPrint(const char *s) */ static void myKeyHandler(char key) { - g_lastKey = key; - g_keyReady = true; blinkMorseChar(key); } +void init_timer(void) { + static Timer_B_initUpModeParam param = {0}; + + param.clockSource = TIMER_B_CLOCKSOURCE_SMCLK; + param.clockSourceDivider = TIMER_B_CLOCKSOURCE_DIVIDER_1; + param.timerPeriod = 999; // wenn 1000 Taktimpulse gezählt + // wurden, erfolgt ein Interrupt + // Periodendauer somit 1ms + param.timerInterruptEnable_TBIE = + TIMER_B_TBIE_INTERRUPT_DISABLE; // no interrupt on 0x0000 + param.captureCompareInterruptEnable_CCR0_CCIE = + TIMER_B_CAPTURECOMPARE_INTERRUPT_ENABLE; // interrupt on TRmax + param.timerClear = TIMER_B_DO_CLEAR; + param.startTimer = true; + + // start Timer: + Timer_B_initUpMode(TB0_BASE, ¶m); +} + +void init_i2c(void) { + EUSCI_B_I2C_initMasterParam param = {0}; + + // Configure Pins for I2C + /* + * Select Port 1 + * Set Pin 2, 3 to input with function, (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL). + */ + + GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_UCB0SCL, GPIO_PIN_UCB0SCL, GPIO_FUNCTION_UCB0SCL); + GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_UCB0SDA, GPIO_PIN_UCB0SDA, GPIO_FUNCTION_UCB0SDA); + + param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; + param.i2cClk = CS_getSMCLK(); + param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS; + param.byteCounterThreshold = 1; + param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; + EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m); + + //Specify slave address + EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, 0x27); + //Set in transmit mode + EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); + //Enable I2C Module to start operations + EUSCI_B_I2C_enable(EUSCI_B0_BASE); +} + /** * @brief Main application entry point. * @@ -104,9 +89,6 @@ static void myKeyHandler(char key) */ int main(void) { - char buf[32]; - int len; - /* Stop watchdog and unlock GPIO pins */ WDT_A_hold(WDT_A_BASE); PMM_unlockLPM5(); @@ -115,27 +97,43 @@ int main(void) GPIO_setAsOutputPin(LED_PORT, LED_PIN); GPIO_setOutputLowOnPin(LED_PORT, LED_PIN); - /* Initialize UART console */ - initSerial(); - serialPrint("Keypad + LED test starting...\r\n"); - /* Initialize keypad interrupt driver */ initKeypadInterrupts(myKeyHandler); + init_timer(); + + I2C_init(); /* I²C-Master initialisieren */ + lcd_init(); /* LCD initialisieren */ + + lcd_set_cursor(0, 0); + lcd_print("Hello, world!"); + + lcd_set_cursor(1, 0); + lcd_print("MSP430 + I2C"); + /* Enter low-power mode and wait for key interrupts */ for (;;) { __bis_SR_register(LPM0_bits | GIE); /* Enter LPM0 with interrupts enabled */ __no_operation(); - if (g_keyReady) { - /* Echo key over UART */ - len = sprintf(buf, "Key pressed: %c\r\n", g_lastKey); - (void)len; - serialPrint(buf); - g_keyReady = false; - } + /* Do nothing */ } - - /* Should never reach here */ - return 0; +} + +/** + * @brief Führt eine blockierende Wartezeit aus. + * @param ms Zeit in Millisekunden + */ +void sleep(uint16_t ms) { + while (ms--) { + __bis_SR_register(LPM0_bits + GIE); + __no_operation(); + } +} + +// TimerB0 Interrupt Vector (TBxIV) handler +#pragma vector=TIMER0_B0_VECTOR +__interrupt void TIMER0_B0_ISR(void) +{ + __bic_SR_register_on_exit(LPM0_bits); }