mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik u8g2 lib - SSD1309 mit Hardware-SPI aber ohne Arduino?


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: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo U8G2 Anwender ;)

ich komme leider irgendwie mit der Doku dieser ansonsten mega 
hilfreichen Bibliothek U8G2 nicht weiter.

Ich habe hier ein Electronic Assembly OLEDL128-6 Display mit SSD1309 
Controller. Dazu habe ich mir ausßerdem die aktuellste Version der U8G2 
Bibliothek heruntergeladen und versuche nun, "die tollsten Sachen" damit 
zu machen ;)

An und für sich komme ich damit gut zurecht und ich kann das Display im 
Software-SPI Modus mit meinem Atmega2560 prima ansteuern.

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <u8g2.h>

#define DISPLAY_CLK_DIR DDRK
#define DISPLAY_CLK_PORT PORTK
#define DISPLAY_CLK_PIN PK0

#define DISPLAY_DATA_DIR DDRK
#define DISPLAY_DATA_PORT PORTK
#define DISPLAY_DATA_PIN PK1

#define DISPLAY_CS_DIR DDRK
#define DISPLAY_CS_PORT PORTK
#define DISPLAY_CS_PIN PK3

#define DISPLAY_DC_DIR DDRK
#define DISPLAY_DC_PORT PORTK
#define DISPLAY_DC_PIN PK4

#define DISPLAY_RESET_DIR DDRK
#define DISPLAY_RESET_PORT PORTK
#define DISPLAY_RESET_PIN PK2

u8g2_t u8g2;

uint8_t u8x8_avr_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t cycles;

  switch(msg)
  {
    case U8X8_MSG_DELAY_NANO:     // delay arg_int * 1 nano second
      // At 20Mhz, each cycle is 50ns, the call itself is slower.
      break;
    case U8X8_MSG_DELAY_100NANO:    // delay arg_int * 100 nano seconds
      // Approximate best case values...
#define CALL_CYCLES 26UL
#define CALC_CYCLES 4UL
#define RETURN_CYCLES 4UL
#define CYCLES_PER_LOOP 4UL

      cycles = (100UL * arg_int) / (P_CPU_NS * CYCLES_PER_LOOP);

      if(cycles > CALL_CYCLES + RETURN_CYCLES + CALC_CYCLES) 
        break;

      __asm__ __volatile__ (
      "1: sbiw %0,1" "\n\t" // 2 cycles
      "brne 1b" : "=w" (cycles) : "0" (cycles) // 2 cycles
      );
      break;
    case U8X8_MSG_DELAY_10MICRO:    // delay arg_int * 10 micro seconds
      for(int i=0 ; i < arg_int ; i++)
        _delay_us(10);
      break;
    case U8X8_MSG_DELAY_MILLI:      // delay arg_int * 1 milli second
      for(int i=0 ; i < arg_int ; i++)
        _delay_ms(1);
      break;
    default:
      return 0;
  }
  return 1;
}

uint8_t u8x8_avr_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  // Re-use library for delays

  switch(msg)
  {
    case U8X8_MSG_GPIO_AND_DELAY_INIT:  // called once during init phase of u8g2/u8x8
      DISPLAY_CLK_DIR |= 1<<DISPLAY_CLK_PIN;
      DISPLAY_DATA_DIR |= 1<<DISPLAY_DATA_PIN;
      DISPLAY_CS_DIR |= 1<<DISPLAY_CS_PIN;
      DISPLAY_DC_DIR |= 1<<DISPLAY_DC_PIN;
      DISPLAY_RESET_DIR |= 1<<DISPLAY_RESET_PIN;
      break;              // can be used to setup pins
    case U8X8_MSG_GPIO_SPI_CLOCK:        // Clock pin: Output level in arg_int
      if(arg_int)
        DISPLAY_CLK_PORT |= (1<<DISPLAY_CLK_PIN);
      else
        DISPLAY_CLK_PORT &= ~(1<<DISPLAY_CLK_PIN);
      break;
    case U8X8_MSG_GPIO_SPI_DATA:        // MOSI pin: Output level in arg_int
      if(arg_int)
        DISPLAY_DATA_PORT |= (1<<DISPLAY_DATA_PIN);
      else
        DISPLAY_DATA_PORT &= ~(1<<DISPLAY_DATA_PIN);
      break;
    case U8X8_MSG_GPIO_CS:        // CS (chip select) pin: Output level in arg_int
      if(arg_int)
        DISPLAY_CS_PORT |= (1<<DISPLAY_CS_PIN);
      else
        DISPLAY_CS_PORT &= ~(1<<DISPLAY_CS_PIN);
      break;
    case U8X8_MSG_GPIO_DC:        // DC (data/cmd, A0, register select) pin: Output level in arg_int
      if(arg_int)
        DISPLAY_DC_PORT |= (1<<DISPLAY_DC_PIN);
      else
        DISPLAY_DC_PORT &= ~(1<<DISPLAY_DC_PIN);
      break;
    
    case U8X8_MSG_GPIO_RESET:     // Reset pin: Output level in arg_int
      if(arg_int)
        DISPLAY_RESET_PORT |= (1<<DISPLAY_RESET_PIN);
      else
        DISPLAY_RESET_PORT &= ~(1<<DISPLAY_RESET_PIN);
      break;
    default:
      if (u8x8_avr_delay(u8x8, msg, arg_int, arg_ptr))  // check for any delay msgs
        return 1;
      u8x8_SetGPIOResult(u8x8, 1);      // default return value
      break;
  }
  return 1;
}



void main(void) {

  u8g2_Setup_ssd1309_128x64_noname0_f(&u8g2, U8G2_R2, u8x8_byte_4wire_sw_spi, u8x8_avr_gpio_and_delay);      
  u8g2_InitDisplay(&u8g2);
  u8g2_SetPowerSave(&u8g2, 0);
  u8g2_SetContrast(&u8g2, 128);

  u8g2_ClearBuffer(&u8g2);
  u8g2_SetFont(&u8g2, u8g2_font_5x7_tf);
  u8g2_DrawStr(&u8g2, 121, 59, "Hallo Welt!");
  u8g2_SendBuffer(&u8g2);

  while(1) {
  }

}

Soweit, so minimal.

Das Display wird somit im 4-wire Software-SPI Modus betrieben.

Nun würde ich das aber gerne mit dem Hardware-SPI des Atmega2560 
betreiben.
In der U8G2 Doku findet man C++/Arduino Beispiele, in denen das gemacht 
wird.

Aber im C-Teil der Doku finde dahingehend nix. Heisst das jetzt, das man 
Hardware-SPI nur in der Arduino Umgebung konfigurieren und nutzen kann?

In der oben gezeigten Konfiguration ist das Display wirklich 
fürchterlich langsam. Meine Hoffnung war, dass es mit Hardware-SPI 
schneller läuft.

Kann mir hier jemand auf die Sprünge helfen?
Hat jemand schonmal die U8G2 lib mit einem SSD1309 Controller verwendet?

Vielen Dank vorab ;)

LG, Manni

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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.