mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Arduino digitalWrite durch C-Code ersetzen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: SG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich lerne gerade Arduinos und C und verwende im Projekt ein LCDisplay 
Nokia 5110 mit PCD8544 Controller, siehe:
http://www.rinkydinkelectronics.com/images/libpics/L0044P001313163463.png

Nun will ich die Arduino-Befehle (z. B. digitalWrite()) durch 
C-Programmierung ersetzen, die wesentlich schneller sind. Dabei entsteht 
leider ein Problem mit der Definition/Festlegung der Pinzuweisung.

Arduino IDE:
------------
#define LCD_DC            7  // LCD: Data/!Command, Pegel: LOW für Befehl (command) oder HIGH für Daten (data)
const boolean ISCMD=  LOW;   // Wird an das LCD gesendet muß eingestellt werden, ob es Daten oder Befehle sind, siehe LCD_DC.
const boolean ISDATA= HIGH;  // dito

digitalWrite(LCD_DC, ISCMD);  // Die folgenden Daten werden als Befehl/Kommando interpretiert (Einstellung des LCD)

C:
--
#define LCD_DC          PD7  // LCD: Data/!Command, Pegel: LOW für Befehl (command) oder HIGH für Daten (data)
#define LCD_DC_PORT   PORTD  // Diese Zeile will ich einsparen [1]

LCD_DC_PORT &= ~(1<<LCD_DC);  // statt digitalWrite(LCD_DC, ISCMD);
Wenn ich jetzt den Pin wechsle (z. B. PB3 statt PD7) und die zweite 
Zeile übersehe und vergesse PORTD in PORTB zu ändern meckert der 
Compiler nicht und ich wundere mich, daß das nicht funktioniert.

[1]: Gibt es eine Möglichkeit den C-Befehl so zu implementieren, daß die 
Zeile mit der Port-Festlegung entfallen kann?

Folgenes habe ich gefunden, was vielleicht eine Lösungsweg mit sbi und 
cbi eröffnet hätte:
"In Quellcodes, die für ältere Version den des avr-gcc/der avr-libc 
entwickelt wurden, werden einzelne Bits mittels der Funktionen sbi und 
cbi gesetzt bzw. gelöscht. Beide Funktionen sind nicht mehr 
erforderlich."
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten

Grüße an Alle, die mir helfen. ;-)
SG

: Bearbeitet durch Moderator
Autor: SG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, ich bin versehentlich auf Absenden gekommen.
Da wollte ich noch den Code als Code markieren...

Vielleicht kann ein Moderator den Betreff korrigieren:
   Arduino digitalWrite durch C-Code ersetzen

SG

