Forum: Mikrocontroller und Digitale Elektronik SSD1306 per SPI Bit-Banging am XMEGA


von Manu (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Ich versuche gerade eine OLED mit SSD1306 Controller mittels Bit-Banging 
an einem XMega 32A4U zum Laufen zu bekommen. Hardware SPI kann ich nicht 
nutzen, da das Display auf dem Board (XProtolab) fest verdrahtet ist (s. 
Bild).
Ich versuche seit Tagen, das Display zumindest an zu bekommen aber will 
einfach nicht klappen aber ich finde den Fehler nicht!
Der XMega läuft auf dem internen Osci mit 32 MHz. Hier mal mein Code zum 
Resetten des Displays und zum senden eines Bytes. In der Reset wird nur 
versucht, das Display anzuschalten (0xAF) und alle Pixel anzuschalten 
(0xA5).
Vielleicht seht ihr was, was ich nicht sehe. Ich bin auf jeden Fall für 
jeden Hinweis dankbar!

---------------------------------------------------------
1
#define F_CPU    32000000UL
2
// Chip Select
3
#define CS_EN    PORTB.OUTCLR = PIN0_bm
4
#define CS_DIS    PORTB.OUTCLR = PIN0_bm
5
// SDIN 
6
#define DATA_HI    PORTD.OUTSET = PIN3_bm
7
#define DATA_LOW  PORTD.OUTCLR = PIN3_bm
8
// Clock
9
#define CKL_HI    PORTD.OUTSET = PIN1_bm
10
#define CKL_LOW    PORTD.OUTCLR = PIN1_bm 
11
// Reset
12
#define RES_EN    PORTB.OUTCLR = PIN1_bm
13
#define RES_DIS    PORTB.OUTSET = PIN1_bm
14
// Data / Command
15
#define DC_HI    PORTB.OUTSET = PIN3_bm
16
#define DC_LOW    PORTB.OUTCLR = PIN3_bm
17
18
19
#include <avr/io.h>
20
#include <util/delay.h>
21
#include "display.h"
22
#include <avr/interrupt.h> 
23
24
void OLED_start()
25
{
26
  //cli();
27
  RES_EN;
28
  _delay_us(10);
29
  RES_DIS;
30
  DC_LOW;
31
  CS_DIS;
32
  CKL_LOW;
33
  _delay_us(100);
34
  //OLED_data(0xAE);
35
  OLED_data(0xAF);
36
  _delay_ms(150);  
37
  OLED_data(0xA5);
38
  //sei();
39
}
40
41
// transmit byte serially, MSB first
42
void OLED_data(unsigned char data)
43
{  
44
  int i;
45
46
  // select device
47
  CS_EN;
48
  // wait 62,5ns
49
  asm volatile ("nop");
50
  asm volatile ("nop");
51
  
52
  // send bits 7..0
53
  for (i = 0; i < 8; i++)
54
  {
55
    // consider leftmost bit
56
    // set line high if bit is 1, low if bit is 0
57
    if (data & 0x80)
58
    {
59
      DATA_HI;
60
    }
61
    else
62
    {
63
      DATA_LOW;
64
    }
65
    asm volatile ("nop");
66
    asm volatile ("nop");
67
    
68
    // pulse clock to indicate that bit value should be read
69
    CKL_HI;
70
    asm volatile ("nop"); // 31.25 nS
71
    asm volatile ("nop");
72
    CKL_LOW;
73
    asm volatile ("nop"); // 31.25 nS
74
    asm volatile ("nop");
75
    
76
    // shift byte left so next bit will be leftmost
77
    data <<= 1;
78
  }
79
  
80
  // deselect device
81
  CS_DIS;
82
  DATA_LOW;
83
}
---------------------------------------------------------

Gruß und Danke
Manu

von Manu (Gast)


Lesenswert?

PS: Die Pins sind in meiner main-File natürlich vorher als Output 
initialisiert!

Gruß
Manu

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

ist das
#define CS_EN    PORTB.OUTCLR = PIN0_bm
#define CS_DIS    PORTB.OUTCLR = PIN0_bm
jetzt ein 'Kopierfehler' ?

Sascha

von Manu (Gast)


Lesenswert?

Hallo,

Nein, das habe ich tatsächlich im Code übersehen!
Vielen Dank!
Leider möchte das Display trotzdem noch nicht :/

Gruß
Manu

von U8glib (Gast)


Lesenswert?

Anbei die Sequenz, die ich u.a. in U8glib verwende:
  U8G_ESC_CS(0),             /* disable chip */
  U8G_ESC_ADR(0),           /* instruction mode */
  U8G_ESC_RST(1),           /* do reset low pulse with (1*16)+2 
milliseconds */
  U8G_ESC_CS(1),             /* enable chip */

  0x0ae,        /* display off, sleep mode */
  0x0d5, 0x080,    /* clock divide ratio (0x00=1) and oscillator 
frequency (0x8) */
  0x0a8, 0x03f,    /* multiplex ratio */
  0x0d3, 0x000,    /* display offset */
  0x040,        /* start line */
  0x08d, 0x010,    /* charge pump setting (p62): 0x014 enable, 0x010 
disable */
  0x0a1,        /* segment remap a0/a1*/
  0x0c8,        /* c0: scan dir normal, c8: reverse */
  0x0da, 0x012,    /* com pin HW config, sequential com pin config (bit 
4), disable left/right remap (bit 5) */
  0x081, 0x09f,    /* set contrast control */
  0x0d9, 0x022,    /* pre-charge period */
  0x0db, 0x040,    /* vcomh deselect level */
  0x022, 0x000,    /* page addressing mode WRONG: 3 byte cmd! */
  0x0a4,        /* output ram to display */
  0x0a6,        /* none inverted normal display mode */
  0x0af,        /* display on */
  U8G_ESC_CS(0),             /* disable chip */
  U8G_ESC_END                /* end of sequence */


Soweit ich mich erinnere muss mindestens auch die charge pump activiert 
werden.

Oliver

von Manu (Gast)


Lesenswert?

Hi,

Und danke für den Hinweis!
Nachdem ich die Initialisierung mal komplett gemacht hab, geht es!
Hier der Code:
1
void OLED_start()
2
{
3
  //cli();
4
  RES_EN;
5
  _delay_us(10);
6
  RES_DIS;
7
  DC_LOW;
8
  CS_DIS;
9
  CKL_LOW;
10
  // Recommended intialization sequence
11
  OLED_data(LCD_DISP_OFF);
12
  OLED_data(LCD_SET_RATIO_OSC);
13
  OLED_data(0x80);
14
  OLED_data(LCD_MULTIPLEX);
15
  OLED_data(0x3F);
16
  OLED_data(LCD_SET_OFFSET);
17
  OLED_data(0x00);
18
  OLED_data(LCD_SET_LINE);
19
  OLED_data(LCD_CHARGE_PUMP);
20
  OLED_data(LCD_PUMP_ON);
21
  OLED_data(LCD_SET_SEG_REMAP1);
22
  OLED_data(LCD_SET_SCAN_NOR);
23
  OLED_data(LCD_SET_PADS);
24
  OLED_data(0x12);
25
  OLED_data(LCD_SET_CONTRAST);
26
  OLED_data(0xFF);
27
  OLED_data(LCD_SET_CHARGE);
28
  OLED_data(0xF1);
29
  OLED_data(LCD_SET_VCOM);
30
  OLED_data(0x40);
31
  OLED_data(LCD_EON_OFF);
32
  OLED_data(LCD_DISP_NOR);
33
  OLED_data(LCD_MEM_ADDRESSING);
34
  OLED_data(0x00);          // Horizontal Addressing mode
35
  OLED_data(LCD_DISP_ON);
36
  OLED_data(LCD_EON_ON);
37
  //sei();
38
}

Nochmals danke!

Gruß
Manu

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.