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


von SG (Gast)


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:
------------
1
#define LCD_DC            7  // LCD: Data/!Command, Pegel: LOW für Befehl (command) oder HIGH für Daten (data)
2
const boolean ISCMD=  LOW;   // Wird an das LCD gesendet muß eingestellt werden, ob es Daten oder Befehle sind, siehe LCD_DC.
3
const boolean ISDATA= HIGH;  // dito
4
5
digitalWrite(LCD_DC, ISCMD);  // Die folgenden Daten werden als Befehl/Kommando interpretiert (Einstellung des LCD)
C:
--
1
#define LCD_DC          PD7  // LCD: Data/!Command, Pegel: LOW für Befehl (command) oder HIGH für Daten (data)
2
#define LCD_DC_PORT   PORTD  // Diese Zeile will ich einsparen [1]
3
4
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 User
von SG (Gast)


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

von Beo Bachta (Gast)


Lesenswert?

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

von M.K. B. (mkbit)


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.

von Wolfgang (Gast)


Lesenswert?

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

Dann verwende doch digitalWriteFast()

von Joachim B. (jar)


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

von SG (Gast)


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:
1
pinMode(LCD_DC, OUTPUT);         // Ausgang zuweisen

C:
1
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

von yesitsme (Gast)


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

von SG (Gast)


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

von Joachim B. (jar)


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);


1
#ifndef _PINS_H_
2
#define _PINS_H_
3
4
#if defined(__AVR_ATmega328P__)
5
#define COUNTER1
6
7
#ifdef COUNTER1
8
  #define   TIMSKx              TIMSK1
9
  #define   OCIExA              OCIE1A
10
  #define   TIMERx_COMPA_vect   TIMER1_COMPA_vect  // ATmega
11
  #define   TCCRxA              TCCR1A
12
  #define   COMxA0              COM1A0
13
  #define   OCRxA               OCR1A
14
  #define   TCCRxB              TCCR1B
15
  #define   WGMx2               WGM12
16
  #define   CSx0                CS10
17
#endif
18
19
  #define LED_ARDUINO           5
20
  #define LED_ARDUINO_DDR       DDRB
21
  #define LED_ARDUINO_PORT      PORTB
22
23
  // arduino nano v3
24
  // DIGITAL
25
  // (Reset)        PC6
26
  // D0 (Rx)        PD0
27
  // D1 (Tx)        PD1
28
  // D2 (Int0)      PD2
29
30
// Nokia 5110
31
// 8 GND
32
// 7 LIGHT
33
// 6 VCC
34
// 5 CLK
35
// 4 DIN
36
// 3 DC
37
// 2 CE
38
// 1 RST
39
40
  // D3 (Int1)      PD3
41
  // D4 (XCK/T0)    PD4
42
//LCD5110 myGLCD(CLK,DIN,DC,RST,CE);
43
  // D5 (T1)        PD5
44
  #define RST         5
45
  // D6 (AIN0)      PD6
46
  #define CE          6
47
  // D7 (AIN1)      PD7  
48
  #define DC          7
49
  // D8 (ICP1)      PB0
50
  #define DIN 8
51
  // D9 (OC1A)      PB1 (PWM)
52
  #define CLK 9
53
  // D10(SS/OC1B)   PB2 (PWM)
54
  #define VCC 10
55
  // D11(MOSI/OC2)  PB3 (PWM)
56
  #define BL  11
57
  // D12(MISO)      PB4
58
  #define GND 12
59
  // D13(SCK)       PB5 (LED)
60
#endif // _PINS_H_
1
#include <LCD5110_Basic.h>
2
#include "pins.h"
3
4
  void myGLCD_init(void)
5
  { // ----- section LCD ------
6
#ifdef VCC
7
    pinMode(VCC, OUTPUT); // pin number on Arduino Uno Board    
8
    digitalWrite(VCC, HIGH);
9
#endif // #ifdef VCC
10
#ifdef GND
11
    pinMode(GND, OUTPUT); // pin number on Arduino Uno Board    
12
    digitalWrite(GND, LOW);
13
#endif //#ifdef GND
14
    myGLCDflags|=(1<<MY_GLCD);
15
    myGLCD.InitLCD();
16
    myGLCD.setFont(SmallFont);
17
    myGLCD.setContrast(MY_EEP_VAR.contra);
18
    myGLCD.clrScr();
19
    // ----- PWM LCD BL ----
20
    pinMode(BL, OUTPUT); // pin number on Arduino Uno Board    
21
    analogWrite(BL, pgm_read_byte(&pwmtable_11C[MY_EEP_VAR.backlicht]));   
22
    CLRSCREEN;
23
    con_hell_stat(false);
24
  } // void myGLCD_init(void)
25
26
27
  void con_p(void)
28
  { if(MY_EEP_VAR.contra<MAX_KONTRAST)
29
    { myGLCD.setContrast(++MY_EEP_VAR.contra);
30
      con_hell_stat(true);
31
      DEBUG_PRINT(F("contrast=")); DEBUG_PRINTLN(MY_EEP_VAR.contra);
32
    }
33
  } // void con_p(void)
34
  void con_m(void)
35
  { if(MY_EEP_VAR.contra>MIN_KONTRAST)
36
    { myGLCD.setContrast(--MY_EEP_VAR.contra);
37
      con_hell_stat(true);
38
      DEBUG_PRINT(F("contrast=")); DEBUG_PRINTLN(MY_EEP_VAR.contra);
39
    }
40
  } // void con_m(void)
41
  
42
  void backlight_p(void)
43
  { if(MY_EEP_VAR.backlicht<MAX_BL)
44
    { analogWrite(BL, pgm_read_byte(&pwmtable_11C[++MY_EEP_VAR.backlicht]));   
45
      con_hell_stat(true);
46
      DEBUG_PRINT(F("backlight=")); DEBUG_PRINTLN(MY_EEP_VAR.backlicht);
47
   }
48
  } // void backlight_p(void)
49
  void backlight_m(void)
50
  { if(MY_EEP_VAR.backlicht>MIN_BL)
51
    { analogWrite(BL, pgm_read_byte(&pwmtable_11C[--MY_EEP_VAR.backlicht]));   
52
      con_hell_stat(true);
53
      DEBUG_PRINT(F("backlight=")); DEBUG_PRINTLN(MY_EEP_VAR.backlicht);
54
    }
55
  } // void backlight_m(void)
56
  
57
  void con_hell_stat(boolean zueep)
58
  { sprintf_P(s_out_str, PSTR("con=%02d hell=%02d"), MY_EEP_VAR.contra, MY_EEP_VAR.backlicht);
59
    myGLCD.print(s_out_str, LEFT, COHE_LINE);
60
    if(zueep)
61
    { my_i2c_eeprom_wait_ready();
62
      my_i2c_eeprom_write_buffer( sizeof(jar_str), (char*)&MY_EEP_VAR, sizeof(MY_EEP_VAR) );   
63
      Serial.println(s_out_str);
64
      Serial.println(F("EEP_W"));
65
    }
66
  } // void con_hell_stat(boolean)

von Carl D. (jcw2)


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.

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.