- Labornetzteil AliExpress         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Übergabe von Buchstaben an Unterfunktionen

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    21.10.2005
    Beiträge
    165

    Übergabe von Buchstaben an Unterfunktionen

    Anzeige

    Praxistest und DIY Projekte
    Hallo allesamt =)
    Ich bringe auf meinem RN-Contro aktuell über dieses Programm eine LED zum blinken. *Sagt jetzt nichts wegen der Zählschleifen, die sind nur testweise...*

    Code:
    #include <avr/io.h>
    
    
    
    int main(void)
    	{
    	//Initialisierungsphase
    	unsigned long counter;
    	
    	DDRC = 0x10;	//set PORTC for output
    	
    	while(1)
    		{
    		setpout(2,4,1);
    		
    		//wait
    		counter = 0;
    		while(counter < 160000000)
    			{
    			counter++;
    			}
    
    		setpout(2,4,0);
    		
    		//wait
    		counter = 0;
    		while(counter < 160000000)
    			{
    			counter++;
    			}
    		}
    	
    	return 1;
    	}
    
    
    
    int setpout(int p, int n, int io)
    	{
    	if(p == 0) {PORTA = io<<n;}	//set PORTA.n high oder low
    	if(p == 1) {PORTB = io<<n;}	//set PORTB.n high oder low
    	if(p == 2) {PORTC = io<<n;}	//set PORTC.n high oder low
    	if(p == 3) {PORTD = io<<n;}	//set PORTC.n high oder low
    	return 0;
    	}


    Das ganze soll mal mit etlichen Unterroutinen so eine Art "Betriebssystem" für das Board werden, damit ich nich jeden scheiß ständig direkt einstellen muss. Gut, fällt bei den Digitalports nu nich so auf, aber man muss ja klein anfangen... Ich möchte gerne der Funktion "setpout" als erstes ("p") anstelle der Zahl einen Buchstaben übergeben, der den jeweiligen Port kennzeichnet. Also die Form "setpout(port,stelle,wert)". Damit könnte ich mir dann die if-Abfragen sparen.

    Frage: wie geht das? Hab fleißig Google, die RN-Wiki und diverse andere Seiten gequält, aber irgendwie wurde ich daraus nicht recht schlau :-/

    Wäre für etwas Hilfe dankbar


    Gruß
    Corone

    Ach ja, so am Rande... ich habe immer "PORTX = y<<z;" geschrieben. In Beispielen fand ich aber immer anstelle des einfachen =Zeichens |= bzw &= und statt ner "0" für "aus" so was wie "~(1<<z)". Warum? Welchen Sinn hat das? Hat es irgend einen Nachteil, so wie ich gleich mit "bla = 0;" zu arbeiten?

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    Wie so ein Buchstabe dir die If's er sparen können ?

    Auch wenn du den Buchstabe übergibst ändert das nicht's an de Case oder If strucktur. Den PORTB ist ein Synonym einer Adresse und wird nicht Zur lauf zeit sonder zur Compeliert Zeit Interpretiert. Also falls du dir vorgestellt hast das du durch Buchstaben den Port namen zusammen bauen kannst vergiss es dan geht nicht.

    PORTA für den AMGEA 16 heist
    #define PORTA _SFR_IO8(0x1B)

    Ich hoffe das es dir hilft.

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.04.2004
    Ort
    München
    Alter
    36
    Beiträge
    288
    Also wenn du PORTX|=(1<<PXY) verwendest setzt du NUR das Y-te Bit im PORTX auf 1 alle anderen Bits in PORTX bleiben wie sie sind.
    Bei deiner Methode PORTX=1 (oder was auch immer) werden alle Bits gesetzt und eventuelle andere Pinzustände überschrieben.

    Wenn du es dir einfacher machen willst könntest du das mit den Ouptupins auch so machen:

    #define OutputA1 DDRA|=(1<<PA1)

    dann musst du um PA1 zum output zu machen nur noch OutputA1; schrieben.
    Wenn du das jetzt durchziehst und für alle Pins das machst (scheis viel Arbeit und vlt umständlich) dann kannst dus einfacher haben

    Ansonsten schließ ich mich NumberFive an, dass du nämlich PORTA nicht aus PORT und A zusammensetzen kannst.

    Grüße Javik
    Beschreibung meiner 8 Roboter unter: http://www.j-robotics.de

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Wenn du das wirklich so machen willst, dann ginge es so:
    Code:
    void set_port (const char port, const uint8_t pad)
    {
        if ('A' == port)
        {
            PORTA |= (1 << pad);
        }
        if ('B' == port)
        {
            PORTB |= (1 << pad);
        }
    }
    Das würde zunächst dazu führen, daß das Portsetzen recht lange dauert.

    Anstatt diese Funktion in ein C-Modul zu schreiben, könntest du sie in den entsprechenden Header tun und die Funktion als
    Code:
    static inline set_port (const char, const uint8_t);
    oder
    Code:
    static set_port (const char, const uint8_t) __attribute__((always_inline));
    deklarieren. Dann weiß GCC schon zur Compilezeit, wie die Werte in der Funktion sind und optimiert das bis nur noch eine Maschineninstruktion da steht.

    Aber was hat es für ein Vorteil, set_port ('A', 7) zu schreiben anstatt PORTA |= (1 << 7)

    Ich selbst benutze allerdings auch Port-Support Makros, die Code folgender Gestalt erlauben:
    Code:
    // irgendwo in "ports.h"
    #define PORT_LED    PORTB_6
    #define PORT_TASTER PORTC_1
    
    // irgendwo in "module.c"
    
    // LED anschalten
    MAKE_OUT (PORT_LED);
    SET (PORT_LED);
    
    // Taster ist IN + PullUp
    MAKE_IN (PORT_TASTER);
    SET (PORT_TASTER);
    
    if (IS_SET (PORT_TASTER)) ...
    Das erlaubt eine zentrale Port-Definition und man muss nicht PORTx, PINx, DDRx anpassen, wenn man was an der Schaltung ändert.

    Die gcc-Optimierungen führen dazu, daß die riesigen Makros zu einer einzigen Maschineninstruktion kollabieren -- ganz wichtig, weil das Setzen/Löschen von Ports ATOMAR sein muss!

    Zudem muss der Port nicht physikalisch sein, sondern es kann auch ein virtueller Port sein (also zB einer, der im RAM abgebildet ist und über Kommunikation mit einem Portexpander gelesen/geschrieben wird).

    Die Makros sind allerding nicht schön. Zudem müssen die Ports zur Compilezeit bekannt sein, in einer lib funktioniert des Ansatz also nicht.
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    21.10.2005
    Beiträge
    165
    gut, danke

    das hilft mir weiter. *jetz dann auch gleich delay-loops einbaut*






    ach ja... immer, wenn ich in Programmers Notepad 2 das Program-Tool aufrufe, kommt das hier:
    Code:
    > "make.exe" program
    avrdude -p atmega32 -P lpt1 -c stk200    -U flash:w:RNControl-Test.hex -U eeprom:w:RNControl-Test.eep
    avrdude: can't open device "giveio"
    
    avrdude: failed to open parallel port "lpt1"
    
    make.exe: *** [program] Error 1
    
    > Process Exit Code: 2
    > Time Taken: 00:00
    Compilieren funzt hingegen einwandfrei. Ich übertrage die Hex-Files derzeit immer per PonyProg... dort bekomme ich aber auch jedes mal ne Meldung "Falsches oder fehlendes Device (-24)"... wenn ich da dann auf "Ignorieren" klicke flasht er trotzdem ohne Probleme.
    Ich verwende das Kabel von robotikhardware.de, im makefile habe ich den stk200 als Programmer eingestellt. Weiss jemand, woran das leigen könnte? *gerne direkt von PN2 aus arbeiten würde*



    Gruß
    Corone

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.04.2004
    Ort
    München
    Alter
    36
    Beiträge
    288
    Also wenn du von PN2 aus Ponyprog starten willst um den µC zu proggen hab ich da was für dein Makefile :

    Code:
    ISPEXE = C:\.....\PonyProg2000\PONYPROG2000.EXE
    
    isp: $(TARGET).hex 
    	echo -e "SELECTDEVICE $(MCU)\nLOAD-PROG $(TARGET).hex\nWRITE-PROG" >isp.e2s
    	$(ISPEXE) isp.e2s
    	
    eeprom: $(TARGET).eep
    	echo -e "SELECTDEVICE $(MCU)\nLOAD-DATA $(TARGET).hex\nWRITE&VERIFY-DATA" >isp.e2s
    	$(ISPEXE) eeprom.e2s
    Einfach einfügen und noch den Pfad auf deine Installation von Ponyprog2000 einstellen und du kannst durch das Ausführen von "isp" den µC programmieren oder per "eeprom" das Eeprom mit deinen im Eeprom abgelegten Variablen flaschen.

    Das Ausführen machst du so wie du es auch für "make all" gemacht hast nur das du eben als Parameter nun "isp" bzw "eeprom" eingibst.
    Wenn du "isp" ausführst compiliert der Kompiler automatisch das Programm erstellt die Hex Datei und startet dann Ponyprog2000 welches deinen µC flasht und sich dann wieder automatisch schliest EXTREM nützlich
    Ich find auch die schnelltastenbelegung sehr nützlich
    wenn noch Fragen sin stell sie
    Beschreibung meiner 8 Roboter unter: http://www.j-robotics.de

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    21.10.2005
    Beiträge
    165
    ok... habe in http://winavr.sourceforge.net/install_config_WinAVR.pdf die antwort gefunden. hatte nich gewusst, dass man das teil erst installieren muss

    hab jetzt ne verbesserte version meines blinkprogrammes geschrieben, enthält delay-loops und ne eigene header-datei, die ich schrittweise ausbauen werde. schaut euch das zeug bitte mal an... irgendwo fehler drin? will möglichst standard-gerecht bleiben, damit der kram auch läuft


    Code:
    //rncontrol.h
    static inline void setpout(const char p, const uint8_t n, const uint8_t io)
    	{
    	if(p == 'A') {PORTA = io<<n;}	//set PORTA.n high oder low
    	if(p == 'B') {PORTB = io<<n;}	//set PORTB.n high oder low
    	if(p == 'C') {PORTC = io<<n;}	//set PORTC.n high oder low
    	if(p == 'D') {PORTD = io<<n;}	//set PORTC.n high oder low
    	}
    
    
    
    //RNControl-Test.c
    #include <avr/io.h>
    #include <avr/delay.h>
    #include <rncontrol.h>
    
    
    
    int main(void)
    	{
    	//Initialisierungsphase
    	unsigned int counter;
    	
    	DDRC |= 0x10;	//set PORTC.4 for output
    	
    	while(1)
    		{
    		setpout('C',4,1);
    		
    		//wait 16*65536
    		counter = 0;
    		while(counter < 16)
    			{
    			counter++;
    			_delay_loop_2(65535);
    			}
    
    		setpout('C',4,0);
    		
    		//wait
    		counter = 0;
    		while(counter < 16)
    			{
    			counter++;
    			_delay_loop_2(65535);
    			}
    			
    		}
    	return 1;
    	}

    ach ja... aus "static inline set_port" habe ich "static inline void setpout" gemacht, weil der compiler sonst immer meckerte, ich hätte da keine rückgabe, obwohl das ne integerfunktion ist. ist das richtig so, wie ich es gemacht habe?

    vielen dank für eure hilfe!

    gruß
    corone

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Zu den Standards:

    Die { und } werden üblicherweise links ausgerichtet:
    Code:
    while (foo)
    {
        if (bar)
        {
            bazz();
        }
    }
    Macht dir und anderen das Quelle-Lesen einfacher.


    Um die C-Quelle Standard-konform zu halten, gibt es Optionen wie -ansi, -pedantic, -std=c99, -Wmissing-prototypes, -W, -Wall, ...

    Mit deinen Makros musst du darauf achten, daß die Werte zur Compilezeit bekannt sind. Ausserdem gibt es Grenzen, ab der eine Funktion als "wert sie zu inlinen" betrachtet wird. Wenn die Funktion (setpout) nicht geinlint wird, fällt sie u.U recht groß aus, weil die o.g. Optimierung nicht gemacht werden kann. Sind die Werte zur Compilezeit nicht bekannt, bläht das den Code auf.
    Inlining erzwingen kannst mit dem o.g. Attribut. Anwarnen, wenn Inlining nicht klappt mit -Winline oder so. Musst eben bei dem gcc-Schaltern schauen.
    Disclaimer: none. Sue me.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    21.10.2005
    Beiträge
    165
    gut, danke dir *das mit der ausrichtung mal ändern wird*

    sonst irgendwelche fehler drin oder optimierungsvorschläge vorhanden?

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Ja.

    setpout tut nicht das, was du willst.

    Eine Port wird HIGH gesetzt durch
    Code:
    PORTx |= (1 << pad);
    und low gesetzt durch
    Code:
    PORTx &= ~(1 << pad);
    Dein setpout setzt zwar den gewünschten Port wie du willst, aber alle anderen Ports des PORT-Registers auf LOW.

    Wie ein BSP (board support package) aussehen könnte wird dir vielleicht klarer, wenn du ein paar kleine, funktionierende Projekte gemacht hast und siehst, was die brauchen und welche Anforderungen sie an ein BSP stellen würden.

    Da das BSP in unterschiedlichen Prokejten zum Einsatz kommen soll, musst du schon sehr genau überlegen, wie du es implementierst. weil es nicht so toll ist, das BSP nachträglich zu ändern weil du zB das Interface ändern musst und inkompatibel zu älteren Versionen wirst. Daher der Vorschlag, erst mal ein paar Erfahrungen aus der Praxis zu sammeln.

    Zudem musst du dir überlegen, ob du das BSP als Quellarchiv oder als Bibliothek zur Verfügung stellen willst. Mach dir dazu die Unterschiede/Schwächen/Stärken der beiden Lösungen klar.
    Disclaimer: none. Sue me.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen