diff --git a/.gitignore b/.gitignore index 1e842b3..ada3d1d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ memmap.map *.pro *.user *.user* +measurement_data +*.jdebug + diff --git a/Makefile b/Makefile index 28c0f14..731a1e1 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ mapfile = memmap ##Custom Files### -CFILES += bme680-driver-fork/bme680.c +CFILES += bme680-driver-fork/bme680.c lcd.c delay.c ################################################################################### @@ -28,10 +28,10 @@ SIZE=arm-none-eabi-size LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles -LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -g -Os +LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -g -O0 CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork -CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g -Os +CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g -O0 #################################################################################### diff --git a/delay.c b/delay.c new file mode 100644 index 0000000..6f3a25f --- /dev/null +++ b/delay.c @@ -0,0 +1,9 @@ +#include + +volatile uint32_t tick; + +void delay_ms(uint32_t ms) +{ + tick = 0; + while (tick < ms); +} diff --git a/lcd.c b/lcd.c new file mode 100644 index 0000000..03d1c5c --- /dev/null +++ b/lcd.c @@ -0,0 +1,215 @@ +#include +#include + +static void lcd_port_clear(void) +{ + LCD_DPORT->ODR &= ~(LCD_E_MASK); + LCD_DPORT->ODR &= ~(LCD_DATA_MASK | LCD_RS_MASK | LCD_E_MASK); +} + +static void lcd_enable(void) +{ + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + LCD_DPORT->ODR |= LCD_E_MASK; + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + LCD_DPORT->ODR &= ~LCD_E_MASK; + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); +} + +static void lcd_out(uint8_t data) +{ + LCD_DPORT->ODR &= ~(LCD_DATA_MASK); + LCD_DPORT->ODR |= (data << LCD_DATA_BIT_OFFSET) & LCD_DATA_MASK; +} + +static void lcd_data(uint8_t data) +{ + lcd_port_clear(); + LCD_DPORT->ODR |= LCD_RS_MASK; + lcd_out((data>>4) & 0xFU); + lcd_enable(); + lcd_out(data & 0xFU); + lcd_enable(); + delay_ms(1); +} + +static void lcd_command(uint8_t data) +{ + lcd_port_clear(); + lcd_out((data>>4) & 0xFU); + lcd_enable(); + lcd_out(data & 0xFU); + lcd_enable(); + delay_ms(1); +} + +#define LCD_DDADR_LINE1 0x00 +#define LCD_DDADR_LINE2 0x40 +#define LCD_DDADR_LINE3 0x10 +#define LCD_DDADR_LINE4 0x50 + +// Clear Display -------------- 0b00000001 +#define LCD_CLEAR_DISPLAY 0x01 + +// Cursor Home ---------------- 0b0000001x +#define LCD_CURSOR_HOME 0x02 + +// Set Entry Mode ------------- 0b000001xx +#define LCD_SET_ENTRY 0x04 + +#define LCD_ENTRY_DECREASE 0x00 +#define LCD_ENTRY_INCREASE 0x02 +#define LCD_ENTRY_NOSHIFT 0x00 +#define LCD_ENTRY_SHIFT 0x01 + +// Set Display ---------------- 0b00001xxx +#define LCD_SET_DISPLAY 0x08 + +#define LCD_DISPLAY_OFF 0x00 +#define LCD_DISPLAY_ON 0x04 +#define LCD_CURSOR_OFF 0x00 +#define LCD_CURSOR_ON 0x02 +#define LCD_BLINKING_OFF 0x00 +#define LCD_BLINKING_ON 0x01 + +// Set Shift ------------------ 0b0001xxxx +#define LCD_SET_SHIFT 0x10 + +#define LCD_CURSOR_MOVE 0x00 +#define LCD_DISPLAY_SHIFT 0x08 +#define LCD_SHIFT_LEFT 0x00 +#define LCD_SHIFT_RIGHT 0x04 + +// Set Function --------------- 0b001xxxxx +#define LCD_SET_FUNCTION 0x20 + +#define LCD_FUNCTION_4BIT 0x00 +#define LCD_FUNCTION_8BIT 0x10 +#define LCD_FUNCTION_1LINE 0x00 +#define LCD_FUNCTION_2LINE 0x08 +#define LCD_FUNCTION_5X7 0x00 +#define LCD_FUNCTION_5X10 0x04 + +#define LCD_SOFT_RESET 0x30 + +// Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM) +#define LCD_SET_CGADR 0x40 + +#define LCD_GC_CHAR0 0 +#define LCD_GC_CHAR1 1 +#define LCD_GC_CHAR2 2 +#define LCD_GC_CHAR3 3 +#define LCD_GC_CHAR4 4 +#define LCD_GC_CHAR5 5 +#define LCD_GC_CHAR6 6 +#define LCD_GC_CHAR7 7 + +// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM) +#define LCD_SET_DDADR 0x80 + +void lcd_clear(void) +{ + lcd_command(LCD_CLEAR_DISPLAY); + delay_ms(3); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Sendet den Befehl: Cursor Home +void lcd_home( void ) +{ + lcd_command(LCD_CURSOR_HOME); + delay_ms(3); +} + +//////////////////////////////////////////////////////////////////////////////// +// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4) + +void lcd_setcursor( uint8_t x, uint8_t y ) +{ + uint8_t data; + + switch (y) + { + case 1: // 1. Zeile + data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x; + break; + + case 2: // 2. Zeile + data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x; + break; + + case 3: // 3. Zeile + data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x; + break; + + case 4: // 4. Zeile + data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x; + break; + + default: + return; // für den Fall einer falschen Zeile + } + + lcd_command(data); +} + +void lcd_string(const char *data) +{ + while(*data != '\0') { + lcd_data((uint8_t)*data++); + } +} + +void lcd_init(void) +{ + int i; + + lcd_port_clear(); + delay_ms(100); + LCD_DPORT->ODR |= (0x3 << LCD_DATA_BIT_OFFSET); + + for (i = 0; i < 3; i++) { + lcd_enable(); + delay_ms(5); + } + + // Set 4 Bit mode + lcd_port_clear(); + LCD_DPORT->ODR |= (0x2< #include "bme680-driver-fork/bme680.h" +#include +#include +#include unsigned int i = 0x12345678; unsigned char c = 2; -#define OUTPUT(pin) (0x01 << (pin * 2)) +#define OUTPUT(pin) (0x01U << (pin * 2)) +#define PULLUP(pin) (0x1U << (pin* 2)) #define ALTFUNC(pin) ((0x2) << (pin * 2)) #define PINMASK(pin) ((0x3) << (pin * 2)) #define SETAF(PORT,PIN,AF) PORT->AFR[(PIN < 8 ? 0 : 1)] |= AF << ((PIN < 8 ? PIN : (PIN - 8)) * 4) +static struct bme680_dev gas_sensor; +static volatile uint8_t backlight_counter; + +static uint8_t spi_transfer(uint8_t out_data) +{ + while(SPI1->SR & SPI_SR_BSY); + SPI1->DR.DR8.DR8_1 = out_data; + __DSB(); + while((SPI1->SR & SPI_SR_BSY) || !(SPI1->SR & SPI_SR_TXE)); + return (uint8_t)(SPI1->DR.DR8.DR8_1 & 0xFF); +} + +static int8_t write_spi(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) +{ + (void)dev_id; + int i; + + GPIOA->ODR &= ~(1U<<4); + + spi_transfer(reg_addr); + + for (i = 0; i < len; i++) + spi_transfer(reg_data[i]); + + GPIOA->ODR |= (1U<<4); + + return 0; +} + + +static int8_t read_spi(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) +{ + (void)dev_id; + int i; + + GPIOA->ODR &= ~(1U<<4); + + spi_transfer(reg_addr); + + for (i = 0; i < len; i++) + reg_data[i] = spi_transfer(0x00); + + GPIOA->ODR |= (1U<<4); + + return 0; +} + +uint32_t gas_res; +int16_t temp = 2000; +struct bme680_field_data data; int main(void) { - RCC->AHBENR |= RCC_AHBENR_GPIOFEN; + char display_data[20]; + + RCC->AHBENR |= RCC_AHBENR_GPIOFEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + + GPIOA->MODER |= OUTPUT(4) | ALTFUNC(5) | ALTFUNC(7) | ALTFUNC(6) | OUTPUT(0) | OUTPUT(1) | OUTPUT(2) | OUTPUT(3) | OUTPUT(9) | OUTPUT(10); + SETAF(GPIOA, 5, 0); + SETAF(GPIOA, 6, 0); + SETAF(GPIOA, 7, 0); GPIOF->MODER |= OUTPUT(0); + GPIOF->PUPDR |= PULLUP(1); GPIOF->ODR |= (1<<0); - SysTick_Config(800000); - while(1) { - i++; - } + /* Configure Systick for 1ms interval */ + SysTick_Config(8000/*00*/); + + + lcd_init(); + + lcd_setcursor(0,4); + lcd_string("Initializing..."); + + GPIOB->MODER |= OUTPUT(1); + GPIOB->ODR &= ~(1<<1); + + + GPIOA->ODR |= (1<<4); + SPI1->CR1 = SPI_CR1_BR_2 | SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI; + SPI1->CR1 |= SPI_CR1_SPE; + + /* You may assign a chip select identifier to be handled later */ + gas_sensor.dev_id = 0; + gas_sensor.intf = BME680_SPI_INTF; + gas_sensor.read = read_spi; + gas_sensor.write = write_spi; + gas_sensor.delay_ms = delay_ms; + /* amb_temp can be set to 25 prior to configuring the gas sensor + * or by performing a few temperature readings without operating the gas sensor. + */ + gas_sensor.amb_temp = 12; + + int8_t rslt = BME680_OK; + rslt = bme680_init(&gas_sensor); + + uint8_t set_required_settings; + + /* Set the temperature, pressure and humidity settings */ + gas_sensor.tph_sett.os_hum = BME680_OS_8X; + gas_sensor.tph_sett.os_pres = BME680_OS_8X; + gas_sensor.tph_sett.os_temp = BME680_OS_8X; + gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_7; + + /* Set the remaining gas sensor settings and link the heating profile */ + gas_sensor.gas_sett.run_gas = BME680_DISABLE_GAS_MEAS; + /* Create a ramp heat waveform in 3 steps */ + gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */ + gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */ + + /* Select the power mode */ + /* Must be set before writing the sensor configuration */ + gas_sensor.power_mode = BME680_FORCED_MODE; + + /* Set the required sensor settings needed */ + set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + + /* Set the desired sensor configuration */ + rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor); + + /* Set the power mode */ + rslt = bme680_set_sensor_mode(&gas_sensor); + + + uint16_t meas_period; + uint8_t meas_gas = 0; + + do { + bme680_get_profile_dur(&meas_period, &gas_sensor); + delay_ms(meas_period); /* Delay till the measurement is ready */ + + if (meas_gas) + gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; + else + gas_sensor.gas_sett.run_gas = BME680_DISABLE_GAS_MEAS; + + + rslt = bme680_get_sensor_data(&data, &gas_sensor); + temp = data.temperature - 300; + gas_sensor.amb_temp = (int8_t)(data.temperature / 100)-3; + /* Avoid using measurements from an unstable heating setup */ + if(data.status & BME680_GASM_VALID_MSK) + gas_res = data.gas_resistance; + + lcd_home(); + display_data[0] = 0; + itoa((int)data.temperature, display_data, 10); + display_data[4] = display_data[3]; + display_data[3] = display_data[2]; + display_data[2] = '.'; + display_data[5] = 0x0; + lcd_string(display_data); + + delay_ms(1000); + + if (gas_sensor.power_mode == BME680_FORCED_MODE) { + bme680_set_sensor_settings(set_required_settings,&gas_sensor); + rslt = bme680_set_sensor_mode(&gas_sensor); + } + } while(1); + +} + +void HardFault_Handler(void) +{ + while(1); } void SysTick_Handler(void) { + static int internal_tick = 0; /* Blink bad air LED */ - GPIOF->ODR ^= (1<<0); + tick++; + internal_tick++; + + if (!(GPIOF->IDR & (1U<<1))) { + backlight_counter = 30; + GPIOB->ODR |= (1U<<1); + } + + if (internal_tick > 200) { + internal_tick = 0; + if (backlight_counter > 0) { + backlight_counter--; + } else if (backlight_counter == 0) { + GPIOB->ODR &= ~(1U<<1); + } + GPIOF->ODR ^= (1<<0); + } }