mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Attiny 45 Lenkradfernbedienungs-Interface, erstes Programm so in Ordnung?


Autor: Stefan B. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Erst mal vorweg, ich bin seit fast 10 Jahren nicht mehr mit C in 
Berührung gekommen, dafür aber viel ABAP und C#.
Ich habe am Wochenende fleißig Datenblätter gewälzt und hier im Forum 
gestöbert, und einen ersten Entwurf für mein Programm erstellt.

Und zwar will ich einen Lenkradfernbedienungs-Interface für mein Auto 
bauen, fertig gibts sowas leider für mein Modell nicht.

Der Aufbau ist folgendermaßen:
An Pin PB3 kommt der Eingang von der LFB, eine Widerstandsleiter mit 
Tastern. Den genauen Wert für R2 kann ich erst berechnen, wenn ich die 
einzelnen Werte für die Tasten ausgemessen habe.

An Pin PB4 kommt der Anschluss für mein Radio.
Die genauen Informationen über das nötige Protokoll für mein 
Alpine-Radio hab ich von hier: 
http://www.mp3car.com/vbulletin/input-devices/1311...

Leider habe ich noch keinen µC um das ganze mal zu testen, muss erst 
noch die Teile bestellen.

Könnt ihr mal bitte drüberschauen, ob mein Code so einigermaßen stimmt?

Vor allem die Initialisierung der Register und des ADC und die Benutzung 
des Interrupts.

Das Programm habe ich mit WinAVR im Programmer's Notepad erstellt.
Beim kompilieren erhalte ich ein paar Warnings bei folgenden Stellen:
const alp_datagram_data_t  alp_datagram_vol_up  = {1,1,0,1,1,0,1,1, 1,1,0,1,0,1,1,0, 1};
...
alp_datagram_data_t *data;
data = alp_datagram_vol_up;    <--
Hier kommt "warning: assignment from incompatible pointer type", aber 
ich verstehe nicht ganz warum...

Kommentare, Kritik und Verbesserungsvorschläge sehr erwünscht ;)

MfG

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:

>
> const alp_datagram_data_t  alp_datagram_vol_up  = {1,1,0,1,1,0,1,1,
> 1,1,0,1,0,1,1,0, 1};
> ...
> alp_datagram_data_t *data;
> data = alp_datagram_vol_up;    <--
> 
> Hier kommt "warning: assignment from incompatible pointer type", aber
> ich verstehe nicht ganz warum...

data ist ein Pointer auf eine Datenstruktur, alp_datagram_vol_up 
beinhaltet die Daten. Das passt nicht zusammen.

Wenn, dann muss es heißen:

data = &alp_datagram_vol_up;

Gruß,

Frank

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast natürlich recht.
Aber die Compilerwarnung bleibt leider die selbe...

Also sowohl bei
data = &alp_datagram_vol_up; (eigentlich richtig)
als auch bei
data = alp_datagram_vol_up; (falsch)

Am Anfang hatte ich es auch richtig, so wie du geschrieben hast.
Nur beim Testen woher die dusslige Warning kommt hab ich halt mal alle 
falschen Möglichkeiten durchprobiert, um zu sehen was für Meldungen dann 
ausgeworfen werden.
Und am Ende dann vergessen es wieder richtig zu schreiben, war schon 
spät gestern...

MfG

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Aber die Compilerwarnung bleibt leider die selbe...

Sicher?

Ich würde eher denken, dass da ein "...discards qualifier" kommt.

Autor: Stefan B. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ja, bei beiden Varianten die gleiche Meldung.
Ich hab auch mal einen Screenshot angehängt...

Irgendwelche Ideen woher das kommen könnte?
Vielleicht eine Einstellung im Compiler...

Ich habe alles ohne weitere Anpassungen so verwendet, wie es installiert 
wurde.
Das Makefile ist aus dem sample-Verzeichnis kopiert, dort habe ich nur 
die Zeile
CU = attiny45
angepasst.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moment mal, als was ist denn alp_datagram_data_t deklariert?  Der
Initializer sieht so aus, als wäre das ein Array...  Ein Array
wird durch einen Zeiger auf das erste Element weitergereicht, ich
vermute, du hast ein array of pointers draus gemacht.

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau, alp_datagram_data_t ist ein Array:
#define ALP_DATAGRAM_DATA_LEN  17
typedef bool alp_datagram_data_t[ALP_DATAGRAM_DATA_LEN];
const alp_datagram_data_t  alp_datagram_vol_up  = {1,1,0,1,1,0,1,1, 1,1,0,1,0,1,1,0, 1};

