No artigo anterior aprendemos os primeiros passos com o MPLAB® Xpress Cloud-Based IDE e fizemos um Hello World com a placa MPLAB Xpress Evaluation Board. Continuaremos explorando os recursos dessa plataforma com o uso de algumas placas Click boards. Neste artigo vamos desenvolver uma aplicação para a OLED W click.
Click Boards
As Click Boards são placas criadas pela Mikroe com a finalidade de facilitar o uso de recursos externos através de um padrão de conexão chamado de mikroBUS. Com esse padrão é possível criar diversas placas de aplicações que possam ser usadas por diversas plataformas com configurações mínimas. O padrão mikroBUS é definido da seguinte forma:
A partir desse padrão foram criadas diversas Click boards:
A MPLAB Xpress Evaluation Board possui um conector padrão mikroBUS, o que permite explorar os recursos dessas fantásticas plaquinhas.
Durante nossos estudos com essa ferramenta iremos explorar algumas Click Boards.
OLED W Click
A OLED W Click possui um display OLED de matriz passiva 96 x 39 px monocromático branco, sendo uma tela brilhante com um excelente ângulo de visão e de baixo consumo de energia. Já possui integrado o controlador SSD1306 responsável pela controle do display e interface com microcontrolador. Esse controlador possui diversas funcionalidades para controle de contraste, exposição de imagem normal ou inversa, funções de rolagem vertical e horizontal, entre outras.
Seguindo o padrão mikroBUS, a OLED W Click pode se comunicar com o microcontrolador através SPI ou I2C.
O circuito da OLED W Click é apresentado a seguir:
O display OLED utilizado é o MI9639BO-W. Além disso, a placa possui o regulador linear AP7331-ADJ. É possível selecionar o tipo de comunicação entre SPI e I2C através dos jumpers J1, J2 e J3. Por padrão a placa vem com SPI, e nesse exemplo utilizaremos essa comunicação. A figura a seguir exibe os jumpers na placa:
Exemplo de aplicação
Nesse exemplo vamos desenvolver uma aplicação para a escrita no display usando o MPLAB® Xpress Cloud-Based IDE, o MCC e o compilador XC8. Será lido o valor no potenciômetro disponível na Xpress Board e exibido o valor da conversão AD no display.
Antes de desenvolver os arquivos de interface com o display, vamos mapear os pinos da Xpress board que serão utilizados nessa aplicação. Começando pelo pino que será usado para leitura de tensão presente no potenciômetro, verificamos no esquemático da placa que é o pino RA4, conforme exibido na figura a seguir:
Já pra interface com o display, iremos utilizar os seguintes pinos:
Tabela 1 – Pinos usados para interface com o display
|
OLED W Click |
Microcontrolador |
|
RST |
RB1 |
|
CS |
RB2 |
|
PWM |
RC7 |
|
SCK |
RB3/SCK1 |
|
MISO |
RB4/SDI1 |
Com o mapa de pinos que serão utilizados na aplicação em mãos, vamos agora passar para o desenvolvimento do código fonte.
Acesse o MPLAB Xpress IDE e crie um novo projeto. Após criado o projeto, deve-se abrir o MCC e fazer a configuração do sistema.
Caso você ainda possui dúvidas para criar um novo projeto ou nas configurações para a Xpress Board usando o MCC, é recomendável a leitura do artigo Primeiros passos com a MPLAB Xpress Evaluation Board.
Agora vamos configurar o comunicação SPI. Para isso selecione o módulo MSSP:
Com o módulo selecionado, vamos ajustar as configurações da seguinte forma:
Próximo passo é fazer a configuração do conversor AD. Para isso seleciono o módulo ADC:
Para essa aplicação, vamos configurar o ADC da seguinte forma:
Por último, vamos configurar os pinos da seguinte forma:
Pronto, agora é só dar o comando para o MCC gerar o código de configuração e drivers para os periféricos.
Para comunicação com o display, foi desenvolvida uma biblioteca simples para interface e escrita no display. O código a seguir apresenta as funções criadas para manipulação do display OLED usando o SSD1306:
/*
* File: SSD1306.c
* Author: fabio.souza@embarcados.com.br
*
* Created on 8/10/2016 1:14:10 AM UTC
* "Created in MPLAB Xpress"
*/
#include "SSD1306.h"
// SSD1306 microcontroller pins
#define SSD1306_CS CS_LAT
#define SSD1306_PWM PWM_LAT
#define SSD1306_RST RST_LAT
const uint8_t font[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0x00,0x00,0x00,0x07,0x00,0x07,0x00, // 'sp,!,"
0x14,0x7F,0x14,0x7F,0x14, // #
0x24,0x2A,0x7F,0x2A,0x12,0x23,0x13,0x08,0x64,0x62,0x36,0x49,0x56,0x20,0x50, // '$,%,&
0x00,0x08,0x07,0x03,0x00,0x00,0x1C,0x22,0x41,0x00,0x00,0x41,0x22,0x1C,0x00, // '',(,)
0x2A,0x1C,0x7F,0x1C,0x2A,0x08,0x08,0x3E,0x08,0x08,0x00,0x00,0x70,0x30,0x00, // '*,+,,
0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x60,0x60,0x00,0x20,0x10,0x08,0x04,0x02, // '-,.,/
0x3E,0x51,0x49,0x45,0x3E,0x00,0x42,0x7F,0x40,0x00,0x72,0x49,0x49,0x49,0x46, // '0,1,2
0x21,0x41,0x49,0x4D,0x33,0x18,0x14,0x12,0x7F,0x10,0x27,0x45,0x45,0x45,0x39, // '3,4,5
0x3C,0x4A,0x49,0x49,0x31,0x41,0x21,0x11,0x09,0x07,0x36,0x49,0x49,0x49,0x36, // '6,7,8
0x46,0x49,0x49,0x29,0x1E,0x00,0x00,0x14,0x00,0x00,0x00,0x40,0x34,0x00,0x00, // '9,:,;
0x00,0x08,0x14,0x22,0x41,0x14,0x14,0x14,0x14,0x14,0x00,0x41,0x22,0x14,0x08, // '<,=,>
0x02,0x01,0x59,0x09,0x06,0x3E,0x41,0x5D,0x59,0x4E, // '?,@
0x7C,0x12,0x11,0x12,0x7C, // 'A
0x7F,0x49,0x49,0x49,0x36,0x3E,0x41,0x41,0x41,0x22,0x7F,0x41,0x41,0x41,0x3E, // 'B,C,D
0x7F,0x49,0x49,0x49,0x41,0x7F,0x09,0x09,0x09,0x01,0x3E,0x41,0x41,0x51,0x73, // 'E,F,G
0x7F,0x08,0x08,0x08,0x7F,0x00,0x41,0x7F,0x41,0x00,0x20,0x40,0x41,0x3F,0x01, // 'H,I,J
0x7F,0x08,0x14,0x22,0x41,0x7F,0x40,0x40,0x40,0x40,0x7F,0x02,0x1C,0x02,0x7F, // 'K,L,M
0x7F,0x04,0x08,0x10,0x7F,0x3E,0x41,0x41,0x41,0x3E,0x7F,0x09,0x09,0x09,0x06, // 'N,O,P
0x3E,0x41,0x51,0x21,0x5E,0x7F,0x09,0x19,0x29,0x46,0x26,0x49,0x49,0x49,0x32, // 'Q,R,S
0x03,0x01,0x7F,0x01,0x03,0x3F,0x40,0x40,0x40,0x3F,0x1F,0x20,0x40,0x20,0x1F, // 'T,U,V
0x3F,0x40,0x38,0x40,0x3F,0x63,0x14,0x08,0x14,0x63,0x03,0x04,0x78,0x04,0x03, // 'W,X,Y
0x61,0x59,0x49,0x4D,0x43, // 'Z
0x00,0x7F,0x41,0x41,0x41,0x02,0x04,0x08,0x10,0x20, // '[,\
0x00,0x41,0x41,0x41,0x7F,0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40, // '],^,_
0x00,0x03,0x07,0x08,0x00,0x20,0x54,0x54,0x38,0x40,0x7F,0x28,0x44,0x44,0x38, // '`,a,b
0x38,0x44,0x44,0x44,0x28,0x38,0x44,0x44,0x28,0x7F,0x38,0x54,0x54,0x54,0x18, // 'c,d,e
0x00,0x08,0x7E,0x09,0x02,0x0C,0x52,0x52,0x4A,0x3C,0x7F,0x08,0x04,0x04,0x78, // 'f,g,h
0x00,0x44,0x7D,0x40,0x00,0x20,0x40,0x40,0x3D,0x00,0x7F,0x10,0x28,0x44,0x00, // 'i,j,k
0x00,0x41,0x7F,0x40,0x00,0x7C,0x04,0x78,0x04,0x78,0x7C,0x08,0x04,0x04,0x78, // 'l,m,n
0x38,0x44,0x44,0x44,0x38,0x7C,0x18,0x24,0x24,0x18,0x18,0x24,0x24,0x18,0x7C, // 'o,p,q
0x7C,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x24,0x04,0x04,0x3F,0x44,0x24, // 'r,s,t
0x3C,0x40,0x40,0x20,0x7C,0x1C,0x20,0x40,0x20,0x1C,0x3C,0x40,0x30,0x40,0x3C, // 'u,v,w
0x44,0x28,0x10,0x28,0x44,0x4C,0x50,0x50,0x50,0x3C,0x44,0x64,0x54,0x4C,0x44, // 'x,y,z
0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x41,0x36,0x08,0x00, // '{,|,}
0x02,0x01,0x02,0x04,0x02 // '~
};
uint8_t _row, _column; //curso position memory
void SSD1306_Cmd( unsigned char cmd){
SSD1306_CS = 0;
SSD1306_PWM = 0;
SPI_Write( cmd);
SSD1306_CS = 1;
}
void SSD1306_Data( unsigned char data){
SSD1306_CS = 0;
SSD1306_PWM = 1;
SPI_Write( data);
SSD1306_CS = 1;
}
void SetRowDisplay( uint8_t y)
{
_column = y;
y = 0xB0 | y;
SSD1306_Cmd( y);
}
void SetColumnDisplay( uint8_t x)
{
_row = x;
x*=5;
x += 32;
SSD1306_Cmd(( SSD1306_SETHIGHCOLUMN | (x >> 4))); // SET_HIGH_COLUMN
SSD1306_Cmd(( 0x0f & x)); // SET LOW_COLUMN
}
void SetContrastDisplay( unsigned char value)
{
SSD1306_Cmd( SSD1306_SETCONTRAST);
SSD1306_Cmd( value); // contrast from 1 to 256
}
void InitDisplay(void)
{
SSD1306_RST = 0;
__delay_ms(1000);
SSD1306_RST = 1;
__delay_ms(1000);
SSD1306_Cmd(SSD1306_DISPLAYOFF); //0xAE Set OLED Display Off
SSD1306_Cmd(SSD1306_SETDISPLAYCLOCKDIV); //0xD5 Set Display Clock Divide Ratio/Oscillator Frequency
SSD1306_Cmd(0x80);
SSD1306_Cmd(SSD1306_SETMULTIPLEX); //0xA8 Set Multiplex Ratio
SSD1306_Cmd(39);
SSD1306_Cmd(SSD1306_SETSEGMENTREMAP); //0xA1 Set Segment Remap Inv
SSD1306_Cmd(SSD1306_COMSCANDEC); //0xC8 Set COM Output Scan Inv
SSD1306_Cmd(SSD1306_SETSTARTLINE); //0x40 Set Display Start Line
SSD1306_Cmd(SSD1306_SETDISPLAYOFFSET); //0xD3 Set Display Offset
SSD1306_Cmd(0x00);
SSD1306_Cmd(SSD1306_CHARGEPUMP); //0x8D Set Charge Pump
SSD1306_Cmd(0x14); //0x14 Enable Charge Pump
SSD1306_Cmd(SSD1306_SETCOMPINS); //0xDA Set COM Pins Hardware Configuration
SSD1306_Cmd(0x12);
SSD1306_Cmd(SSD1306_SETCONTRAST); //0x81 Set Contrast Control
SSD1306_Cmd(0xAF);
SSD1306_Cmd(SSD1306_SETPRECHARGE); //0xD9 Set Pre-Charge Period
SSD1306_Cmd(0x25);
SSD1306_Cmd(SSD1306_SETVCOMDETECT); //0xDB Set VCOMH Deselect Level
SSD1306_Cmd(0x20);
SSD1306_Cmd(SSD1306_DISPLAYALLON_RESUME); //0xA4 Set Entire Display On/Off
SSD1306_Cmd(SSD1306_NORMALDISPLAY); //0xA6 Set Normal/Inverse Display
SSD1306_Cmd(SSD1306_DISPLAYON); //0xAF Set OLED Display On
}
void ClearDisplay(void)
{
uint8_t i,j;
for( i=0; i<5; i++) //rows
{
SetRowDisplay(i);
SetColumnDisplay(0);
for( j=0; j<96; j++) //column
SSD1306_Data( 0);
}
_row = 0; _column = 0;
SetRowDisplay(0);
SetColumnDisplay(0);
}
void PutcharDisplay(char c)
{
unsigned char i;
const unsigned char *p = &font[(c-' ')*5];
for( i=0; i<5; i++)
SSD1306_Data( *p++ << 1);
SSD1306_Data(0);
_row++; //colum ++
if (_row >= 16) { // column >= 16
_row = 0; //return to 0
SetColumnDisplay(0); //set column 0
_column++; //increments Row
if (_column >= 5) { // line >= 5
_column = 0; //return to 0
}
SetRowDisplay(_column); //se new row
}
}
Para a leitura do potenciômetro e exibição do valor de conversão AD no display foi desenvolvido o seguinte código:
/*
* File: main.c
* Author: fabio.souza@embarcados.com.br
*
* Created on 8/10/2016 1:13:50 AM UTC
* "Created in MPLAB Xpress"
*/
#include "mcc_generated_files/mcc.h"
#include "SSD1306.h"
extern const uint8_t font[];
void mainScreen(void);
void updateDisplay(unsigned int value);
/*
Main application
*/
void main(void)
{
//variables
bool inv = true;
unsigned int ADCValue;
// initialize the device
SYSTEM_Initialize();
InitDisplay();
ClearDisplay();
mainScreen();
while (1) {
ADCValue = ADCC_GetSingleConversion(POT);
updateDisplay(ADCValue);
printf("\r\n Valor ADC = %i ", ADCValue);
if(ADCValue>800){
SSD1306_Cmd(SSD1306_INVERTDISPLAY);
}
else{
SSD1306_Cmd(SSD1306_NORMALDISPLAY);
}
__delay_ms(1000);
}
}
void mainScreen(void){
SetRowDisplay(1);
SetColumnDisplay(3);
PutcharDisplay('E');
PutcharDisplay('M');
PutcharDisplay('B');
PutcharDisplay('A');
PutcharDisplay('R');
PutcharDisplay('C');
PutcharDisplay('A');
PutcharDisplay('D');
PutcharDisplay('O');
PutcharDisplay('S');
SetRowDisplay(3);
SetColumnDisplay(7);
PutcharDisplay('0');
PutcharDisplay('0');
PutcharDisplay('0');
PutcharDisplay('0');
}
void updateDisplay(unsigned int value){
SetRowDisplay(3);
SetColumnDisplay(7);
PutcharDisplay((value/1000) + 0x30);
PutcharDisplay((value%1000)/100 + 0x30);
PutcharDisplay((value%100)/10 + 0x30);
PutcharDisplay((value%10) + 0x30);
}
/**
End of File
*/
Resultado
Você pode acessar o código desse exemplo diretamente no MPLAB Xpress Cloud IDE. Assim você poderá navegar pelo código, alterar, compilar e carregar diretamente na sua MPLAB Xpress Board.
Acesse o manual da OLED W Click, aqui. Baixe diversos exemplos para essa Click Board na Libstock.
Ficou alguma dúvida? Deixe seu comentário.






















Belo post Fabio, parabens! Voce sabe quando estas plaquinhas vão chegar no Brasil? Encontrei apenas os sites estrangeiros com as plaquinhas por US$10!
Abraço
Olá Eron, infelizmente no Brasil não é fácil achar essas placas. Talvez seja mais fácil comprar de fora. Esse site possui algumas placas da mikroe: https://www.microgenios.com/?1.36,modulos-acessorios.html