segunda-feira, 3 de outubro de 2016

Inicialização do controlador de display OLED SSD1306.

        Dando sequencia aos posts sobre displays OLED, compartilho a seguir a inicialização destes displays baseados no controlador SSD1306.
        O controlador SSD1306 da Solomon Systech, é muito popular atualmente pois é usados em módulos OLED muito usados com o Arduino e similares. Estas módulos tem comumente resolução de 128x64 (máximo do controlador), mas também pode ter 64x32, 128x32, 64x48, etc. Variam de tamanho e cores (verde, amarelo e azul sendo o mais comum) e não possuem graduação de brilho, ou seja, ou o pixel está ligado ou não, sem meio termo. Podem ter interface I²C, SPI de 4 vias, SPI de 3 vias (pino D/C, data/command, susbstituído por mais um bit na comunicação), paralela de 8 bits 8080 ou 6800. A interface é definida por hardware via 3 pinos (BS0, BS1 e BS2).
        Como não sei que linguagem (C, assembler, python, etc.) de programação ou dispositivo (PIC, MSP430, etc.) você vai usar, preferi mostrar somente os passos de inicialização:

Observação: isto é um exemplo, que uso nos meus displays, assim consulte sempre a documentação dos mesmos e do controlador pois há parâmetros que podem variar assim como a sequência.

1
Aplica-se um pulso de RESET por no mínimo 3µs. Nos módulos com somente interface I²C, geralmente o RESET é feito via um circuito RC e o pino deste não está disponível.

Típico módulo OLED I²C. Note a ausência do pino RESET.
Típico módulo com interface SPI que pode usar 3 (somente CS) ou 4  (CS e D/C) sinais. Também pode usar I²C ajustando BS0 a BS2.
Módulo com interface paralela que também pode usar SPI e I²C. Note os resistores de 0R e a tabela para ajustar BS0 a BS2.

2
Após o RESET, envia-se o comando AEh (Set display OFF, Sleep mode).

3
Comando D5h (Set display clock divide ratio/oscillator frequency) seguido com o valor 80h (clock divide ratio=1).

4
Comando A8h (Set multiplex ratio) seguido com o valor 3Fh (64MUX).

5
Comando D3h (Set display offset) seguido com o valor 00h (display offset=0).

6
Comando 40h (Set display RAM display start line) + 00h (display RAM display start line=0).

7
Comando 8Dh (Charge pump setting) seguido com o valor 14h (Charge pump enabled). O charge pump deve ser habilitado antes de ligar o display (comando AFh, display ON).

8
Comando A1h (Set segment re-map, column address 127 is mapped to SEG0). Geralmente o mapeamento é feito assim, mas pode variar dependendo do módulo.

9
Comando C8h (Set COM output scan direction, remapped mode scan from COM[n-1] to COM0). Também é geralmente feito assim, mas pode variar dependendo do módulo.

10
Comando DAh (Set COM pins hardware configuration) seguido do valor 12h (Disable COM Left/Right remap & alternate COM pin configuration). Normalmente, usa-se o modo alternado, mas pode ser usado sequencial no caso do display de 128x32 (sequential COM pin configuration).

11
Comando D6h (Set zoom in) seguido do valor 00h (Vertical zoom disabled). Comando opcional, uso pois alguns microcontroladores tem pouca memória para guardar os bitmaps dos caracteres, assim consigo dobrar a altura dos mesmos sem consumir mais memória.

12
Comando 81h (Set contrast control) seguido do valor 28h (Contrast=40). O valor de contraste, ou brilho do display, varia de 0 a 255. 40 é um brilho razoável para não consumir muita energia, assim o display OLED fica com um consumo semelhante a um LCD com backlight de LED.

13
Comando D9h (Set pre-charge period) seguido do valor F1 (Phase 2 period=15DCLK & Phase 1 period=1DCLK).

14
Comando DBh (Set VCOMH deselect level) seguido do valor 20h (VCOMH deselect level=0.77*Vcc).

15
Comando 20h (Set memory addressing mode) seguido do valor 01h (Vertical addressing mode). Há 3 modos: horizontal, vertical e page address. Uso o vertical por ser mais fácil desenhar os bitmaps dos caracteres no display.

16
Comando A4h (Resume to RAM content display). O controlador mostra no display o conteúdo da RAM. Pode-se usar o comando A5h (Entire display ON) para testar o módulo.

17
Comando A6h (Set normal display). Cada bit 1 da RAM é um pixel aceso. Pode-se usar o comando A7h (Inverse display) onde cada bit 0 é um pixel aceso.

18
Comando 22h (Set page start and end address) seguido do valores 00h (start page=0) e 07h (end page=7). Opcional na inicialização, uso para apagar o conteúdo da memória RAM que inicialmente é aleatório.

19
Comando 21h (Set column start and end address) seguido do valores 00h (start column=0) e 7Fh (end column=127). Também opcional na inicialização, uso para apagar o conteúdo da memória RAM.

20
Opcional. Envia 1024 bytes de dados (00h) para limpar a memória RAM.

21
Por último, comando AFh (Set display ON) para ligar o maldito. Se tudo estiver funcionando, neste momento, o display estará sem um único pixel aceso.



Enviando os bitmaps dos caracteres:

        Há várias maneiras de desenhar um caractere no display, a que uso constituí de 4 variáveis e uma rotina de envio:
  • ASCII_Data - Caractere a ser desenhado de acordo com a tabela de bitmaps (Exemplo "T");
  • ASCII_Data_XOR_Mask - Máscara para inverter os pixels (o que é aceso fica apagado e vice-versa);
  • Char_Column - Coluna do caractere no display (0 a 15 com fonte 16x8);
  • Char_Row - Linha do caractere no display (0 a 3 com fonte 16x8);
  • Send_ASCII - Rotina que envia o bitmap do caractere contido em ASCII_Data nas posições Char_Column  e Char_Row. Esta rotina também incrementa automaticamente Char_Column e Char_Row para facilitar o envio de textos.
        Para tudo acontecer, primeiramente deve haver obviamente uma tabela contendo os bitmaps. Usei uma com apenas 64 caracteres para não ocupar muita memória e serve para quase tudo.
Bitmaps. Para ocupar menos memória, só considerei as letras maiúsculas, números e alguns caracteres. Também substituí alguns por outros mais funcionais.
          Antes de chamar a rotina de envio, define-se onde o caractere vai ser desenhado através das variáveis Char_Column e Char_Row. A rotina define a janela de operação através dos comandos 22h (set page) e 21h (set column) com a seguinte fórmula:

Initial page = Char_Row x 2;
End page = (Char_Row x 2) + 1;
Initial column = Char_Column x 8;
End column = (Char_Column x 8) + 7;

        Após definir a janela, envia-se os bytes referentes ao bitmap do caractere. Para esta fonte 16x8, envio 2 bytes em branco (1 coluna), 12 bytes do bitmap e mais 2 bytes em branco (mais 1 coluna).
        O modo de envio é o vertical:
Modo de envio vertical.
Envio dos dados da tabela.
     Após o envio do bitmap, a rotina Send_ASCII auto-incrementa Char_Column e Char_Row, assim pode-se enviar um texto definindo a posição uma única vez.
























Nenhum comentário:

Postar um comentário