Autor: Beo Bachta (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst auch den Teil umsetzen der in der Arduino-Source
die Port-Pins auf Output stellt.

Autor: M.K. B. (mkbit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht in wie weit dir klar ist, was du in der Hardware genau 
austeuerst. Sagen dir Register und Registerbits etwas?
Arduino macht nämlich vermutlich noch mehr, wie Beo Bachta schon gesagt 
hat.

Die beiden defines in deinem Fall legen zwei verschiedene Sachen fest:

LCD_DC_PORT ist ein Register, dass an einer bestimmten Adresse steht und 
das verhalten eines Ports beeinflusst. Für den Compiler ist das im 
Prinzip eine integer Variable. Nur das Handbuch vom Controller sagt dir, 
was diese tut.

LCD_DC ist ein Index für ein Bit in diesem Register, dass gelöscht 
werden soll. Für den Compiler ist das ein Integerwert.

Wenn du nach der Deklaration von PORTD und PD7 suchst, dann findest du 
defines die das ganze umsetzen. Die defines gibt es auch nur, weil der 
Code dann besser lesbar ist, als mit den direkten Adressen zu arbeiten. 
Für den Compiler ist es aber einfach nur ein Integer und ein Wert, die 
in keinem Zusammenhang stehen. Deine Programmlogik und die Doku bringen 
den Zusammenhang.

Die einzige Möglichkeit es zu vereinfachen wäre das ganze in 
Hilfsfunktionen oder Hilfsklasse (dann bräuchte man z.B. C++) 
auszulagern. In deinem Fall bringt das aber nur was, wenn du das in 
mehreren Projekten verwendest, denn die Hilfsfunktion schreibt sich ja 
auch nicht von allein.

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SG schrieb:
> Nun will ich die Arduino-Befehle (z. B. digitalWrite()) durch
> C-Programmierung ersetzen, die wesentlich schneller sind.

Dann verwende doch digitalWriteFast()

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SG schrieb:
> Hallo.
>
> Ich lerne gerade Arduinos und C und verwende im Projekt ein LCDisplay
> Nokia 5110 mit PCD8544 Controller

ich sehe dein Problem nicht

geschicktes Setzen der Ports und alles ist kein Problem

https://www.mikrocontroller.net/attachment/325968/nanoFUNKalt.jpeg
https://www.mikrocontroller.net/attachment/366376/rolladensteuerung_web.jpg

Autor: SG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hinweise.

Beo Bachta schrieb:
> Du musst auch den Teil umsetzen der in der Arduino-Source die Port-Pins auf 
Output stellt.

Das ist das gleiche Problem, aber vielleicht für andere Mitleser 
interessant und zur Vollständigkeit aufgeführt:

Arduino IDE:
pinMode(LCD_DC, OUTPUT);         // Ausgang zuweisen

C:
LCD_DC_PORT |= (1<<LCD_DC);      // statt pinMode(LCD_DC, OUTPUT);

M.K. B. schrieb:
> Ich weiß nicht in wie weit dir klar ist, was du in der Hardware genau 
ansteuerst.
Sehr klar. Es läuft auch schon.

> Die beiden defines in deinem Fall legen zwei verschiedene Sachen fest ...
Auch das ist völlig klar.

Wie gesagt, ich bin nicht so versiert, daher meine Frage.
Ich will ja das Rad nicht neu erfinden...

Wolfgang schrieb:
> Dann verwende doch digitalWriteFast()

Habe ich mir gerade heruntergeladen und angesehen:
https://code.google.com/p/digitalwritefast/

Scheint wohl die Lösung zu sein.

Danke!
SG

Autor: yesitsme (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ich denke das digitalWrite() hauptsächlich durch den Lookup von Port und 
Bitmask langsam wird, der bei jedem Aufruf gemacht werden muss.

Wenn man viel IO machen muss, könnte man diesen Lookup in der init() 
machen.

Source von DigitalWrite(): 
https://github.com/arduino/ArduinoCore-avr/blob/3f63f2975e7183c3254b6794bfcc8f19ca0301c9/cores/arduino/wiring_digital.c#L138

Autor: SG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> ich sehe dein Problem nicht
>
> geschicktes Setzen der Ports und alles ist kein Problem

Und was ist Deine Lösung, wenn Du das Problem verstanden hättest?
Wenn Du das gleiche LCD ansteuerst, zeig doch mal Deinen (C-)Code.

>
> https://www.mikrocontroller.net/attachment/325968/...
> https://www.mikrocontroller.net/attachment/366376/...

Bilder lösen das Problem nicht.

Grüße
SG

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SG schrieb:
> Und was ist Deine Lösung, wenn Du das Problem verstanden hättest?
> Wenn Du das gleiche LCD ansteuerst, zeig doch mal Deinen (C-)Code.

ich leiste mir echt den Luxus die LIBs zu nutzen

ergo ist mein Code nicht sehr berauschend,
im wesentlichen um Verdrahtung zu sparen ein paar Pin #defines

an keiner Stelle brauche ich

pinMode(LCD_DC, OUTPUT);         // Ausgang zuweisen
LCD_DC_PORT |= (1<<LCD_DC);      // statt pinMode(LCD_DC, OUTPUT);


#ifndef _PINS_H_
#define _PINS_H_

#if defined(__AVR_ATmega328P__)
#define COUNTER1

#ifdef COUNTER1
  #define   TIMSKx              TIMSK1
  #define   OCIExA              OCIE1A
  #define   TIMERx_COMPA_vect   TIMER1_COMPA_vect  // ATmega
  #define   TCCRxA              TCCR1A
  #define   COMxA0              COM1A0
  #define   OCRxA               OCR1A
  #define   TCCRxB              TCCR1B
  #define   WGMx2               WGM12
  #define   CSx0                CS10
#endif

  #define LED_ARDUINO           5
  #define LED_ARDUINO_DDR       DDRB
  #define LED_ARDUINO_PORT      PORTB

  // arduino nano v3
  // DIGITAL
  // (Reset)        PC6
  // D0 (Rx)        PD0
  // D1 (Tx)        PD1
  // D2 (Int0)      PD2

// Nokia 5110
// 8 GND
// 7 LIGHT
// 6 VCC
// 5 CLK
// 4 DIN
// 3 DC
// 2 CE
// 1 RST

  // D3 (Int1)      PD3
  // D4 (XCK/T0)    PD4
//LCD5110 myGLCD(CLK,DIN,DC,RST,CE);
  // D5 (T1)        PD5
  #define RST         5
  // D6 (AIN0)      PD6
  #define CE          6
  // D7 (AIN1)      PD7  
  #define DC          7
  // D8 (ICP1)      PB0
  #define DIN 8
  // D9 (OC1A)      PB1 (PWM)
  #define CLK 9
  // D10(SS/OC1B)   PB2 (PWM)
  #define VCC 10
  // D11(MOSI/OC2)  PB3 (PWM)
  #define BL  11
  // D12(MISO)      PB4
  #define GND 12
  // D13(SCK)       PB5 (LED)
#endif // _PINS_H_ 
#include <LCD5110_Basic.h>
#include "pins.h"

  void myGLCD_init(void)
  { // ----- section LCD ------
#ifdef VCC
    pinMode(VCC, OUTPUT); // pin number on Arduino Uno Board    
    digitalWrite(VCC, HIGH);
#endif // #ifdef VCC
#ifdef GND
    pinMode(GND, OUTPUT); // pin number on Arduino Uno Board    
    digitalWrite(GND, LOW);
#endif //#ifdef GND
    myGLCDflags|=(1<<MY_GLCD);
    myGLCD.InitLCD();
    myGLCD.setFont(SmallFont);
    myGLCD.setContrast(MY_EEP_VAR.contra);
    myGLCD.clrScr();
    // ----- PWM LCD BL ----
    pinMode(BL, OUTPUT); // pin number on Arduino Uno Board    
    analogWrite(BL, pgm_read_byte(&pwmtable_11C[MY_EEP_VAR.backlicht]));   
    CLRSCREEN;
    con_hell_stat(false);
  } // void myGLCD_init(void)


  void con_p(void)
  { if(MY_EEP_VAR.contra<MAX_KONTRAST)
    { myGLCD.setContrast(++MY_EEP_VAR.contra);
      con_hell_stat(true);
      DEBUG_PRINT(F("contrast=")); DEBUG_PRINTLN(MY_EEP_VAR.contra);
    }
  } // void con_p(void)
  void con_m(void)
  { if(MY_EEP_VAR.contra>MIN_KONTRAST)
    { myGLCD.setContrast(--MY_EEP_VAR.contra);
      con_hell_stat(true);
      DEBUG_PRINT(F("contrast=")); DEBUG_PRINTLN(MY_EEP_VAR.contra);
    }
  } // void con_m(void)
  
  void backlight_p(void)
  { if(MY_EEP_VAR.backlicht<MAX_BL)
    { analogWrite(BL, pgm_read_byte(&pwmtable_11C[++MY_EEP_VAR.backlicht]));   
      con_hell_stat(true);
      DEBUG_PRINT(F("backlight=")); DEBUG_PRINTLN(MY_EEP_VAR.backlicht);
   }
  } // void backlight_p(void)
  void backlight_m(void)
  { if(MY_EEP_VAR.backlicht>MIN_BL)
    { analogWrite(BL, pgm_read_byte(&pwmtable_11C[--MY_EEP_VAR.backlicht]));   
      con_hell_stat(true);
      DEBUG_PRINT(F("backlight=")); DEBUG_PRINTLN(MY_EEP_VAR.backlicht);
    }
  } // void backlight_m(void)
  
  void con_hell_stat(boolean zueep)
  { sprintf_P(s_out_str, PSTR("con=%02d hell=%02d"), MY_EEP_VAR.contra, MY_EEP_VAR.backlicht);
    myGLCD.print(s_out_str, LEFT, COHE_LINE);
    if(zueep)
    { my_i2c_eeprom_wait_ready();
      my_i2c_eeprom_write_buffer( sizeof(jar_str), (char*)&MY_EEP_VAR, sizeof(MY_EEP_VAR) );   
      Serial.println(s_out_str);
      Serial.println(F("EEP_W"));
    }
  } // void con_hell_stat(boolean)


Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yesitsme schrieb:
> Ich denke das digitalWrite() hauptsächlich durch den Lookup von Port und
> Bitmask langsam wird, der bei jedem Aufruf gemacht werden muss.
>
> Wenn man viel IO machen muss, könnte man diesen Lookup in der init()
> machen.

Die beim Arduino benutzte Sprache kann das sogar beschreiben, daß es 
schon beim Übersetzen ein konstanter Ausdruck ist und damit schon vor 
dem Anlegen einer Betriebsspannung berechnet sein kann.

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.