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


von Stefan B. (Gast)


Angehängte Dateien:

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/131147-need-alpine-wired-remote-control-pinout.html#post1314327

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:
1
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};
2
...
3
alp_datagram_data_t *data;
4
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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Stefan B. schrieb:

>
1
> const alp_datagram_data_t  alp_datagram_vol_up  = {1,1,0,1,1,0,1,1,
2
> 1,1,0,1,0,1,1,0, 1};
3
> ...
4
> alp_datagram_data_t *data;
5
> data = alp_datagram_vol_up;    <--
6
>
> 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

von Stefan B. (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> Aber die Compilerwarnung bleibt leider die selbe...

Sicher?

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

von Stefan B. (Gast)


Angehängte Dateien:

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
1
CU = attiny45
angepasst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Stefan B. (Gast)


Lesenswert?

Ja genau, alp_datagram_data_t ist ein Array:
1
#define ALP_DATAGRAM_DATA_LEN  17
2
typedef bool alp_datagram_data_t[ALP_DATAGRAM_DATA_LEN];
3
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?
1
    alp_datagram_data_t data;
2
    *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... ;) )

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nein,
1
const bool *data;
2
3
...
4
data = alp_datagram_vol_up;

von Stefan B. (Gast)


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.

von Peter D. (peda)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> Funktioniert auch nicht.

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

von Stefan B. (Gast)


Angehängte Dateien:

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:
1
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
2
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:
1
bool get_bit(uint32_t data, uint8_t index)
2
{
3
    // index may not be higher than 31 for 32 bit value
4
    if(index > 31)
5
        return false;
6
    
7
    // extract the n-th bit by and-ing data with just one binary "1" in n-th bit
8
    // then the result is shifted right by n places to get the bit we want
9
    return ((data & (1<<index))>>index);
10
}

Im Anhang liegt die neue Version sowie das Makefile dazu.

MfG

von Peter D. (peda)


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

von Stefan B. (Gast)


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

von Peter D. (peda)


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

von Stefan B. (Gast)


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):
1
#ifndef _STDBOOL_H
2
#define _STDBOOL_H
3
4
#ifndef __cplusplus
5
6
#define bool  _Bool
7
#define true  1
8
#define false  0
9
10
#else /* __cplusplus */
11
12
/* Supporting <stdbool.h> in C++ is a GCC extension.  */
13
#define _Bool  bool
14
#define bool  bool
15
#define false  false
16
#define true  true
17
18
#endif /* __cplusplus */
19
20
/* Signal that all the definitions are present.  */
21
#define __bool_true_false_are_defined  1
22
23
#endif  /* stdbool.h */

von Peter D. (peda)


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

von Stefan B. (Gast)


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
1
    if(index > 31)
2
        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...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Stefan B. (Gast)


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

von Stefan B. (Gast)


Angehängte Dateien:

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.