Jörg Wunsch schrieb:
> Ein Array
> wird durch einen Zeiger auf das erste Element weitergereicht, ich
> vermute, du hast ein array of pointers draus gemacht.

Aah, jetzt hats "Klick" gemacht... Danke!
So muss es sein, oder?
    alp_datagram_data_t data;
    *data = *alp_datagram_vol_up;

Und wie stehts mit dem Rest vom Programm?
Macht der auch wirklich das, was ich in den Kommentaren geschrieben 
habe?
(Ja ich schreibe meine Comments immer in Englisch... ;) )

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein,
const bool *data;

...
data = alp_datagram_vol_up;

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert auch nicht.
Wenn data const ist, kann ich ja keinen Wert zuweisen.
Und wenn ich das const weglasse, bekomme ich
"warning: assignment discards qualifiers from pointer target type"

Vielleicht nochmal eine Beschreibung was ich machen will:
- Ich definiere mir ein paar globale konstante Variablen vom Typ 
"alp_datagram_data_t" (ein bool-Array mit Länge 17).
- In der Funktion "send_to_hu()" hole ich mir anhand des übergebenen 
Parameters per switch...case eine Referenz auf die richtige der vorher 
oben definierten Variablen in meine lokale Variable "data".
Dann kommt eine For-Schleife über die Elemente (="Bits") von "data", und 
die Werte werden entsprechend am Ausgang ausgegeben.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unter C kann man keine beliebigen Bitbreiten definieren, es gibt nur 
uint8_t, uint16_t und uint32_t, also keine 17 Bit usw.

Womöglich macht der Compiler sogar Deine Typen alles int, dann ist aber 
ruchzuch Dein SRAM explodiert. Ein int je Bit ist zu teuer.


Versuch mal alles in Bytefelder umzusetzen, der AVR-GCC versteht sogar 
Binärschreibweise.

Die vielen Switch-Case würde ich als Pointerarray vereinfachen.


Peter

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Funktioniert auch nicht.

Dann liefere mal so viel Programmtext, dass man das selbst compilieren
kann.

Autor: Stefan B. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Dann liefere mal so viel Programmtext, dass man das selbst compilieren
> kann.

Gleich im Anfangspost habe ich doch den kompletten Quelltext des 
Programms angehängt...
Was fehlt denn genau?

Peter Dannegger schrieb:
> Womöglich macht der Compiler sogar Deine Typen alles int, dann ist aber
> ruchzuch Dein SRAM explodiert. Ein int je Bit ist zu teuer.
>
>
> Versuch mal alles in Bytefelder umzusetzen, der AVR-GCC versteht sogar
> Binärschreibweise.

Ja, leider wird bool intern wohl auf byte umgesetzt, der Daten-Speicher 
war fast voll. Und bit fields wollte ich eigentlich vermeiden, wegen dem 
fehlenden Index-Zugriff.

Aber dein Tipp mit der Binärschreibweise hat mich auf was gebracht:
Die ganzen bool[] habe ich durch UINT32_t ersetzt.
Als Wert haben sie jeweils die Element-Werte in umgekehrter Reihenfolge 
in Binärschreibweise erhalten:
const alp_datagram_data_t  alp_datagram_vol_up  = {1,1,0,1,1,0,1,1, 1,1,0,1,0,1,1,0, 1}; // alt
const uint32_t alp_datagram_vol_up = 0b10110101111011011ul; // neu
um nun auf die einzelnen Bits zugreifen zu können, habe ich mir eine 
kleine Hilfsfunktion gebastelt:
bool get_bit(uint32_t data, uint8_t index)
{
    // index may not be higher than 31 for 32 bit value
    if(index > 31)
        return false;
    
    // extract the n-th bit by and-ing data with just one binary "1" in n-th bit
    // then the result is shifted right by n places to get the bit we want
    return ((data & (1<<index))>>index);
}

