PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : readChar richtig verwenden



RobotMichi
07.08.2009, 09:30
Hi,

ich weiß, es gibt schon viele Threads zu diesem Thema, trotzdem hab ich per Suchfunktion nicht das gefunden, was ich brauche.
Folgender Programmcode:


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
char x;

while(1)
{
x = readChar();
}
return 0;
}



Allerdings gibt es da einen Fehler beim Compilieren:




> "E:\RP6\Programme\Eigene Programme\Einlesen\\make_all.bat"

E:\RP6\Programme\Eigene Programme\Einlesen>set LANG=C

E:\RP6\Programme\Eigene Programme\Einlesen>make all

-------- begin --------
avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Linking: Einlesen.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=Einlesen.o -I../RP6lib -I../RP6lib/RP6base -I../RP6lib/RP6common -std=gnu99 -MD -MP -MF .dep/Einlesen.elf.d Einlesen.o ../RP6lib/RP6base/RP6RobotBaseLib.o ../RP6lib/RP6common/RP6uart.o --output Einlesen.elf -Wl,-Map=Einlesen.map,--cref -lm
Einlesen.o: In function `main':
E:\RP6\Programme\Eigene Programme\Einlesen/Einlesen.c:10: undefined reference to `readChar'
make: *** [Einlesen.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:01


Weiß jemand warum das nich funktioniert, bzw. was ich ändern muss?

lg
Michi

Dirk
07.08.2009, 12:03
Hallo Michi,

sieh dir mal das Beispiel Example_02_UART_02 an. Da wird gezeigt, wie man Zeichen mit der RP6Lib einlesen kann.

Gruß Dirk

RobotMichi
07.08.2009, 12:38
Hallo Dirk,
ich glaube aber dass in diesem Beispielprogramm ein Fehler ist - auf jeden Fall muss ich die Antwort eingeben, bevor die Frage gestellt wird. Außerdem wird die Funktion readChar nicht verwendet. Trotzdem danke.
Hat jemand eine andere Lösung?

Gruß Michi

Dirk
07.08.2009, 13:12
Außerdem wird die Funktion readChar nicht verwendet.

Bist du sicher?

Such mal die Zeile: receiveBuffer[buffer_pos] = readChar();


Gruß Dirk

RobotMichi
07.08.2009, 17:27
Hi,
Upps :oops: hab nicht erkannt, dass das das selbe ist.

hab es jetzt foldendermaßen gelöst:



#include "RP6RobotBaseLib.h"

void Einlesen(void)
{
char receiveBuffer[1];
receiveBytes(1);
waitUntilReceptionComplete();
copyReceivedBytesToBuffer(&receiveBuffer[0]);
if(receiveBuffer[0] == 'E')
setLEDs(0b111111);
if(receiveBuffer[0] == 'A')
setLEDs(0b000000);
}

int main(void)
{
initRobotBase();



while(1)
{
Einlesen();
}
return 0;
}

, aber wie kann ich mehr als nur ein Zeichen empfangen? das hab ich aus dem Beispielprogramm nicht herauslesen können.

lg

Dirk
07.08.2009, 19:42
wie kann ich mehr als nur ein Zeichen empfangen?
Zeichen z.B. in einer For-Schleife empfangen und in receiveBuffer[buffer_pos] ablegen. buffer_pos bei jedem Durchlauf inkrementieren.

Wenn alle Zeichen empfangen sind: auswerten.

Gruß Dirk

RobotMichi
08.08.2009, 09:41
Hallo Dirk

jetzt sieht es so aus:



#include "RP6RobotBaseLib.h"

void Einlesen(void)
{
int x;

for(x = 0; x < 5; x++)
{
char receiveBuffer[x];
receiveBytes(x);
waitUntilReceptionComplete();
copyReceivedBytesToBuffer(&receiveBuffer[0]);
writeChar(receiveBuffer[0]);
}

}

int main(void)
{
initRobotBase();



while(1)
{
Einlesen();
}
return 0;
}

Aber der RP6 gibt - wenn überhaupt - nur sinnloses Zeug aus. Ist die for-schleife falsch? wenn ja, wie kann ich sie richtigstellen? wenn nein, was ist sonst falsch?

lg
Michi

RobotMichi
08.08.2009, 12:47
Hi,
ich hab jetzt per Suchfunktion doch noch was gefunden:

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=48027

und hab jetzt folgenden Code:



#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
powerON();
char receiveBuffer[5];
while(true)
{
receiveBytes(5);
waitUntilReceptionComplete();
copyReceivedBytesToBuffer(&receiveBuffer[0]);
if(strcmp(receiveBuffer,"Hello"))
{
setLEDs(0b111111);
}
}
}

