Op deze website gebruiken we cookies om content en advertenties te personaliseren, om functies voor social media te bieden en om ons websiteverkeer te analyseren. Ook delen we informatie over uw gebruik van onze site met onze partners voor social media, adverteren en analyse. Deze partners kunnen deze gegevens combineren met andere informatie die u aan ze heeft verstrekt of die ze hebben verzameld op basis van uw gebruik van hun services. Meer informatie.

Akkoord

Vraag & Antwoord

Programmeren

Geschikte functie in C

None
31 antwoorden
  • Scroll down
  • Als het goed is, dan staan dit soort dingen in de handleiding van je microcontroller. Dit verschilt per microcontroller.
  • Scroll down
  • Ik weet niet hoe je die outputs bediend. Is het een enkel register? Dan kun je makkelijk bit-shiften. Dan krijg je zoiets:
    [code:1:6d38440694]output = 0x0001;
    for (int i = 0; i < 12; ++i)
    {
    output <<= 1;
    }[/code:1:6d38440694]
  • Outputs gestuurd vanuit 3 registers[code:1:6a6f242634]DDR0 - 1111 0000 (Out 9, 10, 11, 12, x, x, x, x)
    bevat outputs 9 t/m 12
    DDR1 - 1111 0010 (Out 2, x, 1, x, x, x, x, x)
    bevat outputs 1 en 2
    DDR2 - 1111 1010 (Out 8, 7, 6, 5, 4, x, 3, x)
    bevat outputs 3 t/m 8
    DDR4 - 0000 0110 (x, x, x, RX, x, x, x, x)
    bevat input RX[/code:1:6a6f242634]Scroll down
  • Laat ik even aannemen dat het mogelijk is de uitvoer van een register in een variabele te zetten. Het is mogelijk een functie te maken die aan een nummer (output nummer) de waarde van die output teruggeeft. Ik zal een voorbeeld geven van zo'n functie die output 1 en output 2 kan lezen:[code:1:ff0cced3e2]char leesOutput( char nummer )
    {
    unsigned char ddr[4];
    char output = 0; //Waarde indien nummer niet geldig is
    //Vul hier de ddr-variables met de registers
    switch( nummer )
    {
    case 1: // output 1
    output = ( ddr[ 1 ] >> 5 ) & 0x01;
    break;
    case 2: // output 2
    output = ( ddr[ 1 ] >> 7 ) & 0x01;
    break;
    }
    return output;
    }[/code:1:ff0cced3e2]Dit is zeker niet de enige (en meest efficiente) methode, maar zou wel moeten werken (ik heb deze functie niet getest).

    Ik maak een vergelijkbare functie voor het veranderen van een output:[code:1:ff0cced3e2]void schrijfOutput( char nummer, char waarde )
    {
    int register = 0;
    unsigned char mask = 0;
    unsigned char ddr;
    switch( nummer )
    {
    case 1:
    register = 1; //Output 1 staat in register 1 (DDR1)
    mask = 0x20; //Binair is dit 00100000, oftewel 1 op de bit waar output1 zit.
    break;
    case 2:
    register = 1;
    mask = 0x80;
    break;
    }
    ddr = leesRegister( register ); //Code om register (register) in de variable ddr te krijgen
    ddr &= ~mask; //Verwijder oude waarde van deze output
    if( waarde )
    ddr |= mask; //Zet nieuwe waarde van deze output
    schrijfRegister( register, ddr ); //Code om ddr terug naar register (register) te schrijven
    }[/code:1:ff0cced3e2]Ook deze functie heb ik niet getest. De code voor RX lijkt hier natuurlijk erg op.

    Hoe je de waarde van RX moet controleren hangt er een beetje van of je een melding krijgt van het systeem als RX verandert. Als dit niet zo is, kun je de volgende code gebruiken:[code:1:ff0cced3e2] while( !leesRX() )
    {
    usleep(100);
    }[/code:1:ff0cced3e2]Ik weet niet zeker of de functie usleep op alle platformen beschikbaar is. Indien deze functie niet beschikbaar is, is er vast wel een andere functie om een korte tijd te wachten (100 microseconden, in dit geval). Zo'n functie zorgt ervoor dat het programma niet teveel processorkracht inneemt.

    LeesRX is natuurlijk een functie die erg lijkt op leesOutput(). De details hoe je registers moet lezen en schrijven (en of je rechtstreeks naar een register mag schrijven) staat natuurlijk in de handleiding van de microcontroller.
  • Ik dank je ontzettend voor je reactie! heb de code verder uitgebreid voor mijn project en na het compileren worden er geen errors weergegeven. Ik zit echter nog met een klein probleempje[code:1:24bff2de0a]char leesOutput( char nummer )
    {
    unsigned char ddr[4];
    char output = 0; // Waarde indien nummer niet geldig is
    [b] // Vul hier de ddr-variables met de registers [/b]
    switch( nummer )
    {
    case 1: // output 1
    output = ( ddr[ 1 ] >> 5 ) & 0x01;
    break;
    case 2: // output 2
    output = ( ddr[ 1 ] >> 7 ) & 0x01;
    break;
    }
    return output;
    }[/code:1:24bff2de0a][b:24bff2de0a]// Vul hier de ddr-variables met de registers[/b:24bff2de0a] zou iemand mij dit kunnen toelichten?
  • [quote:9a1bfb1ad7="Lettin03"]Het vetgedrukte, zou iemand mij dit kunnen toelichten?[/quote:9a1bfb1ad7]Je wilt natuurlijk de gegevens van de microcontroller gebruiken in het programma. Daarom moet je de gegevens uit de microcontroller kunnen lezen.

    De code die daar toegevoegt moet worden moet precies dat doen. Dus eerst register 0 uit de microcontroller halen en deze opslaan in ddr[0]. Evenzo voor register 1 in ddr[1] tot en met register 3 in ddr[3]. Hoe dit precies moet staat waarschijnlijk in de handleiding van de microcontroller.

    De rest van de functie gebruikt deze gegevens om de uitvoer te kunnen berekenen.
  • Ik kan het nergens in de datasheet vinden. Mijn gedachte gaat uit naar een structuur als het volgende.[code:1:2390c2e0a5]char leesRegister( Register[], ddr[] )
    {
    code
    }[/code:1:2390c2e0a5]Of zit ik er nu erg ver naast? Tevens het compileren van beide codes geeft geen error weer, echter tijdens het zogeheten 'make file' worden er twee errors weergegeven[code:1:2390c2e0a5] ddr = leesRegister( Register ) ;
    ddr &= ~mask;
    if( waarde )
    {
    ddr |= mask;
    schrijfRegister( Register, ddr );[/code:1:2390c2e0a5]De errors zijn:[code:1:2390c2e0a5]main.c(72) E4305L: Unresolved external symbol (_leesRegister)
    main.c(77) E4305L: Unresolved external symbol (_schrijfRegister)[/code:1:2390c2e0a5]Deze errors zijn logisch, de twee functies worden nergens naartoe verwezen. Echter kom ik er niet uit hoe dit op te lossen.[size=9:2390c2e0a5][/size:2390c2e0a5]
  • De inhoud van de registers kun je inderdaad ook als argument meegeven. De functiedefinitie wordt dan[code:1:616720fe88]char leesRegister( char nummer, unsigned char* ddr )[/code:1:616720fe88]In dat geval hoeft de variabele ddr niet meer gedefineerd te worden, en ook niet meer geïnitialiseerd. Het defineren gebeurde in de eerste regel van de functie (na {), en het initialiseren was het commentaar in regel 3 van de functie.

    Als je een functie wilt gebruiken voordat je hem defineerd moet de compiler weten hoe de functie eruit ziet. Dit kan met de volgende regels boven de functie waarin de functies wordt gebruikt:[code:1:616720fe88]char leesOutput( char nummer, unsigned char* ddr );
    void schrijfOutput( char nummer, char waarde );[/code:1:616720fe88]
  • Heel erg bedankt voor je snelle reactie, er wordt echter nog een error weergegeven[code:1:51bb4935bf]main.c(72) E4062C: syntax error near `char'

    ddr = leesRegister( char nummer, unsigned char* ddr );[/code:1:51bb4935bf]En wat ik vreemd vind[code:1:51bb4935bf]leesoutput.c(3) W1101C: local declaration of `ddr' hides parameter
    leesoutput.c(1) W1021C: parameter `ddr' unused in function `leesOutput'

    char leesOutput( char nummer, unsigned char* ddr )
    {
    unsigned char ddr[4];
    char output = 0;[/code:1:51bb4935bf]Hij geeft hier een waarschuwing aan en vermeldt dat variabel ddr niet in 'leesOutput' wordt gebruikt
  • De regel[code:1:dc84b1e425]char leesOutput( char nummer, unsigned char* ddr )[/code:1:dc84b1e425]zegt iets over hoe de functie eruit zit. Er wordt een argument van type "char" verwacht (een laag nummer of karakter), en een argument van type unsigned char*. Dit is een pointer naar een "unsigned char", oftewel een laag positief getal of karakter. Een array is ook een pointer, en daar maak je hier gebruik van. Het resultaat van deze functie is weer van het type "char".

    Om de functie aan te roepen doe je het volgende:[code:1:dc84b1e425]char output1;
    output1 = leesRegister( 1, ddr );[/code:1:dc84b1e425]ddr moet dan natuurlijk al bestaan.

    Je bent ook vergeten een regel te verwijderen, wat de tweede fout veroorzaakt. Je moet de volgende regel verwijderen:[code:1:dc84b1e425]unsigned char ddr[4];[/code:1:dc84b1e425]Deze variabele wordt nu aan de functie meegegeven, dus hoeft hij niet meer apart gedefineerd te worden.
  • De volgende code[code:1:26589a5009]char output1;
    output1 = leesRegister( 1, ddr );[/code:1:26589a5009]heb ik onder het volgende stukje code geplaatst[code:1:26589a5009]ddr = leesRegister( char nummer, unsigned char* ddr );
    ddr &= ~mask;
    if( waarde )
    {
    ddr |= mask;
    schrijfRegister( Register, ddr );
    }[/code:1:26589a5009]Dit omdat ddr al een waarde moet hebben. Maar als ik dit doe wordt de volgende fout nog steeds weergegeven[code:1:26589a5009]main.c(61) E4062C: syntax error near `char'
    [/code:1:26589a5009]Zoals je begrijpt heb ik nog nooit eerder gewerkt met C, maar begin het nu meer en meer te snappen. Ik stel je hulp trouwens zeer op prijs
  • [quote:8a7a24fdb2="Lettin03"]De volgende code[code:1:8a7a24fdb2]char output1;
    output1 = leesRegister( 1, ddr );[/code:1:8a7a24fdb2]heb ik onder het volgende stukje code geplaatstddr = leesRegister( char nummer, unsigned char* ddr );[/quote:8a7a24fdb2]Die regel had niet [i:8a7a24fdb2]onder[/i:8a7a24fdb2] deze code gemoeten, maar [i:8a7a24fdb2]in plaats van[/i:8a7a24fdb2]. Laat ik even uitgaan van een programma met de volgende functies:[list:8a7a24fdb2][*:8a7a24fdb2]int main( int argc, char**argv); [*:8a7a24fdb2]char leesOutput( char nummer, unsigned char* ddr ); [*:8a7a24fdb2]void schrijfOutput( char nummer, char waarde, unsigned char* ddr ); [*:8a7a24fdb2]char leesRX( unsigned char* ddr );[/list:u:8a7a24fdb2] Voor de interaktie met de microcontroller moet je informatie kunnen lezen en kunnen schrijven. In de praktijk komt dat neer op het kunnen lezen en het kunnen schrijven van de registers. Omdat je de informatie van de functie meegeeft als argument aan leesRegister, moet die informatie dus in de functie main gelezen worden. Vervolgens geef je die infomatie door aan leesRegiter die de informatie interpreteerd. Ditzelfde geldt voor leesRX. In schrijfOutput moet je de registers veranderen (dat heb ik tenminste verondersteld). In veronderstel ook hier dat je een methode weet (die is afhankelijk van de microcontroller) hoe je die informatie wegschrijft. Ik denk dat het een goed idee is enkele C-tutorials door te nemen. Als je niet precies weet hoe en waarom bepaalde dingen werken, wordt het schrijven van een programma erg ingewikkeld.
  • Als leesRX heb ik tot dusver deze code, om verder gebruikt te worden in de Main[code:1:1b87d90cbe]char leesRX( unsigned char* ddr )
    {
    char input;
    input = ( ddr[ 3 ] >> 0 );
    return input;
    }[/code:1:1b87d90cbe]Bij de compilatie worden geen errors weergegeven, de 0 na >> bepaalt welke bit van register 3 als input wordt gezien of klopt dit niet?

    Over argumenten achter Main[code:1:1b87d90cbe]int main( int argc, char**argv)[/code:1:1b87d90cbe]kan ik weinig informatie over vinden op het net. Zijn deze argumenten gericht naar leesRegister, schrijfRegister en leesRX? Correct me if I am wrong.

    P.S: Ik ben al natuurlijk bezig met het bestuderen van tutorials, echter is er wenig te vinden over het direct aansturen van registers e.d.
  • [quote:31a7efc2fc="Lettin03"]Als leesRX heb ik tot dusver deze code, om verder gebruikt te worden in de Main[code:1:31a7efc2fc]char leesRX( unsigned char* ddr )
    {
    char input;
    input = ( ddr[ 3 ] >> 0 );
    return input;
    }[/code:1:31a7efc2fc]Bij de compilatie worden geen errors weergegeven, de 0 na >> bepaalt welke bit van register 3 als input wordt gezien of klopt dit niet?[/quote:31a7efc2fc]Dit klopt niet, maar je zit er niet ver naast.
    ddr[3] bevat de informatie van register 3. Het is dus van de vorm ? ? ? I ? ? ? ?, waarbij ? een bit is waarvan we de betekenis niet weten, en I de bit is die RX bevat.

    Om die I te krijgen moeten we twee akties doen. De eerste is alles 4 posities naar rechts schuiven. Dit kun je doen met [code:1:31a7efc2fc]ddr[3] >> 4[/code:1:31a7efc2fc]Wat overblijft is dan 0 0 0 0 ? ? ? I

    Maar dit is nog niet voldoende. Als één van de vraagtekens toevallig een 1 is, dan zou dit resultaat "waar" opleveren, en als I een "0" is zou deze functie "onwaar" terug moeten geven. Daarom moet op dit resultaat nog een bitsgewijze "en" gegepast worden, zodat alleen de meest rechter bit overblijft. Omdat de bits 00000001 het getal 1 vormen is dit de volgende code:[code:1:31a7efc2fc](ddr[3] >> 4) & 0x01[/code:1:31a7efc2fc][quote:31a7efc2fc="Lettin03"]Over argumenten achter Main[code:1:31a7efc2fc]int main( int argc, char**argv)[/code:1:31a7efc2fc]kan ik weinig informatie over vinden op het net. Zijn deze argumenten gericht naar leesRegister, schrijfRegister en leesRX? Correct me if I am wrong.

    P.S: Ik ben al natuurlijk bezig met het bestuderen van tutorials, echter is er wenig te vinden over het direct aansturen van registers e.d.[/quote:31a7efc2fc]De argumenten van main zijn altijd int argc, char** argv. Je hoeft deze argumenten niet persé te gebruiken. Deze argumenten heb je nodig als je wilt weten met welke parameters een functie wordt aangeroepen. De namen [i:31a7efc2fc]argc[/i:31a7efc2fc] en [i:31a7efc2fc]argv[/i:31a7efc2fc] zijn standaard, dus voor meer informatie hierover kun je op die twee namen zoeken.
  • Ik ben nu toe aan 'main'[code:1:258abb0260]int main( int argc, char**argv)
    {

    }[/code:1:258abb0260]Hoe ik het begrijp is dat in de 'main' alle functies[code:1:258abb0260]char leesOutput( char nummer, unsigned char* ddr )
    char leesRX( unsigned char* ddr )
    void schrijfOutput( char nummer, char waarde )[/code:1:258abb0260]geroepen moeten worden. En ik neem aan dat[code:1:258abb0260]output1 = leesRegister( 1, ddr );
    schrijfRegister( Register, ddr );[/code:1:258abb0260]ook in de 'main' gebruikt moeten worden. Worden deze functies in 'main' automatisch herkend?
  • [quote:a2047a1c64="Lettin03"]ook in de 'main' gebruikt moeten worden.[/quote:a2047a1c64]Dat klopt. [quote:a2047a1c64="Lettin03"]Worden deze functies in 'main' automatisch herkend?[/quote:a2047a1c64]Het ligt eraan waar je de functies hebt staan. Als de functies in het programma boven "main" zijn, dan worden ze automatisch herkent. De compiler weet dan al wat "leesRX" betekent.

    Als die functies na de functie main staan, dan moet je van tevoren melden hoe deze functies eruit gaan zien. Dit doe je op de volgende manier:[code:1:a2047a1c64]char leesOutput( char nummer, unsigned char* ddr );
    char leesRX( unsigned char* ddr );
    void schrijfOutput( char nummer, char waarde );

    int main( int argc, char **argv )
    {
    }[/code:1:a2047a1c64]
  • Ik zoek tevergeefs naar hoe 'main' van start moet gaan. Heb je misschien een link? Ik wil bij het activeren van de microcontroller (inschakelen) dat output 1 automatisch is geactiveerd en dan vervolgens de cyclus doorloopt. Heb jij misschien een idee hoe de 'main' dan van start moet gaan?
  • [quote:2e8a25bd72="Lettin03"]Ik zoek tevergeefs naar hoe 'main' van start moet gaan. Heb je misschien een link? Ik wil bij het activeren van de microcontroller (inschakelen) dat output 1 automatisch is geactiveerd en dan vervolgens de cyclus doorloopt. Heb jij misschien een idee hoe de 'main' dan van start moet gaan?[/quote:2e8a25bd72]main wordt gestart op het moment dat het programma gestart wordt.

    In dit geval ligt het voor de hand het programma te starten bij het opstarten van de computer / bij het inloggen. Daardoor is het programma al aktief op het moment dat de output verandert. De verandering in de output kun je nagaan door deze vaak genoeg te controleren (maar niet te vaak, want daar wordt de computer zo traag van). Concreet betekent dit dat main moet 'beginnen' met een while-lus zoals die enkele berichten terug genoemd.

Beantwoord deze vraag

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.