Liste der Anhänge anzeigen (Anzahl: 3)
Anhang 29147
Anhang 29148
Anhang 29150
Seltsamerweise läst mich das Forum keine cpp Dateien hochladen. Es benennt auch meine i2c.c Datei nach i.c um...
Die Funktion handle_irq() wird aus dem IRQ Handler aufgerufen. Ganz unten in "i.c" bzw. i2c.cpp.
Mein Makefile sieht so aus:
Code:
############################################################
# Projekteinstellungen
############################################################
# MCU
MCU=atmega328p
F_CPU=16000000
LFUSE=0xde
HFUSE=0xd7
EFUSE=0x01
# Die Sources
SOURCES = util.cpp eeprom.cpp i2c.cpp \
menu.cpp main.cpp \
timer1.cpp scheduler.cpp \
rtc.cpp display.cpp adc.cpp relay.cpp storage.cpp r-to-t.cpp \
core.cpp
# temporary deactivated parser.cpp rs232.cpp
# Die Zieldateien
ELF = heat.elf
HEX = heat.hex
MAP = heat.map
############################################################
# Compiler Flags. Muss vermutlich nicht angepasst werden
############################################################
CFLAGS=-g -DF_CPU=$(F_CPU) -Wall -Os --std=c++11 -mcall-prologues
LFLAGS=-lprintf_flt
############################################################
# Die Toolchain. Muss vermutlich nicht angepasst werden
# Die AVRDUDE Zeile muss an den Programmer und
# die Ziel CPU angepasst werden
############################################################
AVRDUDE=avrdude -p m328p -c avrispmkii -P usb
CC=avr-g++
RM=rm -f
OBJCOPY=avr-objcopy
AVRSIZE=avr-size
OBJDUMP=avr-objdump
############################################################
# Ab hier muss nichts mehr angepasst werden
############################################################
# OBJ = Sources mit ersetzter Dateiendung
OBJ=$(SOURCES:%.cpp=%.o)
all: hex
hex: elf
$(OBJCOPY) -R .eeprom -O ihex $(ELF) $(HEX)
elf: $(OBJ)
$(CC) -mmcu=$(MCU) $(CFLAGS) $(LFLAGS) -o $(ELF) -Wl,-Map,$(MAP) -Wl,-u,vfprintf $(OBJ)
%.o: %.cpp
$(CC) -mmcu=$(MCU) $(CFLAGS) -c $<
.phony: flash
flash: hex
$(AVRDUDE) -e -U flash:w:$(HEX)
# Ziele ohne Abhängigkeiten
clean:
$(RM) $(OBJ) $(ELF) $(HEX) $(MAP)
readfuse:
$(AVRDUDE) lfuse:r:-:i -v
writefuse:
$(AVRDUDE) -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
size: $(ELF)
$(AVRSIZE) -B $(ELF)
dump:
$(OBJDUMP) -d -S --demangle $(ELF)
read-eeprom:
$(AVRDUDE) -U eeprom:r:eeprom.bin:i
- - - Aktualisiert - - -
Benutzen tu ich das ganze so:
Code:
#include "project.h"
#include "i2c.h"
extern avr::project sys;
extern avr::i2c twi;
extern bool check_twi(unsigned char& state);
// -----------------------------------------------------
// relay
// -----------------------------------------------------
namespace relay {
unsigned char state = 0;
bool
handle()
{
switch (state)
{
case 0:
g_buffer[0] = ~sys.relay_state;
twi.write_to_slave(avr::relay_address, g_buffer, 1);
state++;
return false;
// check that twi transmitted successful
case 1:
return check_twi(state);
case 2:
state = 0;
return true;
// 100: Error
case 100:
// reenter. try again
state = 0;
break;
default:
break;
}
return true;
}
}; // namespace relay
Code:
// -----------------------------------------------------
// helper functions for statemachines
// -----------------------------------------------------
bool
check_twi(unsigned char& state)
{
if (twi.is_busy())
return false; // not yet done
else if (twi.is_error() != avr::i2c::no_error)
{
state = 100; // we have an error
}
else
{
// everything ok
state++;
}
return true;
}
- - - Aktualisiert - - -
Der Scheduler ruft das ganze dann so auf:
Code:
// -----------------------------------------------------
// scheduler
// -----------------------------------------------------
namespace scheduler {
unsigned char state_i2c = 0;
unsigned char state_spi = 0;
unsigned char state_uart = 0;
void
i2c()
{
bool next_step = true;
switch (state_i2c)
{
case 0:
next_step = rtc::handle();
break;
case 1:
next_step = storage::handle();
break;
case 2:
next_step = menu::handle();
break;
case 3:
next_step = relay::handle();
break;
case 4:
next_step = display::handle();
break;
}
if (next_step) state_i2c += 1;;
if (state_i2c >= 5) state_i2c = 0;
}
}; // namespace scheduler
Der Scheduler selbst hängt wieder im timer1 IRQ.
Code:
/*
Copyright (c) 2014 "Georg Gast <georg@schorsch-tech.de>"
This file is part of thermocontrol.
thermocontrol is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <avr/interrupt.h>
#include "units.h"
#include "timer1.h"
#include "project.h"
#include "scheduler.h"
extern avr::project sys;
// we count 250 cycles until TOV1 (normal mode)
static const int start_tcnt = 65536-250;
namespace avr {
namespace timer1 {
void
init()
{
// start timer with 1 ms interval
// normal mode
TCCR1A = 0;
TCCR1B = (1 << CS11) | (1 << CS10); // prescale factor 64
TIMSK1 |= (1 << TOIE1);
TCNT1 = start_tcnt;
}
} // namespace timer1
} // namespace avr
// -----------------------------------------------------
// IRQ Handler are outside of our namespace
// -----------------------------------------------------
ISR(TIMER1_OVF_vect)
{
/*
Timer 1, Normal mode, runs up and
and then TOV1 irq when 0xffff to 0x0000
(Timer Counter Overflow 1) irq
*/
// to measure time, set let when we are in here
TCNT1 = start_tcnt;
sys.elapsed_time++;
scheduler::i2c();
scheduler::spi();
scheduler::uart();
}