Forum: Mikrocontroller und Digitale Elektronik SSD1306 clear buffer / display code


von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Hallo!

kann sich mal jemand ssd1306_display_clear() anschauen, ich bekomme es 
nicht hin das Display zu löschen. Der Rest funktioniert.

???

https://pastebin.com/vXEgC4bG

1
#include <string.h>
2
3
#include "freertos/FreeRTOS.h"
4
#include "freertos/task.h"
5
6
#include "driver/gpio.h"
7
#include "driver/i2c.h"
8
9
#include "esp_err.h"
10
#include "esp_log.h"
11
12
#include "ssd1366.h"
13
#include "font8x8_basic.h"
14
15
#define SDA_PIN GPIO_NUM_21
16
#define SCL_PIN GPIO_NUM_22
17
18
#define tag "ssd1306"
19
20
void i2c_master_init() {
21
22
  i2c_config_t i2c_config = {
23
24
    .mode = I2C_MODE_MASTER,
25
    .sda_io_num = SDA_PIN,
26
    .scl_io_num = SCL_PIN,
27
    .sda_pullup_en = GPIO_PULLUP_ENABLE,
28
    .scl_pullup_en = GPIO_PULLUP_ENABLE,
29
    .master.clk_speed = 1000000
30
  };
31
32
  i2c_param_config(I2C_NUM_0, &i2c_config);
33
  i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
34
}
35
36
void ssd1306_init() {
37
  esp_err_t espRc;
38
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
39
  i2c_master_start(cmd);
40
    i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
41
    i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
42
      i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP, true);
43
        i2c_master_write_byte(cmd, 0x14, true); // 0x14(enable)
44
      i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // reverse left-right mapping
45
      i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // reverse up-bottom mapping
46
    i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
47
  i2c_master_stop(cmd);
48
  espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
49
  if (espRc == ESP_OK) {
50
    ESP_LOGI(tag, "ssd1306_init successfully");
51
  } else {
52
    ESP_LOGE(tag, "ssd1306_init failed. code: 0x%.2X", espRc);
53
  }
54
  i2c_cmd_link_delete(cmd);
55
}
56
57
void ssd1306_display_clear(void) {
58
  i2c_cmd_handle_t cmd;
59
  uint8_t zero[128] = {0};
60
  for (uint8_t i = 0; i < 8; i++) {
61
    cmd = i2c_cmd_link_create();
62
    i2c_master_start(cmd);
63
      i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
64
      i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_SINGLE, true);
65
      i2c_master_write_byte(cmd, 0xB0 | i, true); // Set GDDRAM page start address
66
        i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
67
        i2c_master_write(cmd, zero, 128, true);
68
    i2c_master_stop(cmd);
69
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
70
    i2c_cmd_link_delete(cmd);
71
  }
72
}
73
74
void ssd1306_display_text(void *arg_text) {
75
  char *text = (char*)arg_text;
76
  uint8_t text_len = strlen(text);
77
  i2c_cmd_handle_t cmd;
78
  uint8_t cur_page = 0;
79
  cmd = i2c_cmd_link_create();
80
  i2c_master_start(cmd);
81
  i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
82
  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
83
  i2c_master_write_byte(cmd, 0x00, true); // reset column
84
  i2c_master_write_byte(cmd, 0x10, true);
85
  i2c_master_write_byte(cmd, 0xB0 | cur_page, true); // reset page
86
  i2c_master_stop(cmd);
87
  i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
88
  i2c_cmd_link_delete(cmd);
89
  for (uint8_t i = 0; i < text_len; i++) {
90
    if (text[i] == '\n') {
91
      cmd = i2c_cmd_link_create();
92
      i2c_master_start(cmd);
93
      i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
94
      i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
95
      i2c_master_write_byte(cmd, 0x00, true); // reset column
96
      i2c_master_write_byte(cmd, 0x10, true);
97
      i2c_master_write_byte(cmd, 0xB0 | ++cur_page, true); // increment page
98
      i2c_master_stop(cmd);
99
      i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
100
      i2c_cmd_link_delete(cmd);
101
    } else {
102
      cmd = i2c_cmd_link_create();
103
      i2c_master_start(cmd);
104
      i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
105
      i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
106
      i2c_master_write(cmd, font8x8_basic_tr[(uint8_t)text[i]], 8, true);
107
      i2c_master_stop(cmd);
108
      i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
109
      i2c_cmd_link_delete(cmd);
110
    }
111
  }
112
}
113
114
void app_main(void) {
115
  i2c_master_init();
116
  ssd1306_init();
117
  ssd1306_display_clear();
118
  ssd1306_display_text("ABCDEFGHIJKLMNOP");
119
}