Das funktioniert ganz gut. aber wenn ich es so mache:




#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
powerON();
char receiveBuffer[5];
while(true)
{
receiveBytes(5);
waitUntilReceptionComplete();
copyReceivedBytesToBuffer(&receiveBuffer[0]);
if(strcmp(receiveBuffer,"Hello"))
{
setLEDs(0b111111);
}
if(strcmp(receiveBuffer,"HiRP6"))
{
setLEDs(0b000000);
}

}
}

dann geht gar nichts mehr. Es lässt sich zwar compilieren, aber er reagiert auf keinerlei Eingaben.

Hat jemand einen Tipp?

lg Michi

SlyD
09.08.2009, 16:48
http://www.cplusplus.com/reference/clibrary/cstring/strcmp/

--> if(strcmp(receiveBuffer,"Hello") == 0)
...
else if ...

Und drauf achten das auch noch \n (newline) mitgesendet werden kann... besser wie im Beispiel immer eine komplette Zeile einlesen.

z.B. mit dieser Funktion hier:



char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1];

uint8_t getInputLine(void)
{
static uint8_t buffer_pos = 0;
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if(receiveBuffer[buffer_pos]=='\n')
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= 32)
{
receiveBuffer[32]='\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}


und dann z.B. so verwenden



if(getInputLine())
{
if(strcmp(receiveBuffer,"Hallo")==0)
{
...


MfG,
SlyD

RobotMichi
09.08.2009, 17:24
Hallo,

ich habe nun auf die Lösung von SlyD zurückgegriffen und das Programm wie folgt gestaltet:


#include "RP6RobotBaseLib.h"

char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1];

uint8_t getInputLine(void)
{
static uint8_t buffer_pos = 0;
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if(receiveBuffer[buffer_pos]=='\n')
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= 32)
{
receiveBuffer[32]='\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}

int main(void)
{
initRobotBase();
powerON();

while(1)
{
if(getInputLine())
{
if(strcmp(receiveBuffer, "Ein")==0)
{
setLEDs(0b111111);
}
if(strcmp(receiveBuffer, "Aus")==0)
{
setLEDs(0b000000);
}
}
}

return 0;
}

Allerdings mag das der Compiler nicht:


> "E:\RP6\Programme\Eigene Programme\Einlesen2\\make_all.bat"

E:\RP6\Programme\Eigene Programme\Einlesen2>set LANG=C

E:\RP6\Programme\Eigene Programme\Einlesen2>make all

-------- begin --------
avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling: Einlesen2.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=Einlesen2.lst -I../RP6lib -I../RP6lib/RP6base -I../RP6lib/RP6common -std=gnu99 -MD -MP -MF .dep/Einlesen2.o.d Einlesen2.c -o Einlesen2.o
Einlesen2.c: In function 'getInputLine':
Einlesen2.c:8: warning: implicit declaration of function 'getBufferLength'
Einlesen2.c:10: warning: implicit declaration of function 'readChar'

Linking: Einlesen2.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=Einlesen2.o -I../RP6lib -I../RP6lib/RP6base -I../RP6lib/RP6common -std=gnu99 -MD -MP -MF .dep/Einlesen2.elf.d Einlesen2.o ../RP6lib/RP6base/RP6RobotBaseLib.o ../RP6lib/RP6common/RP6uart.o --output Einlesen2.elf -Wl,-Map=Einlesen2.map,--cref -lm
Einlesen2.o: In function `getInputLine':
E:\RP6\Programme\Eigene Programme\Einlesen2/Einlesen2.c:8: undefined reference to `getBufferLength'
E:\RP6\Programme\Eigene Programme\Einlesen2/Einlesen2.c:10: undefined reference to `readChar'
make: *** [Einlesen2.elf] Error 1

Er hat also was gegen getBufferLength und readChar.


Was bezwecken eigentlich return 1 und return 2??

Ich würde mich wirklich freuen, wenn ich die "Aufgabe", den RP6 auf Tastatureingaben reagieren zu lassen bald erfolgreich abschließen könnte.

Gruß
Michi

SlyD
09.08.2009, 17:35
0 = keine Daten
1 = Daten empfangen
2 = mehr Daten emfpangen als Platz im Buffer war, Rest abgeschnitten

Ist aber eigentlich nicht wichtig für Deine Anwendung.

Wie sieht denn Dein Makefile aus?
Immer wenn der Compiler irgendwas nicht findet sollte man hier mal genauer draufschauen...
(der obere Teil reicht - bis zu der ab hier nix mehr ändern Markierung ;) )

MfG,
SlyD

RobotMichi
09.08.2009, 17:44
Hi,

mein Makefile:



# Hey Emacs, this is a -*- makefile -*-
################################################## #############################
# RP6 MAKEFILE FOR WinAVR
# Based on WinAVR Sample makefile written by Eric B. Weddington,
# Jörg Wunsch, et al.
#
#
# YOU NEED TO EDIT SOME SMALL THINGS IN THIS FILE IF YOU WANT TO USE
# IT FOR YOUR OWN PROJECTS!
# THESE LINES ARE ALL AT THE TOP OF THIS FILE AND MARKED VERY CLEARLY !
# BETTER DO NOT EDIT ANYTHING ELSE!
#
# To compile everything you can simply type "make all" on a command line in
# this directory or simply use the supplied batch files!
# To remove all the temporary files the compiler has generated you can use
# "make clean"
# See end of this file and "make" user manual for more details!
#
#
# Note: Everything behind a '#' is interpreted as a comment in this file!
#
################################################## #############################




################################################## #############################
# Target file name (without extension).
# This is the name of your main C source file! Do NOT append the ".c"!
# Example: Let's assume your main source file is "RP6Base_MyProgram.c", then
# you would write: TARGET = RP6Base_MyProgram

TARGET = Einlesen2


################################################## #############################



################################################## #############################
# Specify relative path to RP6 library files here.
# This is "../../RP6lib" or "../RP6lib" usually.

RP6_LIB_PATH=../RP6lib
RP6_LIB_PATH_OTHERS= $(RP6_LIB_PATH)/RP6base $(RP6_LIB_PATH)/RP6common

################################################## #############################


#------------------------------------------------
# Main Source file is _automatically_ added here:
SRC = $(TARGET).c
# DO NOT EDIT THIS!


################################################## #############################
# If there is more than one source file, append them here separated by spaces.
# Usually you have to add the Library files here! (ONLY add c files "*.c" here,
# NO header files "*.h"!)
# Don't forget to add relative paths!

SRC += $(RP6_LIB_PATH)/RP6base/RP6RobotBaseLib.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6uart.c
#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CslaveTWI.c
#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI.c

# You can also wrap lines by appending a backslash to the end of the line
# like this:
#SRC += xyz.c \
#abc.c \
#asdf.c
#
################################################## #############################


################################################## #############################
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)

OPT = s

################################################## #############################















# #
#-----------------------------------------------------------------------------#
################################################## #############################
######-------------------------------------------------------------------######
###### DO NOT EDIT ANYTHING BELOW IF YOU DO NOT KNOW WHAT YOU ARE DOING! ######
######-------------------------------------------------------------------######
################################################## #############################
#-----------------------------------------------------------------------------#
# #














# MCU name - atmega32 for RP6 Base and Processor Expansion
MCU = atmega32


# Output format. (can be srec, ihex, binary)
FORMAT = ihex


# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =


# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2


# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = $(RP6_LIB_PATH) $(RP6_LIB_PATH_OTHERS)


# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99




# DO NOT USE THIS FOR RP6 PROJECTS!
#
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
# F_CPU = 8000000

# Place -D or -U options here
CDEFS =
# -DF_CPU=$(F_CPU)UL
# uncommented - caused a compile problem.




# Place -I options here
CINCS =



#---------------- Compiler Options ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)


#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs,--listing-cont-lines=100


#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)


# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)


MATH_LIB = -lm



#---------------- External Memory Options ----------------

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff

EXTMEMOPTS =



#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)



#---------------- Programming Options (avrdude) ----------------

# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com1 # programmer connected to serial device

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep


# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v

AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)



#---------------- Debugging Options ----------------

# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)

# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight

# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr

# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit

# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1

# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242

# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost



#================================================= ===========================


# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rmdir
COPY = cp
WINSHELL = cmd


# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:




# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)

# Define all listing files.
LST = $(SRC:.c=.lst) $(ASRC:.S=.lst)


# Compiler flags to generate dependency files.
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d


# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)





# Default target.
all: begin gccversion sizebefore build sizeafter end

build: elf hex eep lss sym

elf: $(TARGET).elf
hex: $(TARGET).hex
#eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym



# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)

end:
@echo $(MSG_END)
@echo


# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --format=avr --mcu=$(MCU) $(TARGET).elf

sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
2>/dev/null; echo; fi

sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
2>/dev/null; echo; fi



# Display compiler version information.
gccversion :
@$(CC) --version



# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)


# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)

debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)



# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000


coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof


extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof



# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@

#%.eep: %.elf
# @echo
# @echo $(MSG_EEPROM) $@
# -$(OBJCOPY) -j .eeprom --set-section-flags .eeprom=alloc,load \
# --change-section-lma .eeprom=0 -O $(FORMAT) $< $@

# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@

# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@



# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)


# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@


# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@

# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@


# Target: clean project.
clean: begin clean_list end

clean_list :
@echo
@echo $(MSG_CLEANING)

# We want to keep the generated hexfiles:
# $(REMOVE) $(TARGET).hex

# $(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) $(SRC:.c=.i)
$(REMOVE) .dep/*
$(REMOVEDIR) .dep


# Include the dependency files.
include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)


# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config


################################################## #############################
# Based on WinAVR Sample makefile written by Eric B. Weddington,
# J�g Wunsch, et al.
# Released to the Public Domain.
# Please read the "make" user manual!
#
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#
################################################## #############################


MfG
Michi

SlyD
09.08.2009, 18:24
sieht auf den ersten Blick OK aus - Du hast die aktuellsten Beispielprogramme von www.arexx.com/rp6 ?

Die werden korrekt übersetzt? Insbesondere natürlich das UART02 Programm...

> E:\RP6\Programme\Eigene Programme

Sonderzeichen in Pfaden sind bei Softwareentwicklung mit GCC oft böse ;)
Also das Leerzeichen weg machen nur zur Sicherheit.
(meist gehts auch mit aber auf einigen Systemen halt nicht)

MfG,
SlyD

RobotMichi
09.08.2009, 18:32
Hi,

Hast recht, die neuen Beispielprogramme gehen nicht zum compilieren, ich hatte die alten. Am Leerzeichen liegt es aber nicht, denn die anderen Programme in dem Ordner funktionieren. Beim UART2 sieht das so aus:

> "E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02\\make_all.bat"

E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02>set LANG=C

E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02>make all

-------- begin --------
avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling: RP6Base_SerialInterface_02.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_SerialInterface_02.lst -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_SerialInterface_02.o.d RP6Base_SerialInterface_02.c -o RP6Base_SerialInterface_02.o
RP6Base_SerialInterface_02.c: In function 'askAQuestion':
RP6Base_SerialInterface_02.c:142: warning: implicit declaration of function 'clearReceptionBuffer'
RP6Base_SerialInterface_02.c:153: warning: implicit declaration of function 'getBufferLength'
RP6Base_SerialInterface_02.c:155: warning: implicit declaration of function 'readChar'

Compiling: ../../RP6Lib/RP6base/RP6RobotBaseLib.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=../../RP6Lib/RP6base/RP6RobotBaseLib.lst -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6RobotBaseLib.o.d ../../RP6Lib/RP6base/RP6RobotBaseLib.c -o ../../RP6Lib/RP6base/RP6RobotBaseLib.o

Compiling: ../../RP6Lib/RP6common/RP6uart.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=../../RP6Lib/RP6common/RP6uart.lst -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6uart.o.d ../../RP6Lib/RP6common/RP6uart.c -o ../../RP6Lib/RP6common/RP6uart.o

Linking: RP6Base_SerialInterface_02.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_SerialInterface_02.o -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_SerialInterface_02.elf.d RP6Base_SerialInterface_02.o ../../RP6Lib/RP6base/RP6RobotBaseLib.o ../../RP6Lib/RP6common/RP6uart.o --output RP6Base_SerialInterface_02.elf -Wl,-Map=RP6Base_SerialInterface_02.map,--cref -lm
RP6Base_SerialInterface_02.o: In function `askAQuestion':
E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02/RP6Base_SerialInterface_02.c:142: undefined reference to `clearReceptionBuffer'
E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02/RP6Base_SerialInterface_02.c:153: undefined reference to `getBufferLength'
E:\RP6\Programme\Beispielprogramme\RP6BASE_EXAMPLE S\Example_02_UART_02/RP6Base_SerialInterface_02.c:155: undefined reference to `readChar'
make: *** [RP6Base_SerialInterface_02.elf] Error 1


was kann ich den da machen? (ich hab windows Vista Business 32Bit)

lg

SlyD
09.08.2009, 18:43
Das kann eigentlich nicht sein.
Habe ich gerade selbst nochmal ausprobiert das Beispielprogramm funktioniert einwandfrei.

Du hast wirklich die aktuellen Beispielprogramme?
Oben sollte in RP6Base_SerialInterface_02.c folgendes stehen:
" * Version 2.0 --> Updated 10.09.2007 to support new UART Reception routines in the RP6 Libary! "

Falls nicht hast Du eine alte Version der Beispielprogramme wo die beiden Funktionen die der Compiler nicht findet noch nicht vorhanden waren...

MfG,
SlyD

EDIT:
Ah jetzt haste Dein Posting editiert während ich getippt habe ;) Naja... warte kurz.

SlyD
09.08.2009, 18:46
Entpack nochmal das komplette Archiv mit den Beispielprogrammen!
Klappt es dann?

RobotMichi
09.08.2009, 18:49
Aha - jetzt funktionierts zum compilieren, hatte die alte Lib.

ich lad es gleich mal hoch.

lg

RobotMichi
09.08.2009, 18:52
Hallo,

es funktioniert!
wenn du mir noch erklären könntest, wie das funktioniert, wäre es perfekt!

Danke für eure Hilfe!
lg Michi

SlyD
09.08.2009, 19:40
:)

> wenn du mir noch erklären könntest,
> wie das funktioniert, wäre es perfekt!

Was genau verstehst Du denn nicht?
Wenn man Englisch kann, sollte man eigentlich auch direkt den Sinn des Programms verstehen weil das alles genau das macht was da steht ;)

MfG,
SlyD

RobotMichi
10.08.2009, 07:57
Hallo,

das mit dem if(getInputLine()) und if(getBufferLength()) versteh ich nicht ganz, ich meine, das sind ja keine Variablen sondern Funktionen? Wie kann man sie daher auf true oder false überprüfen?
Und warum braucht man bei if(strcmp(receiveBuffer, "Ein")==0) das "==0", was soll denn da 0 sein?

lg
Michi

SlyD
10.08.2009, 08:42
Hallo,

die Funktionen haben einen Rückgabewert (Variable)! Der wird direkt in der if Bedingung ausgewertet. Ist in C egal ob ich nun schreibe
int x = funktion();
if(x) {}

oder
if(funktion()) {}

... aber nur sofern x später nicht mehr gebraucht wird natürlich.




Und warum braucht man bei if(strcmp(receiveBuffer, "Ein")==0) das "==0", was soll denn da 0 sein?


siehe Link weiter oben



http://www.cplusplus.com/reference/clibrary/cstring/strcmp/

Returns an integral value indicating the relationship between the strings:
A zero value indicates that both strings are equal.
A value greater than zero indicates that the first character that does not match has a greater value in str1 than in str2; And a value less than zero indicates the opposite.


0 heisst gleich. Alles andere nicht.

MfG,
SlyD

RobotMichi
10.08.2009, 08:47
Ok, jetzt hab ich das auch verstanden.
Danke nochmal für eure Hilfe.

lg
Michi

vogel0815
30.08.2009, 10:10
Da es das gleiche Thema ist klinke ich ich hier auch mal ein. Zuerst danke SlyD für den HInweis auf dieses Thema.
Nun mal ne Frage.


char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1];

uint8_t getInputLine(void)
{
static uint8_t buffer_pos = 0;
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if(receiveBuffer[buffer_pos]=='\n')
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= 32)
{
receiveBuffer[32]='\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}

Was macht dieser Code denn genau? Ich weiß gern was ich da in einem Programm verwende. ;)
Ist die Variable UART_RECEIVE_BUFFER_SIZE denn schon definiert? Oder muss ich die selber definieren aufgrund der Menge an Zeichen die ich definiere?
Die Funktion oben geht ja den kompletten receiveBuffer Zeichen für Zeichen durch und jagt readChar() darüber. Was macht readChar() den mit den Zeichen?
Dann, ein Abbruchkriterium ist ja wenn als Zeichen '\n' gefunden wird. Ich vermute das kann ich auch einfach durch andere "Zeilenendzeichen" ersetzen? Also z.B. mit '\r'.
Was bringt es eigentlich wenn man ein Zeichen mit '\0' überschreibt?

Meine letzte aber wohl komischste Frage überhaupt, wo befinden sich denn nach der Funktion überhaupt die eingelesenen Zeichen?
Wenn ich die Funktion ja aufrufe liefert die mir nur je nach Zustand ein 0, eine 1 oder eine 2 zurück. Oder seh ich das grad richtig das am Ende alle Zeichen der Reihe nach in receiveBuffer[0..Ende] stehen?

EDIT: Nachdem ich das ganze geschrieben hab un noch ein paar mal drüber nachgedacht hab glaub ich das ich das doch verstanden hab. Narf immer das gleiche ^^


EDIT2: Aber eine Frage habe ich immernoch, wie kann ich es denn realisieren dass ich in einer Zeile z.B. "050 050" übertragen kann und dann im RP6 das in zwei Variable mit jeweils 50 umsetze?
Ich will da nämlich Geschwindigkeitswerte übertragen und eben auf für Kurven z.B. "075 125" oder sowas
Kann ich denn von dieser Variable vom Typ Char einfach die ersten drei Zeichen irgendwie rausnehmen und in eine integer schreiben? Weiß da einer wie man sowas macht?


EDIT3: Habe nun rausgefunden das sich das ein char mittels
int i = atoi (char) in etwa umwandeln lässt.
Werde das daheim dann mal testen. :-)

vogel0815
03.09.2009, 20:14
Hmm nun probier ich da schon eine Weile rum, aber irgendwie funktioniert da irgendwas nicht so wie es soll.
Mein Quelltext sieht derzeit so aus.


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"

void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}

char receiveBuffer[8];
char dir_char[1], speed_1_char[3], speed_2_char[3];

void getInputLine(void)
{
clearLCD();
writeStringLCD("getinputline");
static uint8_t buffer_pos = 0;
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if((receiveBuffer[buffer_pos]=='\n')||(receiveBuffer[buffer_pos]=='\r'))
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;
}
else if(buffer_pos >= 8)
{
receiveBuffer[7]='\0';
buffer_pos = 0;
}
buffer_pos++;
}
}


uint8_t speed_1=0;
uint8_t speed_2=0;
uint8_t direction=0;
uint8_t speed_max=200;


int main(void)
{
initRP6Control();
initLCD();
mSleep(500);

I2CTWI_initMaster(100);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);


setLEDs(0);
mSleep(500);

sound(180,80,25);
sound(220,80,0);


while(1)
{
task_checkINT0();
task_I2CTWI();

clearLCD();
writeStringLCD("fertig");
mSleep(500);
clearLCD();
//uerbtragung in der form 1050080
//1. erste stelle richtung
//richtung vorwaerts -> 1
//richtung rueckwaerts -> 2
//drehen links -> 3
//drehen rechts -> 4
//2.-4. stelle speed_1 (linke kette)
//5.-7. stelle speed_2 (rechte kette)

getInputLine();

direction=atoi(dir_char);
speed_1=atoi(speed_1_char);
speed_2=atoi(speed_2_char);

writeStringLCD("d:");
writeIntegerLCD(direction, 10);
writeStringLCD("s1:");
writeIntegerLCD(speed_1, 10);
writeStringLCD("s2:");
writeIntegerLCD(speed_2, 10);



}
return 0;
}


Aber aus einem mir unerfindlichen Grund kommt er immer nur bis zur LCD Anzeige "fertig".

Anfangs hatte ich das getInputLine(); mal vor der LCD-Ausgabe für "Fertig", da ist er erst in diese funktion gegangen und hat mir den text "getinputline" angezeigt und danach "fertig". Doch jetzt wo ich die Reihenfolge der zwei getauscht habe macht er das auch nicht mehr.


Ich wär für jeden Hinweis dankbar.
Grüße vogel

Dirk
04.09.2009, 21:17
Hallo vogel0815,

schau dir noch mal genau das Beispiel von RobotMichi vom 9.8.09 an! Da wird gezeigt, wie getInputLine() verwendet wird.

Zu einer deiner früheren Fragen:

Was bringt es eigentlich wenn man ein Zeichen mit '\0' überschreibt?
Ein bestimmtes "Zeichen" überschreibt man häufiger mit 0, und zwar das Stringende. Wenn man Zeichen in receiveBuffer schreibt, dann kann man den ganzen Buffer als String auslesen, wenn im letzten Byte eine 0 ist, also der String Null-terminiert ist.

Gruß Dirk

vogel0815
05.09.2009, 13:31
Also ich hab das nun mal ein bissl umgeändert und probier das wie folgt:


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"

void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}


char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1];
uint8_t getInputLine(void)
{
clearLCD();
writeStringLCD("getinput");
mSleep(500);
static uint8_t buffer_pos = 0;
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if(receiveBuffer[buffer_pos]=='\r')
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= 32)
{
receiveBuffer[32]='\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}

uint8_t setonce2=false, setonce3=false;
/*
LCD Texte einmalig setzen bei betreten des Zustandes
LCD-Display 2*16 Zeichen
*/
void LCDText(uint8_t nmbr)
{
switch (nmbr)
{
case 1:
showScreenLCD("Starting up! One", "moment please.");
break;
case 2:
setonce3=false;
if (!setonce2)
{
setonce2=true;
showScreenLCD("################","################");
}
break;
case 3:
setonce2=false;
if (!setonce3)
{
setonce3=true;
showScreenLCD("################","################");
}
break;
}
}


uint8_t speed_max=200;


int main(void)
{
initRP6Control();
initLCD();
mSleep(500);

I2CTWI_initMaster(100);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

LCDText(1);
setLEDs(0);
mSleep(500);

sound(180,80,25);
sound(220,80,0);


while(1)
{
task_checkINT0();
task_I2CTWI();

clearLCD();
writeStringLCD("fertig");
mSleep(500);


if(getInputLine())
{
if(strcmp(receiveBuffer, "Ein")==0)
{
clearLCD();
writeStringLCD("ein");
mSleep(500);
}
if(strcmp(receiveBuffer, "Aus")==0)
{
clearLCD();
writeStringLCD("aus");
mSleep(500);
}
}
}
return 0;
}


aber irgendwie klappt da gar nix.
Der RP6 rennt zwar sein Programm durch und zeigt mir auch die Textausgaben "fertig" und "getinputline" an so wie er soll, aber die ankommenden daten wertet er irgendwie nicht aus.

Die Daten schicke ich mittels eines bluetooth moduls das ich auch schon mal als schleife ans notebook gehängt hab, das klappt so wie es soll.
Hab auch die baudrate im rp6 auf 19200 geändert wie das modul derzeit eingestellt ist.
Aber selbst wenn ich das eigene UART interface benutze, und das dann auch mit der normalen baudrate im RP6 funktioniert das nicht.
ich hab das gefühl der hat irgendein problem mit dem datenempfang.

SlyD
05.09.2009, 13:47
Ein writeString(receiveBuffer) als Debug Ausgabe könnte schon helfen um zu sehen WAS denn genau ankommt. Oder noch besser in einer Schleife die ASCII Codes ausgeben lassen (writeInteger(receiveBuffer[i],DEC))

Immer wenn irgendwas nicht funktioniert solltest Du versuchen die Variablen Inhalte auszugeben. Dafür ist die serielle Schnittstelle ja auch da ;)


Der Grund warum es nicht funktioniert liegt wohl hier:
mSleep(500);
(kommt an zwei Stellen vor!)

Damit funktioniert das task System nicht mehr!
mSleep darfst Du nur für kurze Pausen <20ms verwenden wenn Du task_ABCD Funktionen in der Hauptschleife aufrufst.
getInputline ist im prinzip auch so eine Art von Task Funktion und muss MEHRFACH aufgerufen werden damit es funktioniert.
Die Funktion verarbeitet jedes ankommende Zeichen EINZELN damit das nebenläufig verwendet werden kann und nichts anderes blockiert.

Wenn man das anders haben möchte muss man das if gegen while austauschen...

Die bessere Lösung ist aber von mSleep komplett auf die Stopwatches (Software Timer) umzusteigen.

MfG,
SlyD

vogel0815
06.09.2009, 15:09
Also ich hab da heute mal weiter gemacht, und nu funktioniert das so wie es soll :-)

Mein Code sieht nun so aus.

#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"

void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}


char receiveBuffer[8]; // our reception buffer is one byte larger
// than the data we want to receive, because
// we also need to receive the "Newline" character!
void getInputLine(void)
{
clearReceptionBuffer(); // Make sure reception Buffer is empty and no junk data
// is left in it.

uint8_t buffer_pos = 0;
while(true) // Loop until we received one line of Data!
{
if(getBufferLength()) // Check if we still have data (means getBufferLength()
{ // is not zero)
receiveBuffer[buffer_pos] = readChar(); // get next character from reception buffer
if(receiveBuffer[buffer_pos]=='\n') // End of line detected!
{
receiveBuffer[buffer_pos]='\0'; // Terminate String with a 0, so other routines.
buffer_pos = 0; // can determine where it ends!
// We also overwrite the Newline character here.
break; // We are done and can leave reception loop!
}
else if(buffer_pos >= 7) // IMPORTANT: We can not receive more
{ // characters than "charsToReceive" because
// our buffer wouldn't be large enough!
receiveBuffer[7]='\0'; // So if we receive more characters, we just
// stop reception and terminate the String.
writeString_P("\n\nZu viele Zeichen eingegeben FEHLER!\n");
break; // We are done and can leave reception loop!
}
buffer_pos++;

}
}
}

/*
char-array von receivebuffer in seine einzelteile zerlegen und ebenfalls in einem char-array
sowie diese neuen char-arrays umwandeln in integerzahlen
*/
static int speed_1=0;
static int speed_2=0;
static int direction=0;
char dir_char[2];
char speed_1_char[4];
char speed_2_char[4];

void splitbuffer(void)
{
dir_char[0]=0;
dir_char[0]=receiveBuffer[0];
direction=atoi(dir_char);
int i=0;
while (i<3)
{
speed_1_char[i]=receiveBuffer[i+1];
speed_2_char[i]=receiveBuffer[i+4];
i++;
}

speed_1=atoi(speed_1_char);
speed_2=atoi(speed_2_char);

}


int speed_max=200;

int main(void)
{
initRP6Control();
initLCD();

I2CTWI_initMaster(100);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

setLEDs(0);

sound(180,80,25);
sound(220,80,0);


while(1)
{
task_checkINT0();
task_I2CTWI();
writeString_P("\nget input\n");
getInputLine();
splitbuffer();

if(speed_1>200)
{
speed_1=speed_max;
}
if(speed_2>200)
{
speed_2=speed_max;
}
switch (direction)
{
case 1: //vorwaerts fahren
writeInteger(1,DEC);
writeChar('\n');
changeDirection(FWD); //richtung wechseln nach forward
moveAtSpeed(speed_1, speed_2);
break;

case 2: //rueckwaerts fahren
writeInteger(2,DEC);
writeChar('\n');
changeDirection(BWD); //richtung wechseln nach backward
moveAtSpeed(speed_1, speed_2);
break;

case 3: //links drehen
writeInteger(3,DEC);
writeChar('\n');
changeDirection(FWD); //forward sonst leichte verwirrung
moveAtSpeed(speed_1, speed_2);
break;

case 4: //rechts drehen
writeInteger(4,DEC);
writeChar('\n');
changeDirection(FWD);
moveAtSpeed(speed_1, speed_2);
break;

default:
writeInteger(5,DEC);
writeChar('\n');
moveAtSpeed(0,0);
}
}
return 0;
}


Die Steuerung vom RP6 über Bluetooth und Labview, wie es später auch geschehen soll funktioniert nun auch einwandfrei. :-)

Nun muss ich nur noch am RP6 mal die Encoder richtig einstellen, aber da macht mir derzeit der RP6Loader zicken. Irgendwie ist der grad verdammt lahm was die Textausgabe dort angeht. Der hängt ewig hinterher. Aber deswegen hab ich mal im Arexx forum die frage gestellt. :-)


Nur eine Sache kapier ich nicht. In meinem Quellcode oben teile ich den 7-stelligen Inhalt des receivebuffers auf auf 3 einzelne char-arrays.
das erste zeichen in das erste array, und dann je 3 zeichen in die anderen arrays. Im Code oben habe ich diese neuen Arrays aber jeweils ein zeichen größer machen müssen als das was da rein kommt. Also statt einem Zeichen hab ich das 2 Zeichen groß machen müssen, und anstelle von 3 Zeichen 4 Zeichen. Sonst hat das einfach nicht funktioniert. Hat irgendjemand eine idee warum das so ist? ist ja schließlich schon etwas komisch.

Ansonste Grüße und danke für eure Hilfe.

SlyD
06.09.2009, 15:39
> Nur eine Sache kapier ich nicht.

receiveBuffer[buffer_pos]='\0';
// Terminate String with a 0, so other routines.
// can determine where it ends!


;)

Und wenn Du atoi verwendest musst Du die Arrays auch 0 terminieren!