Hallo,
Ich habe ein IR-Sender gebaut, der universell einsetzbar sein soll. Das
Programm für den uC soll erstmal nur sehr banal funktionieren.
Eigentlich ist der uC im Moment TOTAL überflüssig dennoch soll der
Sender über den ATmega16 laufen...
Das Programm soll so funktionieren:
Initialisierung
LOGIN: IR-Ausgang ausschalten dass die Dioden NIX senden und per USART
auf ein "connect" vom Rechner warten... Kommen nun Daten vom Rechner
werden sie mit dem im uC gespeicherten "pw" verglichen. Ist das pw
falsch wird weiter auf Daten gewartet bis dass korrekte pw kommt. Ist
das pw korrekt, soll der uC per USART eine Antwort an den Rechner
schicken und in den SENDE Modus wechseln, eine Schleife die alle Daten
(per USART) entgegen nimmt, mit dem "disconnect" vergleicht und sie an
den IR-Ausgang weiterleitet.
Bei "disconnect" werden die Daten natürlich NICHT an den IR-Ausgang
gesendet, und das Programm springt wieder in die LOGIN-Schleife.
Ich habe mein bisheriges Programm angehängt weil ein Kollege auf der
Arbeit gemeint "das funktioniert so nicht". Er wollte mir jedoch nicht
sagen warum und weshalb...
Ich weiss dass die Initialisierung noch nicht komplett ist, daran liegt
es jedoch nicht...
Er hat gemeint "es liegt am Programm selbst..."
Ich habe den ATmega bisher immer nur per Assembler programmiert und
wollte nun mit Hilfe von dem AVR-GCC Tutorial auf dieser seite mit C
anfangen... Programmieren kann ich, also Programm Struktur usw sind kein
Problem, da ich schon viel in VB programmiert habe, nur mit C kann ich
mich iergendwie nicht so anfreunden.
Kann mir da villeicht einer ein wenig unter die Arme greifen?
Dies kann gerne auch per ICQ, MSN oder sonst was sein...
ABER bitte verkneift euch die üblichen "Lies das Tutorial" oder "Google
weiss alles" Sprüche. Ich hab das Programm mit Hilfe des Tutorials und
mit Hilfe des ATmega16 Datenblattes (USART: init. senden und empfangen)
geschrieben, Ich kapier das nur alles nicht so ganz da in Tuorials usw
immer nur Teilprogramme sind die gewöhnlich nicht auf das zutreffen, das
ich brauche, und ich somit erstmal verstehen muss was das Teilprogramm
macht, das da geschrieben steht...
Tja. Was macht man da ? Es liegt eigentlich meist am Programm selbst.
Fehler suchen. Einen noch nicht benutzten Pin als Debugpin definieren
und dort jeweils einen Puls ausgeben wenn das Programm dort
veorbeikommt. Aufm Oszilloskop kann man so mitverfolgen wo das Programm
was macht.
1. Fehler:
Der Compiler dürfte schon mal meckern, weil die Funktionen USART_init
und LOGIN hinter der main() stehen und keine Funktionsprototypen
angelegt wurden.
3. Fehler:
Die Device-spezifischen Header (in diesem Fall iom16.h) werden nicht
direkt eingebunden, sondern es wird immer nur die io.h mit #include
eingebaut. Die Einstellung des verwendeten µC ist im Makefile bzw. im
AVRStudio unter "Project | Configuration Options" vorzunehmen.
4. Fehler:
In der Funktion LOGIN() rufst du die Funktion USART_empfangen() auf,
welche...
a) ein Byte (char) an die aufrufende Funktion zurückgeben würde,
dieses zurückgegebene Zeichen wird im Aufruf aber keiner Variablen
zugewiesen
b) nur ein Byte zurückgibt (ein Passwort besteht meines Wissens aber
in der Regel aus mehreren Zeichen !)
Zacc wrote:
> Tja. Was macht man da ? Es liegt eigentlich meist am Programm selbst.> Fehler suchen. Einen noch nicht benutzten Pin als Debugpin definieren> und dort jeweils einen Puls ausgeben wenn das Programm dort> veorbeikommt. Aufm Oszilloskop kann man so mitverfolgen wo das Programm> was macht.
Das war jetzt alles viel aufeinmal... Oszillo hab ich keins...
Zum Rest:
4. Fehler: sowas hat er erwähnt, jedoch wollte es sich nicht dazu
äussern was ich ändern kann...
3. Fehler: Hab ich aus BSP. Programmen vom Datenblatt, und weiss auch
nicht we oder was ich da ändern soll...
2. Fehler: Ja klar fehlen da Programmteile, jedoch sind das
Programmteile wo ich nicht weiss wie ich sie in C lösen soll...
1. Fehler: kA was du damit meinst, LOGIN() kommt von mir und das mit
USART_init kommt wieder aus dem Datenblatt...
Roy Thinnes wrote:
> 1. Fehler: kA was du damit meinst, LOGIN() kommt von mir und das mit> USART_init kommt wieder aus dem Datenblatt...
Eine Funktion muss bei ihrem Aufruf im Programm dem Compiler bekannt
sein. LOGIN ist aber beim Aufruf nicht bekannt, da sie erst weiter
unten definiert wird und eben kein Prototyp (Deklaration) vorhanden ist.
Also entweder einen Prototypen schreiben oder die Definitionen der
Funktionen vor main machen.
Roy Thinnes wrote:
> 3. Fehler: Hab ich aus BSP. Programmen vom Datenblatt, und weiss auch> nicht we oder was ich da ändern soll...
Hab ich doch geschrieben: Nicht avr/iom16.h einbinden, sondern avr/io.h
und den Controllertyp entsprechend einstellen!
Roy Thinnes wrote:
> Fehler 1: Ich habe nun einfach main hinter ALLE anderen Programmteile> gesetzt somit dürfte das ja kein Problem mehr sein...
Doch. Du rufst in LOGIN die Funktion START auf, die an der Stelle
ebenfalls noch nicht bekannt ist...
> Fehler 3: Ich habe nun>
1
#include<avr/io.h>
> anstelle von>
1
#include<avr/iom16.h>
> eingebunden, und in Project --> Configuration Options war eh schon> atmega16 eingestellt. (bei General, ich hoffe ich muss da sonst nix> ändern)
Du solltest auch die Taktfrequenz dort angeben, auch wenn es derzeit
noch irrelevant ist, es gibt nämlich einige Funktionen, die diesen Wert
brauchen. Abgesehen davon kannst Du Dir die Angabe der Frequenz im
Programm sparen, wenn Du anstelle von FOSC mit F_CPU rechnest. Das ist
der Wert, der da bei der Konfiguration angegeben wird.
Und wenn Du schon den Wert im Programm angibst, dann schreib besser
16000000UL, damit es bei Berechnungen damit keine Probleme gibt und der
Compiler weiß, dass es sich um einen long-Wert handelt.
Abgesehen davon sollte bei den Configuration Options noch ein
Optimierungslevel angegeben werden (sinnvoll ist meist
Codegrößenoptimierung, also -Os).
-Os war schon eingestellt und UL hab ich im Code angehängt...
Ich hab auch jetzt START vor LOGIN gemacht... Hab den Code nun wieder
mal angehängt...
EDIT: hmm iergendwie nimmt ers nicht, also aufm Rechner ist alles ok nur
hochladen klappt hier nicht...
Hab hier mal den Code wieder angehängt bekomme beim kompilieren folgende
Fehler:
55: lvalue required as left operant of assignement
64: lvalue required as left operant of assignement
Dann sind da noch mehrere Warnings aber solange es keine errors sind ;)
Kann mir wer verraten was da falsch ist resp. ob das so über haupt
funktionieren kann?? Auchnoch würde ich gerne wissen welche max.
Baudrate ich verwenden kann/soll. Das Teil soll später ein 38kHz Signal
vom Rechner an die IR-LEDs schicken... (Wenn das überhaupt möglich
ist...)
MfG
Roy Thinnes wrote:
> Hab hier mal den Code wieder angehängt bekomme beim kompilieren folgende> Fehler:>> 55: lvalue required as left operant of assignement> 64: lvalue required as left operant of assignement>> Dann sind da noch mehrere Warnings aber solange es keine errors sind ;)>> Kann mir wer verraten was da falsch ist resp. ob das so über haupt> funktionieren kann?? Auchnoch würde ich gerne wissen welche max.> Baudrate ich verwenden kann/soll. Das Teil soll später ein 38kHz Signal> vom Rechner an die IR-LEDs schicken... (Wenn das überhaupt möglich> ist...)>> MfG
PORTC0 = UDR; geht nicht da PORTC0 definiert ist als PC0 und PC0 ist
definiert als 0. Du versuchst also der Zahl 0 einen Wert zuzuweisen.
hmm ???
Also Pin 0 vom Port C soll UDR sein, resp. ich will da die Daten die per
USART reinkommen ausgeben... Aber was du da jetzt meinst versteh ich
nicht...
Du kannst auf einen Portpin nicht auf diese Weise einzeln zugreifen! Das
Portregister heißt PORTC, und PORTC0 gibt es nicht. Und Du kannst erst
recht kein ganzes Register (UDR) an einen Portpin zuweisen. Bitte schau
Dir die Abschnitte im AVR-GCC-Tutorial und
AVR-Tutorial: IO-Grundlagen an. Da scheinen bei Dir einige
elementare Basics zu fehlen.
Johannes M. wrote:
> Du kannst auf einen Portpin nicht auf diese Weise einzeln zugreifen! Das> Portregister heißt PORTC, und PORTC0 gibt es nicht. Und Du kannst erst> recht kein ganzes Register (UDR) an einen Portpin zuweisen. Bitte schau> Dir die Abschnitte im AVR-GCC-Tutorial und> AVR-Tutorial: IO-Grundlagen an. Da scheinen bei Dir einige> elementare Basics zu fehlen.
und wenn ichs so probiere:
@ Roy Thinnes (thinnes)
>und wenn ichs so probiere:> PORTC = (7<<UDR);
Dir fehlen WESENTLICHE Grundlagen. Hausaufgaben machen. Muss sein.
Bitmanipulation
MfG
Falk
Jo ich kann ASM und VB und nun will ich halt C lernen. Und ich lerns
halt am einfachsten in dem ich es anwende... Wenn ich es richtig
verstanden habe muss es so sein:
PORTC |= (UDR << 0);
und zum löschen:
PORTC &= ~(1 << 0);
oder schon wieder falsch?
Roy Thinnes wrote:
> Jo ich kann ASM und VB und nun will ich halt C lernen. Und ich lerns> halt am einfachsten in dem ich es anwende... Wenn ich es richtig> verstanden habe muss es so sein:>> PORTC |= (UDR << 0);>> und zum löschen:>> PORTC &= ~(1 << 0);>> oder schon wieder falsch?
Ja. Schon wieder falsch.
> PORTC &= ~(1 << 0);
Das hier löscht das Bit 0 am Port C. Soweit mag das richtig
sein.
Aber das hier:
> PORTC |= (UDR << 0);
ist Unsinn.
Karl heinz Buchegger wrote:
> Roy Thinnes wrote:>> Jo ich kann ASM und VB und nun will ich halt C lernen. Und ich lerns>> halt am einfachsten in dem ich es anwende... Wenn ich es richtig>> verstanden habe muss es so sein:>>>> PORTC |= (UDR << 0);>>>> und zum löschen:>>>> PORTC &= ~(1 << 0);>>>> oder schon wieder falsch?>> Ja. Schon wieder falsch.>>> PORTC &= ~(1 << 0);> Das hier löscht das Bit 0 am Port C. Soweit mag das richtig> sein.>> Aber das hier:>> PORTC |= (UDR << 0);>> ist Unsinn.
Wie soll ich das denn machen?? Muss man da ein if machen das so ausieht:
Wenn UDR = 1 dann bitsetzen sonst bit löschen
Oder wie wird das gemacht?
Bit setzen: PORTC |= (1 << PORTC0);
Bit löschen: PORTC &= ~(1 << PORTC0);
Für dein Vorhaben müsstest du jedes der 8 Bits des Registers UDR
nacheinander auf dem untersten Bit (PORTC0) des PORTC ausgeben.
PS: Das du Assembler kannst, glaube ich schonmal garnicht...
Johannes M. wrote:
> UDR ist ein REGISTER mit 8 Bits und PORTC ist ebenfalls ein> REGISTER mit 8 Bits...
Jo also ich will nur bit 0 von portc ansteuern also ausmaskieren aber
wie mach ich das mit dem udr reg.
Denk doch mal nach was du tun willst:
Du bekommst ein Byte vom Rechner (8 Bit, 256 mögiche Kombinationen) die
du auf einem Pin des PORTC (1 Bit, 2 mögliche Kombinationen) ausgeben
willst.
Du wirst also die 8 Eingangsbits nacheinander ausgeben müssen, mit einer
Modulation die bisher nur du kennst...
Ansonsten: http://de.wikipedia.org/wiki/Manchester_Code ist recht
verbreitet.
Tim T. wrote:
> Bit setzen: PORTC |= (1 << PORTC0);>> Bit löschen: PORTC &= ~(1 << PORTC0);>> Für dein Vorhaben müsstest du jedes der 8 Bits des Registers UDR> nacheinander auf dem untersten Bit (PORTC0) des PORTC ausgeben.>> PS: Das du Assembler kannst, glaube ich schonmal garnicht...
Ich kann Assembler habe jedoch seit Mai 07 nicht mehr programmiert...
Weder AMS noch VB oder sonst was...
Kann man es nicht mit einer Schleife lösen?? Also am schwierigsten ist
es für mich ASM und VB zu kombinieren (ASM wegen uC und VB wegen
Hochsprache) und dann auch noch in C umdenken (C kann ich noch
garnicht...)
Ich habe jetzt dies hier programmiert:
1
for(i=0;i<8;i++){
2
temp=(UDR&0x01);/* erstes bit ausmaskieren und in temp speichern */
3
4
if(temp==1){
5
PORTC|=(1<<PORTC0);/* =1 --> PORTC 1tes Bit setzen */
6
}else{
7
PORTC&=~(1<<PORTC0);/* =0 --> PORTC 1tes Bit löschen */
8
}
9
10
UDR=(UDR<<1);/* die Bits in UDR verschieben */
11
}
Was ich jetzt NICHT weiss ist:
- funktioniert das so?
- Schiebe ich in die richtige richtung?
Johannes M. wrote:
> Roy Thinnes wrote:>> - funktioniert das so?> Sieht eigentlich gar nicht schlecht aus, bis auf...>> - Schiebe ich in die richtige richtung?> Nein!
das heisst einfach nur so: UDR = (UDR>>1);
resp. die lösung von tim... die sieht auch ganz plausibel aus...
wobei ich dann wieder nicht weiss was das mit dem unsigned char auf sich
hat... muss da kein define oder so hin? resp. das ist doch wie bei VB
das dim i as ... ??? oder nicht??
Roy Thinnes wrote:
> Johannes M. wrote:>> Roy Thinnes wrote:>>> - funktioniert das so?>> Sieht eigentlich gar nicht schlecht aus, bis auf...>>> - Schiebe ich in die richtige richtung?>> Nein!>> das heisst einfach nur so: UDR = (UDR>>1);>> resp. die lösung von tim... die sieht auch ganz plausibel aus...> wobei ich dann wieder nicht weiss was das mit dem unsigned char auf sich> hat... muss da kein define oder so hin? resp. das ist doch wie bei VB> das dim i as ... ??? oder nicht??
unsigned char ist einfach nur eine vorzeichenlose 8 Bit Variable. Der
Datentyp Int ist ja mindestens 16 Bit.
Ja, sollte das gleiche sein wie dim i as integer.
Afaik gibt es nur auf Visual Basic keine unsigned Datentypen, was ich
aber nicht genau sagen kann da meine letzten Basic Sachen noch auf einem
C64 liefen...
Roy Thinnes wrote:
> muss da kein define oder so hin? resp. das ist doch wie bei VB> das dim i as ... ??? oder nicht??
Oh oh, bitte besorge Dir ein gutes Buch oder Tutorial! Egal in welcher
Sprache man programmiert: Wie Variablen deklariert werden, ist eines der
allerersten Dinge, die man wissen muss.
@ Roy Thinnes (thinnes)
>Ich hab die Schleife nun eingebaut...
Du hast noch sehr viel zu lernen.
>Könnte das Programm also nun so funktionieren wie es im Anhang ist?
1
/* Daten an IR-Port ausgeben */
2
unsignedchari;
3
for(i=0;i<8;i++){
4
if((UDR&(0x01<<i))>0){
5
PORTC|=(1<<PORTC0);
6
}else{
7
PORTC&=~(1<<PORTC0);
8
};
9
};
Das ist der Hammer! Mal abgesehen davon, dass man UDR nur einmal lesen
sollte, kann man das recht einfach "optimieren".
1
PORTC=UDR;
;-)
Der Rest deine Programms strotzt nur so vor Null-Plan. Fang nochmal ganz
am Anfang an. Mit ner blinkenden LED. Und einem C-Grundlagenbuch.
AVR-GCC-Tutorial
MFG
Falk
Das haut schon mal nicht hin. USART_empfangen() gibt einen Wert zurück,
den Du aber nicht verwendest! Du musst den Rückgabewert der Funktion
einer Variablen zuweisen (*).
1
if(UDR=="D")
Und das geht auch schief. UDR darf nur einmal gelesen werden. Das macht
aber schon die Funktion USART_Empfangen(). Wie oben schon gesagt: Der
Rückgabewert von USART_Empfangen() muss einer Variablen zugewiesen
werden und mit der Variablen kannst Du dann irgendwelche Abfragen
machen.
Außerdem rufst Du immer noch in der Funktion START die Funktion LOGIN
auf, die zu dem Zeitpunkt noch unbekannt ist. Nochmal, weil's so schwer
zu sein scheint: Du musst entweder dafür sorgen, dass alle Funktionen
zum Zeitpunkt ihres ersten Aufrufs definiert oder zumindest deklariert
sind. Wenn das aus dem Programmaufbau heraus so nicht möglich ist, dann
musst Du für die betreffenden Funktionen Prototypen deklarieren!
(*) Das ist zwar nicht generell erforderlich, da man einen Rückgabewert
auch ignorieren kann, wenn man ihn nicht braucht. Aber in diesem Fall
brauchst Du ihn.
Ansonsten kann ich nur wiederholen, was ich und andere oben schon
angedeutet haben: Das hat so keinen Zweck, Du brauchst C-Grundlagen. Und
die gibt's eigentlich nur in einem guten Buch!
Falk Brunner wrote:
> Das ist der Hammer! Mal abgesehen davon, dass man UDR nur einmal lesen> sollte, kann man das recht einfach "optimieren".>>
1
>PORTC=UDR;
2
>
Nö, grad das wollte er nicht! Siehe irgendwo weiter oben. Und das macht
auch die Schleife nicht. Er will den Inhalt von UDR an PC0 seriell
raustakten (warum auch immer, aber das steht hier zunächst mal nicht zur
Debatte...).
Die Geschwindigkeit, mit der er da raustaktet, ist eh viel zu hoch, als
dass da was Sinnvolles rauskommen kann...
Falk Brunner wrote:
> Das ist der Hammer! Mal abgesehen davon, dass man UDR nur einmal lesen> sollte, kann man das recht einfach "optimieren".>>
1
>PORTC=UDR;
2
>
Nö, die Schleife macht was anderes.
Und das mit dem nur einmal einlesen hatte ich auch in meinem Beispiel
auch erwähnt...
Aber das er die 8 Bit einfach an Pin 0 des Port C raushaut wird ihm eh
nicht weiter helfen, zumindest nicht wenn er nicht noch irgendwoher nen
Takt zaubert oder das ganze Moduliert. Wurde aber auch schon
geschrieben...
Ihr seit echt der Hammer ne... Dann sagt ihr mir 2 Fehler ich arbeite
daran und ihr sagt jo so klappts. Dann lad ich das Ding wieder hoch und
aufeinmal ist wieder alles falsch... Aber Hauptsache ICH hab keinen
Plan...
Das Programm soll einfach die Daten per usart empfangen und bei L ne
Antwort schicken und dann in den Sendemodus gehn dann im Sendemodus soll
es vergleichen ob die Daten die per uart kommen D sind und wenn ja dann
wieder in login und wenn nicht dann soll es alle Daten die per uart
kommen an portc pin 0 ausgeben... Da sind meine IR-Leds dran... Die
daten werde ich per PC "modulieren" es geht nur drum dass der uC ne
verbindung mit dem PC aufbaut und dann alle Daten die der PC sendet an
die IR-Leds weitergibt...
@ Tim T. (tim_taylor)
>Nö, die Schleife macht was anderes.
Ja, Entschuldigung, hab ich übersehen. Aber ich bleibe meiner zweiten
Aussage. Der OP Roy Thinnes braucht erst mal ganz dringend Grundlagen.
@ Roy Thinnes (thinnes)
>daten werde ich per PC "modulieren" es geht nur drum dass der uC ne>verbindung mit dem PC aufbaut und dann alle Daten die der PC sendet an>die IR-Leds weitergibt...
Und du glaubst ernsthaft, dass DU das mit deinem aktuellen Kenntnisstand
auch nur annähernd hinbekommst? Ich nicht.
MfG
Falk