von Doctor What (Gast)


Lesenswert?

W3ll S. schrieb:
> kann sich mal jemand ssd1306_display_clear() anschauen, ich bekomme es
> nicht hin das Display zu löschen. Der Rest funktioniert.


Kruder und ineffizienter Code. Was geht denn nicht bzw. wass passiert 
mit Deinem Code?

Ich würde den Horizontal Addressing Mode nutzen, dann kannst Du in einem 
durchschreiben. Geht schneller und spart Speicherplatz.

von M. K. (sylaina)


Lesenswert?

Ich hab das ganze so gelöst:
1
void lcd_clrscr(void){
2
    memset(displayBuffer, 0x00, sizeof(displayBuffer));
3
#if defined SSD1306
4
    lcd_data(displayBuffer, sizeof(displayBuffer));
5
#elif defined SH1106
6
    for (uint8_t i=0; i <= DISPLAY_HEIGHT/8; i++) {
7
        uint8_t actualLine[DISPLAY_WIDTH];
8
        for (uint8_t j=0; j< DISPLAY_WIDTH; j++) {
9
            actualLine[j]=displayBuffer[i*DISPLAY_WIDTH+j];
10
        }
11
        lcd_data(actualLine, sizeof(actualLine));
12
        lcd_gotoxy(0, i);
13
    }
14
#endif
15
    lcd_home(); // gotoxy(0,0)
16
}
17
...
18
void lcd_data(uint8_t data[], uint16_t size) {
19
    i2c_start(LCD_I2C_ADR);
20
    i2c_byte(0x40);  // 0x00 for command, 0x40 for data
21
    for (uint16_t i = 0; i<size; i++) {
22
        i2c_byte(data[i]);
23
    }
24
    i2c_stop();
25
}
Mein Library findest du unter:

https://github.com/Sylaina/oled-display/

Sie ist für Atmegas geschrieben, für andere µC müssen nur die 
I2C-Funktionen entsprechend umgeschrieben werden.

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Doctor What schrieb:
> W3ll S. schrieb:
>> kann sich mal jemand ssd1306_display_clear() anschauen, ich bekomme es
>> nicht hin das Display zu löschen. Der Rest funktioniert.
>
>
> Kruder und ineffizienter Code. Was geht denn nicht bzw. wass passiert
> mit Deinem Code?

Ja, er löscht nur unzuverlässig. Mal gehts, mal gehts nicht. Was meinst 
Du mit kruder Coder?


> Ich würde den Horizontal Addressing Mode nutzen, dann kannst Du in einem
> durchschreiben. Geht schneller und spart Speicherplatz.

Danke, das schau ich mir an!

von Stefan F. (Gast)


Lesenswert?

Meine funktionierende Prozedur sieht ein bisschen anders aus:
1
        i2c_start();
2
        i2c_send(i2c_address << 1);    // address + write
3
        i2c_send(0x00);                // command
4
        i2c_send(0xB0 + page);         // set page 0-7
5
        i2c_send(0x21);                // column address
6
        i2c_send(0x00);                // first column =0
7
        i2c_send(width - 1);           // last column (=127)
8
        i2c_stop();
9
10
        // send one page of buffer to the display
11
        i2c_start();
12
        i2c_send(i2c_address << 1);    // address + write
13
        i2c_send(0x40);                // data
14
15
        for (uint_fast8_t column = 0; column < width; column++)
16
        {
17
            i2c_send(buffer[index++]);
18
        }
19
20
        i2c_stop();

Das ganze wiederhole ich 8 mal für die 8 pages. Wobei mein Buffer ein 
komplettes Abbild des Display-SPeichers ist. Du könntest in der 
for-Schleife einfach 128 mal eine 0 senden, um das Display zu löschen.

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Stefan U. schrieb:

> for-Schleife einfach 128 mal eine 0 senden, um das Display zu löschen.

Hi Stefan, danke für deinen Code!

Das war mein Plan:

(I2C commands entfernt)
1
void ssd1306_display_clear(void) {
2
3
  uint8_t zero[128] = {0};
4
5
  for (uint8_t i = 0; i < 8; i++) {
6
7
    i2c_master_write_byte(cmd, 0x80, true); // OLED_CONTROL_BYTE_CMD_SINGLE
8
    i2c_master_write_byte(cmd, 0xB0 | i, true); // Set GDDRAM page start address
9
10
    i2c_master_write_byte(cmd, 0x00, true); // OLED_CONTROL_BYTE_CMD_STREAM
11
    i2c_master_write(cmd, zero, 128, true);
12
13
  }
14
15
}

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.