Hallo, ich habe ein kleines Problem. Ich habe mehrere Arrays die einen bestimmten Programmablauf darstellen Sprich 16 spalten für die 16 pwm ausgänge (stärke 0..255) und 16 zeilen die quasi eine sequenz von 16 verschiedenen mustern darstellen volatile uint8_t muster1 [16][16] = { Werte werden eingefügt }; volatile uint8_t muster2 [16][16] = { Werte werden eingefügt }; volatile uint8_t muster3 [16][16] = { Werte werden eingefügt }; usw. nun habe ich einen soft pwm programmiert wecher volatile uint8_t pwm_setting [16][16] benutzt um den PWM zu steuern mein problem besteht nun darin, dass ich folgendes nicht schreiben kann pwm_setting = muster2; ich habe keine erklärung dafür gefunden! habe auch im forum gesucht aber auch drt habe ich nichts gefunden kann man da was machen , dass man nur auf das gewünschte muster zeigt??
Ein Zuweisung wie bei einer einfachen Variablen
1 | a = b; |
funktioniert bei einem Array nicht. Du mußt entweder die Elemente in einer Schleife kopieren, oder z.B. memcpy() verwendet. Oder Du übergibst nicht eine Kopie des Arrays, sondern eine Referenz auf das Array (sprich einen Zeiger).
Nimmt die Funktion soft_pwm einen parameter? Ich denke da an den Pointer auf das Array was bearbeitet werden soll. Mit einer festverdrahteten globalen Variable zu arbeiten schränkt ja ein, Wenn also soft_pwm( uint8_t* data ) existiert, die data mit deinem Datenlayout interpretiert (und du davon ausgehst, daß die die beiden Dimensionen konstant hast), kannst du ja einfach soft_pwm( muster1 ), soft_pwm( muster2 ) etc aufrufen. Ist die Dimension [16][16] nicht fest, müsstest du die noch mitübergeben, damit die Funktion das Array nicht verlässt. Nachtrag: Spricht auch nichts dagegen bei den festen Grenzen soft_pwm( uint8_t daten[16][16] ) zu definieren.
Florian Bauer schrieb: > pwm_setting = muster2; > > ich habe keine erklärung dafür gefunden! habe auch im forum gesucht aber > auch drt habe ich nichts gefunden Nun ja, ein gutes C-Buch hilft da eher weiter. Das Forum hier ist ja kein generelles C-Grundlagenforum. Man kann halt in C keine Arrays per "=" kopieren, dafür benötigst du memcpy. Allerdings willst du vermutlich die Array gar nicht kopieren, es reicht ja ein Pointer auf das jeweils aktuelle Array, umd damit was zu machen. Oliver
Vielen Dank für die Tips!! Echt super feedback Habe es jetzt so gelöst: Nachtrag: Spricht auch nichts dagegen bei den festen Grenzen soft_pwm( uint8_t daten[16][16] ) zu definieren. Diese Lösung ist echt super für mich da ich ja nur 8 dieser Arrays/ bei mir sind es quasi muster/ habe
Irgendwie funktiniert das mit den Pointern nicht so wie ich das will. Vieleicht könnt ihr mir helfen. hier habe ich meine muster uint8_t muster1 [16][16]; uint8_t muster2 [16][16]; dann habe ich einen Zeiger der auf ein Muster zeigen soll uint8_t *muster_ptr; in der MAIN weise ich dann dem Pointer die Anfangsadresse meines Arrys zu muster_ptr = muster2; dann rufe ich durch eine Interruptroutine meine Funktion auf soft_PWM (&muster_ptr) die funktion sieht dann wie folgt aus: void soft_PWM (uint8_t **muster) { for (uint8_t i=0;i<16;i++) { uint8_t temp = **(muster+i); //hier wird mein array wert gelesen if(temp>10) //hier wird der wert verarbeitet { setzte bits in einem register } } } irgendwie funktioniert jedoch der aufruf nicht im avr studio kommt auch immer eine warnung: assignment from incopatible pointer type weis echt nicht mehr weiter, hab schon alles durchsucht.... kann des sein, weil mein array 2 dimensional ist??? ich könnte es ja eigentlich auch in ein 1 dimensionales array reinschreiben . Aber normalerweise dürfte es keinen unterschied machen , weil die daten ja eh in einer reihenfolge im speicher stehen.
Florian Bauer schrieb: > in der MAIN weise ich dann dem Pointer die Anfangsadresse meines Arrys > zu > muster_ptr = muster2; Ich habe mich damals auch etwas mit C/C++ beschäftigt. Ich bin der Crack aber müsste das nicht *muster_ptr = &muster2; heissen? Du weisst ja den Pointer den die Anfangsadresse mit. Und warum Florian Bauer schrieb: > void soft_PWM (uint8_t **muster) ???????? Hier ein einfacher Beispiel -------------------------------------------------------- int EinUndAusgabe (int *uebergeben) { printf("Gib eine beliebige Zahl ein: "); scanf("%i",uebergeben); //wieder ist der Adressoperator (&) nicht nötig, weil der Pointer breits die Adresse enthält printf("Ausgabe ueber Pointer: %i",*uebergeben); } int main () { int Eingabe; int *Pointer = &Eingabe; EinUndAusgabe(Pointer); getch(); -------------------------------------------------------- Hoffe das ist richtig so. Habe nur gefährliches Halbwissen :)
Sorry für Doppeleintrag :) Noch zu früh "Ich habe mich damals auch etwas mit C/C++ beschäftigt. Ich bin der Crack aber müsste das nicht" sollte heissen "Ich habe mich damals auch etwas mit C/C++ beschäftigt. Ich bin NICHT der Crack aber so müsste das sein" :-) Sorry
Florian Bauer schrieb:
1 | uint8_t muster1 [16][16]; |
2 | uint8_t muster2 [16][16]; |
3 | uint8_t *muster_ptr; |
4 | muster_ptr = muster2; |
5 | soft_PWM (&muster_ptr) |
6 | void soft_PWM (uint8_t **muster) |
7 | {
|
8 | for (uint8_t i=0;i<16;i++) |
9 | {
|
10 | uint8_t temp = **(muster+i); //hier wird mein array wert gelesen |
11 | if(temp>10) //hier wird der wert verarbeitet |
12 | {
|
13 | setzte bits in einem register |
14 | }
|
15 | }
|
16 | }
|
Da stimmt etwas grundlegendes nicht: 1. Deine "muster1" und "muster1" sind 2-dimensionale 16x16er Arrays. In der Funktion "soft_PWM" liest Du aber ein 1-dimensionales 16er Array aus. D.h. in Deinem Code würden überhaupt nur 16 von 256 Bytes verwendet. 2. Was für einen Datensatz willst Du denn in soft_PWM() überhaupt verarbeiten? Willst Du ein 16er-Array oder ein 16x16er-Array?
Florian Bauer schrieb: > dann habe ich einen Zeiger der auf ein Muster zeigen soll > uint8_t *muster_ptr; Das ist ein Zeiger auf einen uint8_t. Den kannst du nutzen, um auf den Anfang eines Arrays aus uint8_t zu zeigen. Ein Muster ist aber kein Array aus uint8_t, sondern ein Array aus Arrays aus uint8_t. > in der MAIN weise ich dann dem Pointer die Anfangsadresse meines Arrys > zu > muster_ptr = muster2; Das sollte zu einer Warnung führen, weil der Typ falsch ist. > dann rufe ich durch eine Interruptroutine meine Funktion auf > soft_PWM (&muster_ptr) Warum übergibst du die Adresse des Zeigers statt einfach nur den Zeiger selbst? > irgendwie funktioniert jedoch der aufruf nicht > im avr studio kommt auch immer eine warnung: > assignment from incopatible pointer type Sicher, daß die beim Aufruf kommt? Da stimmen die Typen überein, aber bei deiner Zuweisung in main nicht. > ich könnte es ja eigentlich auch in ein 1 dimensionales array > reinschreiben . Aber normalerweise dürfte es keinen unterschied machen , > weil die daten ja eh in einer reihenfolge im speicher stehen. Es macht einen Unterschied, weil C eine typisierte Sprache ist. Datentypen gibt es nicht ohne Grund, und sie müssen zusammenpassen. Du könntest es so machen: statt > uint8_t *muster_ptr; nimmst du:
1 | uint8_t (*muster_ptr)[16]; // Zeiger auf ein Array aus 16 uint8_t |
Dann aus // soft_PWM (&muster_ptr)
1 | soft_PWM (muster_ptr); |
und aus: // void soft_PWM (uint8_t **muster)
1 | void soft_PWM (uint8_t (*muster)[16]) |
dann kannst du über den Pointer genau so zugreifen, wie du es auch bei direkter Verwendung eines Musters tun würdest:
1 | uint8_t temp = muster[a][c]; // a und c im Bereich 0...15 |
PS: Falls sich jemand fragt, warum der zweite Index c statt b ist: Das liegt daran, daß das Forum mein Posting mit b in eckigen Klammern nicht akzeptiert, da das angeblich Spam sei...
> Da stimmt etwas grundlegendes nicht: > 1. Deine "muster1" und "muster1" sind 2-dimensionale 16x16er Arrays. In > der Funktion "soft_PWM" liest Du aber ein 1-dimensionales 16er Array > aus. D.h. in Deinem Code würden überhaupt nur 16 von 256 Bytes > verwendet. > 2. Was für einen Datensatz willst Du denn in soft_PWM() überhaupt > verarbeiten? Willst Du ein 16er-Array oder ein 16x16er-Array? Die Grundidee ist 16 PWM Ausgänge mit 16 bestimmten Werten für eine bestimmte zeit ca.2-3 sekunden laufen zu lassen und dann auf quasi auf den nächsten "frame" (die zweite zeile des arrays) zu springen und diese einstellung wieder für ein par sekunden zu nutzen. Und das eben 16 mal.
> Das ist ein Zeiger auf einen uint8_t. Den kannst du nutzen, um auf den > Anfang eines Arrays aus uint8_t zu zeigen. Ein Muster ist aber kein > Array aus uint8_t, sondern ein Array aus Arrays aus uint8_t. Was meinst du mit Muster denn genau?? Ich habe mir nur die Speicherstruktur von 2 dimesionalen Arrays angesehen und dort ist es ja im prinzip egal ob ich ein 1 dimensionales oder ein zweidimensionales Array mache, weil die werte ja der reihe nach gespeichert werden. Deswegen habe ich mir auch gedacht, dass ich genauso wie bei einem 1 dimensionalen array nur die Adresse der Startposition angebe und dann durch das wissen von der Zeilenlänge und der anzahl von reihen die einzelnen elemente abfragen kann. Oder ist es nicht möglich die Startadresse von 2 dimensionalen arrays zu übergeben? > >> in der MAIN weise ich dann dem Pointer die Anfangsadresse meines Arrys >> zu >> muster_ptr = muster2; > > Das sollte zu einer Warnung führen, weil der Typ falsch ist. Aber wie kann hier der Typ falsch sein? ich weise einem pointer die Startadresse des 2 dimensionalen arrays zu. Das wäre ja "laut literatur" genau das gleiche wie muster_ptr = &muster2[0] > Du könntest es so machen: > > statt >> uint8_t *muster_ptr; > > nimmst du: >
1 | > uint8_t (*muster_ptr)[16]; // Zeiger auf ein Array aus 16 uint8_t |
2 | >
|
........habe hier abgekürzt > [C] > uint8_t temp = muster[a][c]; // a und c im Bereich 0...15 Das verstehe ich nicht ganz. Wie ist es möglich auf ein zweidimensionales array (muster[a][c]) zuzugreifen wenn ich nur ein eindimensionales array erstelle(Zeiger auf ein Array aus 16 uint8_t)?? irgendwie will der groschen bei mir nicht fallen
> Du könntest es so machen: > > statt >> uint8_t *muster_ptr; > > nimmst du: >
1 | > uint8_t (*muster_ptr)[16]; // Zeiger auf ein Array aus 16 uint8_t |
2 | >
|
> > Dann aus > // soft_PWM (&muster_ptr) > >
1 | > soft_PWM (muster_ptr); |
2 | >
|
> > und aus: > // void soft_PWM (uint8_t **muster) > >
1 | > void soft_PWM (uint8_t (*muster)[16]) |
2 | >
|
> > dann kannst du über den Pointer genau so zugreifen, wie du es auch bei > direkter Verwendung eines Musters tun würdest: >
1 | > uint8_t temp = muster[a][c]; // a und c im Bereich 0...15 |
2 | >
|
> > PS: Falls sich jemand fragt, warum der zweite Index c statt b ist: > Das liegt daran, daß das Forum mein Posting mit b in eckigen Klammern > nicht akzeptiert, da das angeblich Spam sei... Hallo, habe es gerade so ausprobiert. Und was soll ich sagen.... Es funktioniert einfach super. Vielen vielen Dank dafür. Habe des mit 2 dimensionalen arrays und den pointern nochmla nachgelesen und verstehe jetzt so halb wie das funktioniert. Am einfachsten wäre immernoch wenn man 2dimensionale arrays einfach per = zuweisen könnte
Florian Bauer schrieb: > Die Grundidee ist 16 PWM Ausgänge mit 16 bestimmten Werten für eine > bestimmte zeit ca.2-3 sekunden laufen zu lassen und dann auf quasi auf > den nächsten "frame" (die zweite zeile des arrays) zu springen und diese > einstellung wieder für ein par sekunden zu nutzen. Und das eben 16 mal. Das Problem ist, daß es mir nicht ersichtlich ist, wo Du mit welcher "Datenbreite" arbeiten willst. Willst Du 1. eine Funktion soft_PWM() für jeden Kanal einzeln machen? -> dann würdest Du ihr ein 1-dim. 16er-Array übergeben. 2. eine gemeinsame Funktion soft_PWM() für alle 16 Kanäle machen? -> dann würdest Du ihr ein 2-dim. 16x16er-Array übergeben. Wenn Du einen Zeiger "uint8_t*" benutzt, enthält dieser nichts anderes als eine Adresse im Speicher. Ob Du diese Adresse als Basis eines 16er oder eines 16x16er Arrays oder irgendetwas anderem interpretierst, liegt in Deiner Handlungsfreiheit. Bsp für 1-kanalige soft_PWM:
1 | uint8_t muster1 [16]; |
2 | uint8_t *muster_ptr; |
3 | muster_ptr = muster2; |
4 | soft_PWM_nur1kanal(muster_ptr); |
5 | |
6 | void soft_PWM_nur1kanal(uint8_t *muster) |
7 | {
|
8 | for (uint8_t i=0;i<16;i++) |
9 | {
|
10 | uint8_t temp = muster[i]; // ist das gleiche wie = *(muster+i); |
11 | if(temp>10) |
12 | {
|
13 | ...
|
14 | }
|
15 | }
|
16 | }
|
Bsp für 16-kanalige soft_PWM:
1 | uint8_t muster1 [16][16]; |
2 | uint8_t *muster_ptr; |
3 | muster_ptr = muster2; |
4 | soft_PWM_16kaenale(muster_ptr); |
5 | |
6 | void soft_PWM_nur1kanal(uint8_t *muster) |
7 | {
|
8 | for (uint8_t kanal=0;kanal<16;kanal++) |
9 | {
|
10 | for (uint8_t i=0;i<16;i++) |
11 | {
|
12 | uint8_t temp = muster[kanal*16+i]; |
13 | if(temp>10) |
14 | {
|
15 | ...
|
16 | }
|
17 | }
|
18 | }
|
19 | }
|
Du siehst, man kann in beiden Fällen die gleiche Mimik benutzen, da Du nichts anderes benögtist, als eine Basisadresse. Allerdings muß Deine soft_PWM()-Funktion natürlich das richtige damit anfangen.
Jetzt hab ichs endlich gechekt mit den pointern. Habe selber viel zu kompliziert gedacht!!!!! Danke an alle die hier wirklich sehr gute Kommentare abgeliefert haben. Ohne eure Hilfe wäre ich sicher noch verzweifelt. Schöne Grüße aus Innsbruck Florian
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.