Im Anhang liegt die neue Version sowie das Makefile dazu.

MfG

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo und wie ist denn bool und false definiert?
Ich versuche, nicht standard Typen möglichst zu vermeiden.

Bezüglich analoge Tastenabfrage, das kann man beqem alles den Compiler 
ausrechnen lassen:

Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"


Peter

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Wo und wie ist denn bool und false definiert?

Das ist über #include <stdbool.h> definiert.

Peter Dannegger schrieb:
> Bezüglich analoge Tastenabfrage, das kann man beqem alles den Compiler
> ausrechnen lassen:
>
> Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"

Danke für den Tip!
Die Rechnerei überlass ich dann dem Compiler...

Sind sonst noch irgendwelche groben Schnitzer bei mir drin?
Vor allem: Machen meine Initialisierungen auch das, was sie laut 
Kommentar bewirken sollen?

MfG

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> Das ist über #include <stdbool.h> definiert.

Die findet der AVR-GCC aber nicht.
Auch die 2 weiteren Compiler auf meinem PC kennen sie nicht.


Peter

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Seltsam, in meinem WinAVR ist das standardmäßig vorhanden, und zwar im 
Verzeichnis
[WinAVR-Ordner]\lib\gcc\avr\4.3.3\include\stdbool.h

Hier der Inhalt (ohne Copyright-Hinweis):
#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool  _Bool
#define true  1
#define false  0

#else /* __cplusplus */

/* Supporting <stdbool.h> in C++ is a GCC extension.  */
#define _Bool  bool
#define bool  bool
#define false  false
#define true  true

#endif /* __cplusplus */

/* Signal that all the definitions are present.  */
#define __bool_true_false_are_defined  1

#endif  /* stdbool.h */

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> [WinAVR-Ordner]\lib\gcc\avr\4.3.3\include\stdbool.h

Hätt ich mal doch die Windows-Suche benutzen sollen.
Ich hab nur unter ...\avr\include nachgesehen.

> #define false  0

Dann stellst sich die Frage, wie sich in der Funktion get_bit() false 
von einem 0-Bit unterscheidet.


Peter

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kein Problem, ich hab zuerst auch nur da nachgeschaut.
Da hätten die doch auch ne info.txt mit reinpacken können, damit man 
weiß wo der Rest ist...

Peter Dannegger schrieb:
> Dann stellst sich die Frage, wie sich in der Funktion get_bit() false
> von einem 0-Bit unterscheidet.

Wenn du damit das
    if(index > 31)
        return false;
meinst, dann gar nichts.
Ist nur eine Angewohnheit, normalerweise programmiere ich ja C#.
Ich ändere es mal auf "return 0", damit es überall gleich aussieht...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:

> Da hätten die doch auch ne info.txt mit reinpacken können, damit man
> weiß wo der Rest ist...

Es gibt einfach zwei Verzeichnisse, in denen der Compiler nach
Headerdateien nachsieht.  Das eine gehört zum Compiler selbst und
wird von ihm verwaltet, die Dateien dort gehören zum GCC-Paket.
Das ist das, wo u. a. auch <stdbool.h> gefunden wird.

Das zweite Verzeichnis gehört zur avr-libc, wird von dieser verwaltet
und entsprechend installiert, wenn man die Bibliothek baut und
installiert.

Wenn man den Compiler mit -v aufruft, zeigt er einem an, wo er beim
Compilieren überall nach den Dateien sucht.

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit der info.txt war auch nur Spaß. ;)

Jörg Wunsch schrieb:
> Wenn man den Compiler mit -v aufruft, zeigt er einem an, wo er beim
> Compilieren überall nach den Dateien sucht.

Danke für den Hinweis!

MfG

Autor: Stefan B. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab mein Programm noch etwas erweitert und (hoffentlich) 
verbessert.

Der ADC-Eingang hat noch eine kleine Entprell-Routine in der ADC-ISR 
spendiert bekommen, und die ganzen delay_ms und delay_us wurden durch 
einen Timer ersetzt.

Ist das jetzt zumindest einigermaßen brauchbar?

MfG Stefan

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.